【问题标题】:How to turn on/off CloudSQL instances using Python3如何使用 Python3 打开/关闭 CloudSQL 实例
【发布时间】:2020-01-17 22:50:14
【问题描述】:

我正在尝试使用 Python 脚本打开/关闭 GoogleCloud 中的 CloudSQL 实例。我终于找到了一种方法,在 Shell 中使用 GoogleCloudAPI:

### shell script
ACCESS_TOKEN="$(gcloud auth print-access-token)"
ACTIVATION_POLICY="ALWAYS/NEVER" # Use 'ALWAYS' to turn on, 'NEVER' to turn off
curl --header "Authorization: Bearer ${ACCESS_TOKEN}"  --header 'Content-Type: application/json' --data '{"settings" : {"activationPolicy" : "${ACTIVATION_POLICY}"}}' -X PATCH https://www.googleapis.com/sql/v1beta4/projects/${PROJECT_ID}/instances/${INSTANCE_ID}

所以,太好了,问题解决了……除了我不能在我运行脚本的机器上使用“gcloud auth print-access-token”,所以什么也解决不了。我发现question from 2017 也在尝试使用 Python 生成这个“访问令牌”,但显然也不起作用。

我需要能够使用 Python 本身生成这个“访问令牌”。我一直在谷歌的文档中四处寻找,但我仍然没有找到与此相关的任何内容,我发现最接近的是使用 oauth2 和 googleapiclient 来获取正在运行的实例列表,但似乎无法更改激活策略那里:

### python3 script
from google.oauth2 import service_account
import googleapiclient.discovery
SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'
credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)
sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta4', credentials=credentials)
response = sqladmin.instances().get(project=PROJECT_ID, instance=INSTANCE_ID).execute()

文档并没有明确说明如何使用这两种工具来关闭 CloudSQL 实例,或者至少没有我能找到的方法。上面的代码返回一个 JSON 文件,我可以在设置下看到“activationPolicy”。不过,我找不到“改变它”的方法。

设法遵循@norbjd 的建议并找到一个“补丁”方法,并为我的凭据授予“SQL Admin”权限,因此它现在可以使用 sqladmin API。尝试使用以下代码对其进行修补:

instance = sqladmin.instances().patch(project=PROJECT_ID, instance=INSTANCE_ID)
instance.data = {"settings" : {"activationPolicy" : "NEVER"}} #also tried with it in a string, like this: instance.data = {"settings" : {"activationPolicy" : "NEVER"}}
instance.headers['Content-Type'] = 'application/json'
instance.execute()

考虑到 instance.data 在此之前不存在,但 instance.headers 存在:

{'accept': 'application/json', 'accept-encoding': 'gzip, deflate', 'user-agent': '(gzip)', 'x-goog-api-client': 'gdcl/1.7.11 gl-python/3.6.9'}

然而,在执行之后,似乎什么都没有发生。它并没有改变实际的activationPolicy。

【问题讨论】:

  • 我相信您可以像在 cURL 请求中一样运行sqladmin.instances().get(<your_instance>).patch(...)。 API 客户端只是封装了对 HTTP API 的调用,所以它应该可以工作。
  • @norbjd 使用您的线路并用它更新了问题。事实上,我能够检索我想要使用的实例的特定对象,除了你对(...).patch(...) 的建议不起作用:AttributeError: 'HttpRequest' object has no attribute 'patch'。我一直在尝试找到解释它的文档,但仍然无法在任何地方找到它。
  • 好吧,设法用instance = sqladmin.instances().patch(project=PROJECT_ID, instance=INSTANCE_ID) 修补它,但是一旦我尝试做instance.execute() 它说客户端无权提出这个请求:raise HttpError(resp, content, uri=self.uri) googleapiclient.errors.HttpError: <HttpError 403 when requesting https://sqladmin.googleapis.com/sql/v1beta4/projects/PROJECT_ID/instances/INSTANCE_ID?alt=json returned "The client is not authorized to make this request.">(即使没有添加任何东西标题/数据)[也更新了问题)

标签: python python-3.x google-api google-cloud-sql google-oauth


【解决方案1】:

最后,使用 ACCESS_TOKEN 并使用 requests 模块发出 Python 请求解决了问题。如果您在生成凭据后尝试从凭据中获取 ACCESS_TOKEN,您将不会获得任何凭据,但如果您实际上将凭据与 googleapiclient.discovery 一起使用,则会使用有效的访问令牌更新该对象,然后可以在 Python 请求中使用,如下:

from google.oauth2 import service_account
import googleapiclient.discovery
import json
import requests

PROJECT_ID = '{PROJECT_ID_HERE}'
INSTANCE_ID = '{INSTANCE_ID_HERE}'

SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'
credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta4', credentials=credentials)
response = sqladmin.instances().get(project=PROJECT_ID, instance=INSTANCE_ID).execute()
print(json.dumps(response))

access_token = credentials.token # Now that the credentials were used, they have a valid access_token associated with them!

activation_policy = 'NEVER' # or 'ALWAYS'

url = "https://www.googleapis.com/sql/v1beta4/projects/{PROJECT_ID}/instances/{INSTANCE_ID}".format(PROJECT_ID=PROJECT_ID, INSTANCE_ID=INSTANCE_ID)
header = {
    "Authorization" : "Bearer {}".format(access_token), 
    "Content-Type" : "application/json"
}
data = {
    "settings" : {
        "activationPolicy" : activation_policy
    }
}
response = requests.patch(url, headers=header, data=json.dumps(data))
print(response.text)

在尝试检索 ACCESS_TOKEN 之前,只需要实际使用凭据即可

【讨论】:

    猜你喜欢
    • 2015-09-07
    • 1970-01-01
    • 2021-10-07
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多