【问题标题】:How to programmatically get current project id in Google cloud run api如何以编程方式在谷歌云运行 api 中获取当前项目 ID
【发布时间】:2020-04-12 11:10:12
【问题描述】:

我有一个容器化并在云运行中运行的 API。如何获取正在执行云运行的当前项目 ID?我试过了:

  • 我在日志中的 textpayload 中看到它,但我不确定如何在 post 函数中读取 textpayload?我收到的 pub sub 消息缺少此信息。
  • 我已经阅读了查询元数据 api 的内容,但是关于如何从 api 中再次执行此操作还不是很清楚。有链接吗?

还有其他方法吗?

编辑:

在下面的一些 cmets 之后,我最终在 Cloud Run 中运行我的 .net API 中的这段代码。

        private string GetProjectid()
        {
            var projectid = string.Empty;
            try {
                var PATH = "http://metadata.google.internal/computeMetadata/v1/project/project-id";
                using (var client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Add("Metadata-Flavor", "Google");
                    projectid = client.GetStringAsync(PATH).Result.ToString();
                }

                Console.WriteLine("PROJECT: " + projectid);
            }
            catch (Exception ex) {
                Console.WriteLine(ex.Message + " --- " + ex.ToString());
            }
            return projectid;
        }

更新,它有效。我的构建推送失败了,我没有看到。感谢大家。

