如何使用Python3打开/关闭CloudSQL实例

如何使用Python3打开/关闭CloudSQL实例,python,python-3.x,google-api,google-cloud-sql,google-oauth,Python,Python 3.x,Google Api,Google Cloud Sql,Google Oauth,我正在尝试使用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 "Authoriza

我正在尝试使用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”,因此无法解决任何问题。我发现了一个尝试使用Python生成这个“访问令牌”的方法,这显然也不起作用

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

### 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'}

然而,在执行死刑之后,似乎什么也没有发生。它没有改变实际的激活策略。

最后,使用ACCESS\u令牌并使用requests模块发出Python请求解决了问题。如果您试图在生成凭据之后从凭据中获取访问令牌,您将不会获得任何令牌,但如果您实际将凭据用于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)

在尝试检索访问令牌之前,只需实际使用凭据,我相信您可以像在cURL请求中那样运行
sqladmin.instances().get().patch(…)
。API客户端只是包装了对HTTP API的调用,这样它就可以工作了。@norbjd使用了您的行并用它更新了问题。事实上,我能够检索到我想要使用的实例的特定对象,除了您建议的
(…)。补丁(…)
不起作用:
AttributeError:'HttpRequest'对象没有属性“patch”
。我一直在试图找到解释它的文档,但仍然找不到它。好的,我设法用
instance=sqladmin.instances().patch(project=project\u ID,instance=instance\u ID)
对它进行了修补,但一旦我尝试执行
instance.execute()
它表示客户端无权发出此请求:
引发HttpError(resp,content,uri=self.uri)googleapiclient.errors.HttpError:
(即使没有向标题/数据添加任何内容)[也更新了此问题)