Patrick Salazar
Patrick Salazar

Reputation: 21

How do you enable GCP APIs through the python client library?

I am trying to create a python function that will enable the Service APIs needed for a GCP project. I believe that the API call will go to the "serviceusage" API and use the "services.enable" or "services.batchEnable" method. I can't figure out how to structure the query correctly.

https://cloud.google.com/service-usage/docs/reference/rest/v1/services/enable

I have been able to use the GCP Python client library to automate most functions for project creation, but not this. I have used code directly from GCP documentation, but there is very little for this particular method

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

credentials = GoogleCredentials.get_application_default()

project = 'projects/964030760997'  # TODO: Update placeholder value.

service = discovery.build('serviceusage', 'v1', credentials=credentials)
request = service.projects().services.list(project=project)
response = request.execute()


pprint(service)

this is the response i get:

Traceback (most recent call last):
  File "enable_apis.py", line 29, in <module>
    request = service.services().services.list(project=project)
AttributeError: 'Resource' object has no attribute 'services'

Upvotes: 2

Views: 3356

Answers (3)

Vincent Yin
Vincent Yin

Reputation: 1716

The answers so far all depend on the prerequisite that the serviceusage.googleapis.com API is already enabled; otherwise, the call to request.execute() would fail with an error like this (trying to enable the firestore.googleapis.com API as a random example):

googleapiclient.errors.HttpError: 

<HttpError 403 when requesting 
https://serviceusage.googleapis.com/v1/projects/my-project-id-xyz/services/firestore.googleapis.com?alt=json 

returned "Service Usage API has not been used in project 11112222333 before or it is disabled. 

Enable it by visiting 
https://console.developers.google.com/apis/api/serviceusage.googleapis.com/overview?project=11112222333 
then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.". 

Details: "[
{
'@type': 'type.googleapis.com/google.rpc.Help', 
'links': [{
'description': 'Google developers console API activation', 
'url': 'https://console.developers.google.com/apis/api/serviceusage.googleapis.com/overview?project=11112222333'
}]},
{'@type': 'type.googleapis.com/google.rpc.ErrorInfo', 
'reason': 'SERVICE_DISABLED', 
'domain': 'googleapis.com', 
'metadata': {'service': 'serviceusage.googleapis.com', 'consumer': 'projects/11112222333'}
}
]">

So, before executing the Python script suggested by other people's (excellent) answers, you need to first (manually?) enable the serviceusage.googleapis.com API via the GCP Console or CLI:

$ gcloud services enable serviceusage.googleapis.com

A corollary is the following. Suppose we disable serviceusage.googleapis.com:

$ gcloud services disable serviceusage.googleapis.com
Operation "operations/acat.p17-77456371124-caf0a1ab-0047-43cd-8a7d-d8492ba0d84b" finished successfully.

Then we can still successfully enable, say, firestore.googleapis.com as long as we use gcloud CLI (or GCP console):

$ gcloud services enable firestore.googleapis.com
Operation "operations/acf.p2-77456371124-10eee72a-948b-493a-aa99-07a9ad3e8769" finished successfully.

But trying to enable it via the Python script in other people's answers posted so far will result in HttpError 403 as I explained above. Therefore, the gcloud CLI (or GCP console) must be using a different mechanism to somehow query the status of the target API.

Upvotes: 1

Jatin
Jatin

Reputation: 111

import googleapiclient.discovery
from oauth2client.client import GoogleCredentials


def enable_api(project_id):
    """Enables the GCP service APIs

    Args:
        project_id : The ID of the project where the service status is being checked
    """
    storage_api = "storagetransfer.googleapis.com"
    cloud_resource_manager_api = "cloudresourcemanager.googleapis.com"

    credentials = GoogleCredentials.get_application_default()

    # Create a ServiceUsage client
    service_usage_client = googleapiclient.discovery.build("serviceusage", "v1", credentials=credentials)

    # Get the Storage Transfer API service status in the project
    storage_api_status = get_service_api_status(
        service_usage_client, storage_api, project_id
    )

    # Enable the Storage Transfer API service in the project
    if storage_api_status != "ENABLED":
        service_usage_client.services().enable(
            name=f"projects/{project_id}/services/{storage_api}"
        ).execute()

        print(f"Enabled Storage Transfer API in project : {project_id}")

    # Get the Cloud Resource Manager API service status in project
    cloud_resource_manager_api_status = get_service_api_status(
        service_usage_client, cloud_resource_manager_api, project_id
    )

    # Enable the Cloud Resource Manager API in the project
    if cloud_resource_manager_api_status != "ENABLED":
        service_usage_client.services().enable(
            name=f"projects/{project_id}/services/{cloud_resource_manager_api}"
        ).execute()

        print(f"Enabled Cloud Resource Manager API in project : {project_id}")

def get_service_api_status(client, api_name, project_id):
    """
    Get the current status of a GCP service API

    Args:
        client : service usage client
        api_name : API name whose status is to be returned
        project_id : The ID of the project where the service status is being checked

    Returns:
        string : service api status
    """
    response = (
        client.services()
        .get(name=f"projects/{project_id}/services/{api_name}")
        .execute()
    )
    return response["state"]


project_id = "<SET THE PROJECT ID WHERE THE SERVICE API WILL BE ENABLED>"
main(project_id)

Upvotes: 1

John Hanley
John Hanley

Reputation: 81464

You are referencing the wrong documentation. Here is the link for Service Usage API:

Google Service Usage API

Here is an example that I wrote. Note. This code does not process the nextPageToken so it only prints the first 50 services. Add code to loop.

from googleapiclient import discovery
from oauth2client.client import GoogleCredentials

credentials = GoogleCredentials.get_application_default()

project = 'projects/myproject'

service = discovery.build('serviceusage', 'v1', credentials=credentials)
request = service.services().list(parent=project)

response = ''

try:
    response = request.execute()
except Exception as e:
    print(e)
    exit(1)

# FIX - This code does not process the nextPageToken
# next = response.get('nextPageToken')

services = response.get('services')

for index in range(len(services)):
    item = services[index]

    name = item['config']['name']
    state = item['state']

    print("%-50s %s" % (name, state))

The output of this code looks similar to this:

abusiveexperiencereport.googleapis.com             DISABLED
acceleratedmobilepageurl.googleapis.com            DISABLED
accessapproval.googleapis.com                      DISABLED
accesscontextmanager.googleapis.com                DISABLED
actions.googleapis.com                             DISABLED
adexchangebuyer-json.googleapis.com                DISABLED
adexchangebuyer.googleapis.com                     DISABLED
adexchangeseller.googleapis.com                    DISABLED
adexperiencereport.googleapis.com                  DISABLED
admin.googleapis.com                               ENABLED
adsense.googleapis.com                             DISABLED

Upvotes: 6

Related Questions