【问题讨论】:

  • http://metadata.google.internal/computeMetadata/v1/project/project-id发出HTTP GET请求
  • 我得到(响应状态码不表示成功:403(尝试执行此操作时禁止。
  • 您从哪里提出请求?您的 Compute Engine 实例启用了哪些范围?您添加了哪些 HTTP 标头?请参阅 Steren 向元数据服务器发出请求的答案,其中必须包含 Metadata-Flavor:Google 标头。
  • 我没有!如何获得 ACCESS_TOKEN?
  • 我更改了我的评论,因为元数据服务器仅在您的代码在 Compute Engine 实例中运行且不需要访问令牌时才可用。如果您在其他地方(例如 Web 浏览器)运行代码,则无法调用此端点。使用有关如何调用此端点的确切详细信息编辑您的问题并包含错误消息。

标签: google-cloud-platform google-cloud-pubsub google-cloud-run


【解决方案1】:
  1. 我按照教程Using Pub/Sub with Cloud Run tutorial

  2. 我在requirements.txt 中添加了模块gcloud

       Flask==1.1.1
       pytest==5.3.0; python_version > "3.0"
       pytest==4.6.6; python_version < "3.0"
       gunicorn==19.9.0
       gcloud
    
  3. 我在 main.py 中更改了index 函数:

       def index():
         envelope = request.get_json()
         if not envelope:
            msg = 'no Pub/Sub message received'
            print(f'error: {msg}')
            return f'Bad Request: {msg}', 400
         if not isinstance(envelope, dict) or 'message' not in envelope:
            msg = 'invalid Pub/Sub message format'
            print(f'error: {msg}')
            return f'Bad Request: {msg}', 400
         pubsub_message = envelope['message']
         name = 'World'
         if isinstance(pubsub_message, dict) and 'data' in pubsub_message:
            name = base64.b64decode(pubsub_message['data']).decode('utf-8').strip()
         print(f'Hello {name}!')
    
         #code added 
         from gcloud import pubsub  # Or whichever service you need
         client = pubsub.Client()
         print('This is the project {}'.format(client.project))
    
         # Flush the stdout to avoid log buffering.
         sys.stdout.flush()
         return ('', 204)
    
    1. 我检查了日志:

        Hello (pubsub message).
        This is the project my-project-id.
      

【讨论】:

    【解决方案2】:

    您可以通过向 http://metadata.google.internal/computeMetadata/v1/project/project-id 发送带有 Metadata-Flavor:Google 标头的 GET 请求来获取项目 ID。

    this documentation

    以 Node.js 为例:

    index.js:

    const express = require('express');
    const axios = require('axios');
    const app = express();
    
    const axiosInstance = axios.create({
      baseURL: 'http://metadata.google.internal/',
      timeout: 1000,
      headers: {'Metadata-Flavor': 'Google'}
    });
    
    app.get('/', (req, res) => {
      let path = req.query.path || 'computeMetadata/v1/project/project-id';
      axiosInstance.get(path).then(response => {
        console.log(response.status)
        console.log(response.data);
        res.send(response.data);
      });
    });
    
    const port = process.env.PORT || 8080;
    app.listen(port, () => {
      console.log('Hello world listening on port', port);
    });
    

    package.json:

    {
      "name": "metadata",
      "version": "1.0.0",
      "description": "Metadata server",
      "main": "app.js",
      "scripts": {
        "start": "node index.js"
      },
      "author": "",
      "license": "Apache-2.0",
      "dependencies": {
        "axios": "^0.18.0",
        "express": "^4.16.4"
      }
    }
    

    【讨论】:

    • 我正在尝试同样的事情,但没有运气。尝试 { var PATH = "metadata.google.internal/computeMetadata/v1/project/project-id";使用 (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("Metadata-Flavor", "Google"); projectid = client.GetStringAsync(PATH).Result.ToString(); } Console.WriteLine("项目:" + projectid); }
    【解决方案3】:

    应该可以使用Google.Api.Gax (https://github.com/googleapis/gax-dotnet/blob/master/Google.Api.Gax/Platform.cs) 中的Platform 类。 Google.Api.Gax 包通常作为其他 Google .NET 包的依赖项安装,例如 Google.Cloud.Storage.V1

    var projectId = Google.Api.Gax.Platform.Instance().ProjectId;
    

    在GAE平台上,也可以简单查看环境变量GOOGLE_CLOUD_PROJECTGCLOUD_PROJECT

    var projectId = Environment.GetEnvironmentVariable("GOOGLE_CLOUD_PROJECT")
                 ?? Environment.GetEnvironmentVariable("GCLOUD_PROJECT");
    

    【讨论】:

      【解决方案4】:

      这是获取当前项目 ID 的 Java 代码的 sn-p:

                  String url = "http://metadata.google.internal/computeMetadata/v1/project/project-id";
                  HttpURLConnection conn = (HttpURLConnection)(new URL(url).openConnection());
                  conn.setRequestProperty("Metadata-Flavor", "Google");
                  try {
                      InputStream in = conn.getInputStream();
                      projectId = new String(in.readAllBytes(), StandardCharsets.UTF_8);
                  } finally {
                      conn.disconnect();
                  }               
      

      【讨论】:

        【解决方案5】:

        其他人已经展示了如何通过 HTTP API 获取项目名称,但在我看来,这里更容易、更简单、更高效的做法是将项目 ID 设置为 run-time environment variable。为此,在部署函数时:

        gcloud functions deploy myFunction --set-env-vars PROJECT_ID=my-project-name
        

        然后您可以使用以下代码访问它:

        exports.myFunction = (req, res) => {
          console.log(process.env.PROJECT_ID);
        }
        

        您只需为部署函数的每个环境设置适当的值。这有一个非常小的缺点,即每个环境都需要一个一次性的命令行参数,而不让你的函数依赖于成功验证和解析 API 响应的主要优点。这也提供了代码可移植性,因为几乎所有托管环境都支持环境变量,包括您的本地开发环境。

        【讨论】:

        • 一些较旧的运行时(例如 nodejs8)会自动填充 process.env. GCP_PROJECT,但在撰写本文时已被弃用一段时间
        【解决方案6】:

        @Steren 在 python 中的回答

        import os
        
        def get_project_id():
            # In python 3.7, this works
            project_id = os.getenv("GCP_PROJECT")
        
            if not project_id:  # > python37
                # Only works on runtime.
                import urllib.request
        
                url = "http://metadata.google.internal/computeMetadata/v1/project/project-id"
                req = urllib.request.Request(url)
                req.add_header("Metadata-Flavor", "Google")
                project_id = urllib.request.urlopen(req).read().decode()
        
            if not project_id:  # Running locally
                with open(os.environ["GOOGLE_APPLICATION_CREDENTIALS"], "r") as fp:
                    credentials = json.load(fp)
                project_id = credentials["project_id"]
        
            if not project_id:
                raise ValueError("Could not get a value for PROJECT_ID")
        
            return project_id
        

        【讨论】:

          猜你喜欢
          • 2019-10-14
          • 1970-01-01
          • 2020-08-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多