def _flatten_aggregated_list_results(project_id, paged_results, item_key, sort_key='name'): """Flatten results and handle exceptions. Args: project_id (str): The project id the results are for. paged_results (list): A list of paged API response objects. [{page 1 results}, {page 2 results}, {page 3 results}, ...] item_key (str): The name of the key within the inner "items" lists containing the objects of interest. sort_key (str): The name of the key to sort the results by before returning. Returns: list: A sorted list of items. Raises: ApiNotEnabledError: Raised if the API is not enabled for the project. ApiExecutionError: Raised if there is another error while calling the API method. """ try: return sorted( api_helpers.flatten_aggregated_list_results(paged_results, item_key), key=lambda d: d.get(sort_key, '')) except (errors.HttpError, HttpLib2Error) as e: api_not_enabled, details = _api_not_enabled(e) if api_not_enabled: raise api_errors.ApiNotEnabledError(details, e) raise api_errors.ApiExecutionError(project_id, e)
def _execute(request, rate_limiter=None): """Executes requests in a rate-limited way. Args: request: GCP API client request object. rate_limiter: An instance of RateLimiter to use. Will be None for api without any rate limits. Returns: API response object. Raises: When the retry is exceeded, exception will be thrown. This exception is not wrapped by the retry library, and will be handled upstream. """ request = _attach_user_agent(request) try: if rate_limiter is not None: with rate_limiter: return request.execute() return request.execute() except HttpError as e: if (e.resp.status == 403 and e.resp.get('content-type', '').startswith( 'application/json')): # If a project doesn't have the necessary API enabled, Google # will return an error domain=usageLimits and # reason=accessNotConfigured. Clients may wish to handle this # error in some particular way. For instance, when listing # resources, it might be treated as "no resources of that type # are present", if the API would need to be enabled in order # to create the resources in question! # # So, if we find that specific error, raise a different # exception to indicate it to callers. Otherwise, propagate # the initial exception. error_details = json.loads(e.content) errors = error_details.get('error', {}).get('errors', []) api_disabled_errors = [ error for error in errors if (error.get('domain') == 'usageLimits' and error.get('reason') == 'accessNotConfigured')] if (api_disabled_errors and len(api_disabled_errors) == len(errors)): raise api_errors.ApiNotEnabledError( api_disabled_errors[0].get('extendedHelp', ''), e) raise
def get_project(self, project_id): """Returns the specified Project resource. Args: project_id (str): The project id. Returns: dict: A Compute Project resource dict. https://cloud.google.com/compute/docs/reference/latest/projects/get """ try: return self.repository.projects.get(project_id) except (errors.HttpError, HttpLib2Error) as e: api_not_enabled, details = _api_not_enabled(e) if api_not_enabled: raise api_errors.ApiNotEnabledError(details, e) raise api_errors.ApiExecutionError(project_id, e)
def get_global_operation(self, project_id, operation_id): """Get the Operations Status Args: project_id (str): The project id. operation_id (str): The operation id. Returns: dict: Global Operation status and info. https://cloud.google.com/compute/docs/reference/latest/globalOperations/get Raises: ApiNotEnabledError: Returns if the api is not enabled. ApiExecutionError: Returns if the api is not executable. """ try: return self.repository.global_operations.get( project_id, operation_id) except (errors.HttpError, HttpLib2Error) as e: api_not_enabled, details = _api_not_enabled(e) if api_not_enabled: raise api_errors.ApiNotEnabledError(details, e) raise api_errors.ApiExecutionError(project_id, e)