def get_all_apis(self): """Gets all APIs that can be enabled (based on caller's permissions). Returns: list: A list of ManagedService resource dicts. https://cloud.google.com/service-management/reference/rest/v1/services#ManagedService { "serviceName": string, "producerProjectId": string, } Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ try: paged_results = self.repository.services.list( max_results=self.DEFAULT_MAX_RESULTS) flattened_results = api_helpers.flatten_list_results( paged_results, 'services') except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError('', e) LOGGER.exception(api_exception) raise api_exception LOGGER.debug('Getting all visible APIs, flattened_results = %s', flattened_results) return flattened_results
def list_instances(self, project_id, service_id, version_id): """Lists instances of a given service and version. Args: project_id (str): The id of the project. service_id (str): The id of the service to query. version_id (str): The id of the version to query. Returns: list: A list of Instance resource dicts for a given Version. """ try: paged_results = self.repository.version_instances.list( project_id, services_id=service_id, versions_id=version_id) flattened_results = api_helpers.flatten_list_results( paged_results, 'instances') LOGGER.debug('Listing instances of a given service and version,' ' project_id = %s, service_id = %s, version_id = %s,' ' flattened_results = %s', project_id, service_id, version_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: if e.resp.status == 501: LOGGER.debug(e) return [] if _is_status_not_found(e): return [] raise api_errors.ApiExecutionError(project_id, e)
def get_curated_roles(self, parent=None): """Get information about organization roles Args: parent (str): An optional parent ID to query. If unset, defaults to returning the list of curated roles in GCP. Returns: list: The response of retrieving the curated roles. Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ try: paged_results = self.repository.roles.list(parent=parent, view='FULL') flattened_results = api_helpers.flatten_list_results( paged_results, 'roles') LOGGER.debug( 'Getting information about organization roles,' ' parent = %s, flattened_results = %s', parent, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'project_roles', e, 'parent', parent) LOGGER.exception(api_exception) raise api_exception
def get_produced_apis(self, project_id): """Gets the APIs produced by a project. Args: project_id (str): The project id for a GCP project. Returns: list: A list of ManagedService resource dicts. https://cloud.google.com/service-management/reference/rest/v1/services#ManagedService { "serviceName": string, "producerProjectId": string, } Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ try: paged_results = self.repository.services.list( producerProjectId=project_id, max_results=self.DEFAULT_MAX_RESULTS) flattened_results = api_helpers.flatten_list_results( paged_results, 'services') except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'name', e, 'project_id', project_id) LOGGER.exception(api_exception) raise api_exception LOGGER.debug( 'Getting the APIs produced by a project, project_id = %s, ' 'flattened_results = %s', project_id, flattened_results) return flattened_results
def get_service_accounts(self, project_id): """Get Service Accounts associated with a project. Args: project_id (str): The project ID to get Service Accounts for. Returns: list: List of service accounts associated with the project. Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ name = self.repository.projects_serviceaccounts.get_name(project_id) try: paged_results = self.repository.projects_serviceaccounts.list(name) flattened_results = api_helpers.flatten_list_results( paged_results, 'accounts') LOGGER.debug( 'Getting service accounts associated with a project,' ' project_id = %s, flattened_results = %s', project_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'serviceAccounts', e, 'name', name) LOGGER.exception(api_exception) raise api_exception
def get_organization_roles(self, org_id): """Get information about custom organization roles. Args: org_id (str): The id of the organization. Returns: list: The response of retrieving the organization roles. Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ name = self.repository.organizations_roles.get_name(org_id) try: paged_results = self.repository.organizations_roles.list( name, view='FULL') flattened_results = api_helpers.flatten_list_results( paged_results, 'roles') LOGGER.debug( 'Getting information about custom organization roles,' ' org_id = %s, flattened_results = %s', org_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'organizations_roles', e, 'name', name) LOGGER.exception(api_exception) raise api_exception
def get_buckets(self, project_id): """Gets all GCS buckets for a project. Args: project_id (int): The project id for a GCP project. Returns: list: a list of bucket resource dicts. https://cloud.google.com/storage/docs/json_api/v1/buckets Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails """ try: paged_results = self.repository.buckets.list(project_id, projection='full') flattened_results = api_helpers.flatten_list_results(paged_results, 'items') LOGGER.debug('Getting all GCS buckets for a project, project_id =' ' %s, flattened_results = %s', project_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'buckets', e, 'project_id', project_id) LOGGER.exception(api_exception) raise api_exception
def get_project_sinks(self, project_id): """Get information about project sinks. Args: project_id (str): The id of the project. Returns: list: The response of retrieving the project sinks. Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ name = self.repository.projects_sinks.get_name(project_id) try: paged_results = self.repository.projects_sinks.list(name) flattened_results = api_helpers.flatten_list_results( paged_results, 'sinks') LOGGER.debug( 'Getting information about project sinks,' ' project_id = %s, flattened_results = %s', project_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'projects_sinks', e, 'name', name) LOGGER.exception(api_exception) raise api_exception
def get_datasets_for_projectid(self, project_id): """Return BigQuery datasets stored in the requested project_id. Args: project_id (str): String representing the project id. Returns: list: A list of datasetReference objects for a given project_id An example return value: [{'datasetId': 'dataset-id', 'projectId': 'project-id'}, {...}] """ try: results = self.repository.datasets.list( resource=project_id, all=True) flattened_results = api_helpers.flatten_list_results( results, 'datasets') LOGGER.debug('Getting bigquery datasets for a given project,' ' project_id = %s, flattened_results = %s', project_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError(project_id, e)
def get_bigquery_projectids(self): """Request and page through bigquery projectids. Returns: list: A list of project_ids enabled for bigquery. If there are no project_ids enabled for bigquery an empty list will be returned. An example return value: ['project-id', 'project-id', '...'] """ try: results = self.repository.projects.list( fields='nextPageToken,projects/id') flattened_results = api_helpers.flatten_list_results( results, 'projects') LOGGER.debug('Request and page through bigquery ' ' projectids, flattened_results = %s', flattened_results) except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError('bigquery', e) project_ids = [result.get('id') for result in flattened_results if 'id' in result] return project_ids
def get_clusters(self, project_id, zone='-'): """Gets the clusters and their node pools for a project and zone. If zone is not specified, it lists clusters for all zones in the project. Args: project_id (int): The project id for a GCP project. zone (str): Name of the zone to get the configuration for. Use '-' to return clusters from all zones. Returns: list: A list of Cluster dicts. https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1/projects.zones.clusters#Cluster An example return value: [ {"name": "cluster-1", ...} {"name": "cluster-2", ...}, {...} ] Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails """ try: repository = self.repository.projects_zones_clusters results = repository.list(project_id, zone=zone) return api_helpers.flatten_list_results(results, 'clusters') except (errors.HttpError, HttpLib2Error) as e: LOGGER.warning(api_errors.ApiExecutionError(project_id, e)) raise api_errors.ApiExecutionError(project_id, e)
def get_instances(self, project_id): """Gets all CloudSQL instances for a project. Args: project_id (int): The project id for a GCP project. Returns: list: A list of database Instance resource dicts for a project_id. https://cloud.google.com/sql/docs/mysql/admin-api/v1beta4/instances [{"kind": "sql#instance", "name": "sql_instance1", ...} {"kind": "sql#instance", "name": "sql_instance2", ...}, {...}] Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP ClodSQL API fails """ try: paged_results = self.repository.instances.list(project_id) flattened_results = api_helpers.flatten_list_results( paged_results, 'items') LOGGER.debug( 'Getting all the cloudsql instances of a project,' ' project_id = %s, flattened_results = %s', project_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'instances', e, 'project_id', project_id) LOGGER.exception(api_exception) raise api_exception
def get_users(self, customer_id='my_customer'): """Get all the users for a given customer_id. A note on customer_id='my_customer'. This is a magic string instead of using the real customer id. See: https://developers.google.com/admin-sdk/directory/v1/guides/manage-groups#get_all_domain_groups Args: customer_id (str): The customer id to scope the request to. Returns: list: A list of user objects returned from the API. Raises: api_errors.ApiExecutionError: If groups retrieval fails. RefreshError: If the authentication fails. """ try: paged_results = self.repository.users.list(customer=customer_id, viewType='admin_view') flattened_results = api_helpers.flatten_list_results( paged_results, 'users') LOGGER.debug( 'Getting all the users for customer_id = %s,' ' flattened_results = %s', customer_id, flattened_results) return flattened_results except RefreshError as e: # Authentication failed, log before raise. LOGGER.exception(GSUITE_AUTH_FAILURE_MESSAGE) raise e except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError('users', e)
def extract_project_ids(crm_client): """Extract a list of project ID's Args: crm_client (CloudResourceManagerClient): An authenticated CRM client Returns: list: Project ID's as strings """ project_response = crm_client.get_projects() projects = api_helpers.flatten_list_results(project_response, 'projects') return [project['projectId'] for project in projects]
def get_enabled_apis(self, project_id): """Gets the enabled APIs for a project. Args: project_id (str): The project id for a GCP project. Returns: list: A list of Services resource dicts. https://cloud.google.com/service-usage/docs/reference/rest/v1/services#Service { "name": string, "parent": string, "config": { object (ServiceConfig) }, "state": enum (State) } Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ formatted_project_name = ( self.repository.services.get_formatted_project_name(project_id)) enabled_filter = 'state:ENABLED' try: paged_results = self.repository.services.list( parent=formatted_project_name, max_results=self.DEFAULT_MAX_RESULTS, filter=enabled_filter) flattened_results = api_helpers.flatten_list_results( paged_results, 'services') except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'serviceusage_enabledapis', e, 'project_id', project_id) LOGGER.exception(api_exception) raise api_exception LOGGER.debug( 'Getting the enabled APIs for project_id = %s, ' 'flattened_results = %s', project_id, flattened_results) return flattened_results
def get_organizations(self): """Get organizations that the authenticated account has access to. Returns: list: A list of Organization dicts as returned by the API. """ try: paged_results = self.repository.organizations.search() flattened_results = api_helpers.flatten_list_results( paged_results, 'organizations') LOGGER.debug( 'Getting organzations that the auth\'d account' ' has access to, flattened_results = %s', flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError('All Organizations', e)
def get_billing_accounts(self, master_account_id=None): """Gets all billing accounts the authenticated user has access to. If no master account is specified, then all billing accounts the caller has visibility to are returned. Otherwise retuns all subaccounts of the specified master billing account. Args: master_account_id (str): If set, only return subaccounts under this master billing account. Returns: list: A list of BillingAccount resources. https://cloud.google.com/billing/reference/rest/v1/billingAccounts { "name": string, "open": boolean, "displayName": string, "masterBillingAccount": string, } Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ filters = '' if master_account_id: filters = 'master_billing_account={}'.format( self.repository.billing_accounts.get_name(master_account_id)) try: paged_results = self.repository.billing_accounts.list( filter=filters) flattened_results = api_helpers.flatten_list_results( paged_results, 'billingAccounts') LOGGER.debug( 'Getting billing_accounts,' ' master_account_id = %s, flattened_results = %s', master_account_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'billing_accounts', e, 'filter', filters) LOGGER.exception(api_exception) raise api_exception
def get_object_acls(self, bucket, object_name, user_project=None): """Gets acls for GCS object. Args: bucket (str): The name of the bucket. object_name (str): The name of the object. user_project (str): The user project to bill the bucket access to, for requester pays buckets. Returns: dict: ACL json for bucket Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails """ try: kwargs = {} if user_project: kwargs['userProject'] = user_project results = self.repository.object_acls.list(resource=bucket, object=object_name, **kwargs) flattened_results = api_helpers.flatten_list_results( results, 'items') LOGGER.debug( 'Getting acls for GCS object, bucket = %s,' ' object_name = %s, flattened_results = %s', bucket, object_name, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: if not user_project and _user_project_missing_error(e): if self._user_project: LOGGER.info( 'User project required for bucket %s, ' 'retrying.', bucket) return self.get_object_acls(bucket, object_name, self._user_project) api_exception = api_errors.ApiExecutionError( 'objectAccessControls', e, 'bucket', bucket) LOGGER.exception(api_exception) raise api_exception
def get_folders(self, parent=None, show_deleted=False): """Find all folders that the authenticated account has access to. If no parent is passed in, then all folders the caller has visibility to are returned. This is significantly less efficient then listing by parent. Args: parent (str): Optional parent resource, either 'organizations/{org_id}' or 'folders/{folder_id}'. show_deleted (bool): Determines if deleted folders should be returned in the results. Returns: list: A list of Folder dicts as returned by the API. Raises: ApiExecutionError: An error has occurred when executing the API. """ if parent: paged_results = self.repository.folders.list( parent, showDeleted=show_deleted) else: query = '' if not show_deleted: query = 'lifecycleState=ACTIVE' paged_results = self.repository.folders.search(query=query) try: flattened_results = api_helpers.flatten_list_results( paged_results, 'folders') LOGGER.debug( 'Getting all the folders that the auth\'d account' ' has access to, parent = %s, show_deleted = %s,' ' flattened_results = %s', parent, show_deleted, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: if parent: resource_name = parent else: resource_name = 'All Folders' raise api_errors.ApiExecutionError(resource_name, e)
def get_group_members(self, group_key): """Get all the members for specified groups. Args: group_key (str): The group's unique id assigned by the Admin API. Returns: list: A list of member objects from the API. Raises: api_errors.ApiExecutionError: If group member retrieval fails. """ try: paged_results = self.repository.members.list(group_key) result = api_helpers.flatten_list_results(paged_results, 'members') LOGGER.debug('Getting all the members for group_key = %s,' ' result = %s', group_key, result) return result except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError(group_key, e)
def get_project_liens(self, project_id): """Get all liens for this project. Args: project_id (str): the id of the project. Returns: list: A list of Lien dicts as returned by the API. Raises: ApiExecutionError: An error has occurred when executing the API. """ project_id = self.repository.projects.get_name(project_id) try: paged_results = self.repository.liens.list(project_id) flattened_results = api_helpers.flatten_list_results( paged_results, 'liens') return flattened_results except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError(project_id, e)
def get_objects(self, bucket, user_project=None): """Gets all objects in a bucket. Args: bucket (str): The bucket to list to objects in. user_project (str): The user project to bill the bucket access to, for requester pays buckets. Returns: list: a list of object resource dicts. https://cloud.google.com/storage/docs/json_api/v1/objects Raises: ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails """ try: kwargs = {} if user_project: kwargs['userProject'] = user_project paged_results = self.repository.objects.list(bucket, projection='full', **kwargs) flattened_results = api_helpers.flatten_list_results( paged_results, 'items') LOGGER.debug( 'Getting all the objects in a bucket, bucket = %s,' ' flattened_results = %s', bucket, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: if not user_project and _user_project_missing_error(e): if self._user_project: LOGGER.info( 'User project required for bucket %s, ' 'retrying.', bucket) return self.get_objects(bucket, self._user_project) api_exception = api_errors.ApiExecutionError( 'objects', e, 'bucket', bucket) LOGGER.exception(api_exception) raise api_exception
def get_tables(self, project_id, dataset_id): """Return BigQuery tables stored in the requested project_id. Args: project_id (str): String representing the project id. dataset_id (str): String representing the dataset id. Returns: list: A list of datasetReference objects for a given project_id """ try: results = self.repository.tables.list( projectId=project_id, datasetId=dataset_id) flattened_results = api_helpers.flatten_list_results( results, 'tables') LOGGER.debug('Getting tables for the project %s and dataset %s', project_id, dataset_id) return flattened_results except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError(project_id + ';' + dataset_id, e)
def list_services(self, project_id): """Lists services of a project. Args: project_id (str): The id of the project. Returns: list: A list of Service resource dicts for a project_id. """ try: paged_results = self.repository.app_services.list(project_id) flattened_results = api_helpers.flatten_list_results( paged_results, 'services') LOGGER.debug('Listing services of a project, project_id = %s,' ' flattened_results = %s', project_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: if _is_status_not_found(e): return [] raise api_errors.ApiExecutionError(project_id, e)
def get_service_account_keys(self, name, key_type=None): """Get keys associated with the given Service Account. Args: name (str): The service account name to query, must be in the format projects/{PROJECT_ID}/serviceAccounts/{SERVICE_ACCOUNT_EMAIL} key_type (str): Optional, the key type to include in the results. Can be None, USER_MANAGED or SYSTEM_MANAGED. Defaults to returning all key types. Returns: list: List with a dict for each key associated with the account. Raises: ValueError: Raised if an invalid key_type is specified. ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ try: kwargs = {} if key_type: if key_type not in self.KEY_TYPES: raise ValueError('Key type %s is not a valid key type.' % key_type) kwargs['keyTypes'] = key_type results = self.repository.projects_serviceaccounts_keys.list( name, **kwargs) flattened_results = api_helpers.flatten_list_results( results, 'keys') LOGGER.debug( 'Getting the keys associated with the given service' ' account, name = %s, key_type = %s,' ' flattened_results = %s', name, key_type, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: api_exception = api_errors.ApiExecutionError( 'serviceAccountKeys', e, 'name', name) LOGGER.exception(api_exception) raise api_exception
def get_project_org_policies(self, project_id): """Get all the org policies for a given project. Args: project_id (str): Either the project number or the project id. Returns: list: Org policies applied to the project. https://cloud.google.com/resource-manager/reference/rest/v1/Policy """ resource_id = self.repository.projects.get_name(project_id) try: paged_results = self.repository.projects.list_org_policies( resource_id) flattened_results = api_helpers.flatten_list_results( paged_results, 'policies') LOGGER.debug( 'Getting all the org policies for a given project,' ' project_id = %s, flattened_results = %s', project_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError(resource_id, e)
def get_folder_org_policies(self, folder_id): """Get all the org policies for a given folder. Args: folder_id (int): The folder id. Returns: list: Org policies applied to the folder. https://cloud.google.com/resource-manager/reference/rest/v1/Policy """ resource_id = self.repository.folders.get_name(folder_id) try: paged_results = self.repository.folders_v1.list_org_policies( resource_id) flattened_results = api_helpers.flatten_list_results( paged_results, 'policies') LOGGER.debug( 'Getting all the org policies of a given folder,' ' folder_id = %s, flattened_results = %s', folder_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError(resource_id, e)
def list_versions(self, project_id, service_id): """Lists versions of a given service. Args: project_id (str): The id of the project. service_id (str): The id of the service to query. Returns: list: A list of Version resource dicts for a given Service. """ try: paged_results = self.repository.service_versions.list( project_id, services_id=service_id) flattened_results = api_helpers.flatten_list_results( paged_results, 'versions') LOGGER.debug('Listing versions of a given service, project_id =' ' %s, service_id = %s, flattened_results = %s', project_id, service_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: if _is_status_not_found(e): return [] raise api_errors.ApiExecutionError(project_id, e)
def get_org_org_policies(self, org_id): """Get all the org policies for a given org. Args: org_id (int): The org id number. Returns: list: Org policies applied to the organization. https://cloud.google.com/resource-manager/reference/rest/v1/Policy """ resource_id = self.repository.organizations.get_name(org_id) try: paged_results = self.repository.organizations.list_org_policies( resource_id) flattened_results = api_helpers.flatten_list_results( paged_results, 'policies') LOGGER.debug( 'Getting all the org policies for a given org,' ' org_id = %s, resource_id = %s,' ' flattened_results = %s', org_id, resource_id, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: raise api_errors.ApiExecutionError(resource_id, e)
def get_service_account_keys(self, name, key_type=None): """Get keys associated with the given Service Account. Args: name (str): The service account name to query, must be in the format projects/{PROJECT_ID}/serviceAccounts/{SERVICE_ACCOUNT_EMAIL} key_type (str): Optional, the key type to include in the results. Can be None, USER_MANAGED or SYSTEM_MANAGED. Defaults to returning all key types. Returns: list: List with a dict for each key associated with the account. Raises: ValueError: Raised if an invalid key_type is specified. ApiExecutionError: ApiExecutionError is raised if the call to the GCP API fails. """ def _service_account_not_found(error): """Checks if the error is due to the SA not found in the project. Args: error (Exception): The error to check. Returns: bool: If the error is due to SA not found. """ sa_not_found_pattern = '^Service account .*? does not exist.$' if isinstance(error, errors.HttpError): if (str(error.resp.status) == '404' and error.resp.get( 'content-type', '').startswith('application/json')): error_resp = json.loads(error.content.decode('utf-8')) error_details = error_resp.get('error', {}) error_message = error_details.get('message', '') LOGGER.debug(error_message) if re.match(sa_not_found_pattern, error_message): return True return False try: kwargs = {} if key_type: if key_type not in self.KEY_TYPES: raise ValueError('Key type %s is not a valid key type.' % key_type) kwargs['keyTypes'] = key_type results = self.repository.projects_serviceaccounts_keys.list( name, **kwargs) flattened_results = api_helpers.flatten_list_results( results, 'keys') LOGGER.debug( 'Getting the keys associated with the given service' ' account, name = %s, key_type = %s,' ' flattened_results = %s', name, key_type, flattened_results) return flattened_results except (errors.HttpError, HttpLib2Error) as e: if _service_account_not_found(e): LOGGER.debug('Service account %s doesn\'t exist', name) return [] api_exception = api_errors.ApiExecutionError( 'serviceAccountKeys', e, 'name', name) LOGGER.exception(api_exception) raise api_exception