Используя Python, я хотел бы получить список всех моих кластеров Dataproc в Google Cloud.

У меня есть учетные данные учетной записи службы, которые хранятся в файле ключей JSON, местоположение которого указано в env var GOOGLE_APPLICATION_CREDENTIALS. Вот код, который у меня есть:

import os
import googleapiclient.discovery
from oauth2client.client import GoogleCredentials


def build_dataproc_service(credentials):
    return googleapiclient.discovery.build("dataproc", "v1", credentials=credentials)


def list_clusters():
    credentials = GoogleCredentials.get_application_default()
    dataproc = build_dataproc_service(credentials)
    clusters = dataproc.projects().regions().clusters().list(projectId="my-project", region="REGION").execute()
    return clusters


if __name__ == "__main__":
    list_clusters()

Как видите, я жестко закодировал идентификатор проекта ("my-project"). Учитывая, что projectId существует в файле ключей JSON, я надеялся, что смогу получить его, просто запросив свойство объекта credentials, но такого свойства не существует. ProjectId действительно существует, встроенный в строковое свойство credentials._service_account_email, но его извлечение оттуда неуклюже и кажется неправильным.

Я предполагаю, что должен быть лучший способ. Как я могу получить идентификатор проекта, в котором находится учетная запись службы?

Обратите внимание, что изначально я намереваюсь запустить этот код в док-контейнере на экземпляре Google Compute Engine, однако однажды в будущем я, возможно, захочу запустить на GKE. Не уверен, влияет ли это на ответ или нет.

2
jamiet 3 Май 2019 в 00:29

3 ответа

Лучший ответ

Формальный способ думать об этом заключается в том, что, хотя projectId иногда является свойством учетной записи службы , projectId обычно не является свойством долгоживущего удостоверения . Например, подумайте о своих установленных в автономном режиме личных учетных данных, которые вы используете с gcloud CLI, если таковой имеется, связанный с вашей учетной записью / адресом электронной почты Google. Этот идентификатор электронной почты не находится в каком-либо облачном проекте, и, тем не менее, может использоваться для получения объекта GoogleCredential.

Технически, если вы хотите сделать это «должным образом», вам понадобится главная учетная запись службы, которая имеет разрешения на GET описания учетной записи службы во всех проектах, которые содержат действительные учетные записи службы, которые вы планируете использовать, а затем вызовите IAM projects.serviceAccounts.get API на сайте службы адрес электронной почты аккаунта, а не на «учетных» объектах. Ответы там могут идентифицировать идентификатор проекта, в котором находится учетная запись службы. Это эквивалентно команде gcloud:

gcloud iam service-accounts describe my-service-account@projectid.iam.gserviceaccount.com

Тем не менее, как говорит Даганг, в долгосрочной перспективе часто возникает обратный эффект, чтобы начать работу в предположении, что учетная запись службы будет использоваться только для операций над проектами, в которых она находится. В частности, хотя ресурсы service account живут внутри проектов, они часто используются в межпроектном режиме. Один общий шаблон работы - это использование одного проекта GCP для управления большим количеством учетных записей служб, которым затем предоставляется различный детальный доступ к ресурсам в других проектах GCP.

4
Dennis Huo 2 Май 2019 в 22:58

Я не думаю, что код клиента должен извлекать идентификатор проекта из GoogleCredentials. Посмотрите этот фрагмент кода в документе API.

from googleapiclient.discovery import build
from oauth2client.client import GoogleCredentials

credentials = GoogleCredentials.get_application_default()
service = build('compute', 'v1', credentials=credentials)

PROJECT = 'bamboo-machine-422'
ZONE = 'us-central1-a'
request = service.instances().list(project=PROJECT, zone=ZONE)
response = request.execute()

print(response)

Возможно, вы сможете определить идентификатор проекта из credentials._service_account_email, но это ненадежно. Кроме того, учетная запись службы в проекте A не связана с проектом, она также может иметь разрешения для других проектов.

3
Dagang 2 Май 2019 в 22:23

Учетные данные учетной записи службы .json содержат идентификатор проекта, так что вы можете сделать:

# If this is running in a cloud function, then GCP_PROJECT should be defined
if 'GCP_PROJECT' in os.environ:
    project_id = os.environ['GCP_PROJECT']

# else if this is running locally then GOOGLE_APPLICATION_CREDENTIALS should be defined
elif 'GOOGLE_APPLICATION_CREDENTIALS' in os.environ:
    with open(os.environ['GOOGLE_APPLICATION_CREDENTIALS'], 'r') as fp:
        credentials = json.load(fp)
    project_id = credentials['project_id']
else:
    raise Exception('Failed to determine project_id')
0
driedler 15 Янв 2020 в 20:47