Ejemplo n.º 1
0
def _CheckResponse(response):
    """Checks API error and if it's an enablement error, prompt to enable & retry.

  Args:
    response: response that had an error.

  Raises:
    apitools_exceptions.RequestError: error which should signal apitools to
      retry.
    api_Exceptions.HttpException: the parsed error.
  """
    # This will throw if there was a specific type of error. If not, then we can
    # parse and deal with our own class of errors.
    http_wrapper.CheckResponse(response)
    if not properties.VALUES.core.should_prompt_to_enable_api.Get():
        return
    # Once we get here, we check if it was an API enablement error and if so,
    # prompt the user to enable the API. If yes, we make that call and then
    # raise a RequestError, which will prompt the caller to retry. If not, we
    # raise the actual HTTP error.
    response_as_error = apitools_exceptions.HttpError.FromResponse(response)
    parsed_error = api_exceptions.HttpException(response_as_error)
    (project, service_token) = GetApiEnablementInfo(parsed_error)
    if (project is not None and ShouldAttemptProjectEnable(project)
            and service_token is not None):
        if console_io.PromptContinue(
                message=None,
                prompt_string=('API [{}] not enabled on project [{}]. '
                               'Would you like to enable and retry? ').format(
                                   service_token, project)):
            enable_api.EnableServiceIfDisabled(project, service_token)
            # An error here will invoke apitools retry logic
            raise apitools_exceptions.RequestError('Retry')
        else:
            raise parsed_error
Ejemplo n.º 2
0
def PromptToEnableApi(project,
                      service_token,
                      exception,
                      is_batch_request=False):
    """Prompts to enable the API and throws if the answer is no.

  Args:
    project (str): The project that the API is not enabled on.
    service_token (str): The service token of the API to prompt for.
    exception (api_Exceptions.HttpException): Exception to throw if the prompt
      is denied.
    is_batch_request: If the request is a batch request. This determines how to
      get apitools to retry the request.

  Raises:
    api_exceptions.HttpException: API not enabled error if the user chooses to
      not enable the API.
  """
    if console_io.PromptContinue(
            default=False,
            prompt_string=('API [{}] not enabled on project [{}]. '
                           'Would you like to enable and retry? ').format(
                               service_token, project)):
        enable_api.EnableServiceIfDisabled(project, service_token)
        # In the case of a batch request, as long as the error's retryable code
        # (in this case 403) was set, after this runs it should retry. This
        # error code should be consistent with apis.GetApiEnablementInfo
        if not is_batch_request:
            raise apitools_exceptions.RequestError('Retry')
    else:
        raise exception
Ejemplo n.º 3
0
    def BatchCheck(self, http_response, exception):
        """Callback for apitools batch responses.

    This will use self.prompted_service_tokens to cache service tokens that
    have already been prompted. In this way, if the same service has multiple
    batch requests and is enabled on the first, the user won't get a bunch of
    superflous messages. Note that this cannot be reused between batch uses
    because of the mutation.

    Args:
      http_response: Deserialized http_wrapper.Response object.
      exception: apiclient.errors.HttpError object if an error occurred.
    """
        if (exception is None or
                not properties.VALUES.core.should_prompt_to_enable_api.Get()):
            return
        parsed_error = api_exceptions.HttpException(exception)
        project, service_token = apis.GetApiEnablementInfo(parsed_error)
        if (project is None or not apis.ShouldAttemptProjectEnable(project)
                or service_token is None):
            return
        if service_token not in self.prompted_service_tokens:
            self.prompted_service_tokens.add(service_token)
            if console_io.PromptContinue(
                    prompt_string=('API [{}] not enabled on project [{}]. '
                                   'Would you like to enable and retry? '
                                   ).format(service_token, project)):
                enable_api.EnableServiceIfDisabled(project, service_token)
Ejemplo n.º 4
0
def PossiblyEnableFlex(project):
    """Attempts to enable the Flexible Environment API on the project.

  Possible scenarios:
  -If Flexible Environment is already enabled, success.
  -If Flexible Environment API is not yet enabled, attempts to enable it. If
   that succeeds, success.
  -If the account doesn't have permissions to confirm that the Flexible
   Environment API is or isn't enabled on this project, succeeds with a warning.
     -If the account is a service account, adds an additional warning that
      the Service Management API may need to be enabled.
  -If the Flexible Environment API is not enabled on the project and the attempt
   to enable it fails, raises PrepareFailureError.

  Args:
    project: str, the project ID.

  Raises:
    PrepareFailureError: if enabling the API fails with a 403 or 404 error code.
    googlecloudsdk.api_lib.util.exceptions.HttpException: miscellaneous errors
        returned by server.
  """
    try:
        log.warn(
            'Checking the status of the Appengine Flexible Environment API '
            'during Appengine Flexible deployments is currently in beta.')
        enable_api.EnableServiceIfDisabled(project,
                                           'appengineflex.googleapis.com')
    except sm_exceptions.ListServicesPermissionDeniedException:
        # If we can't find out whether the Flexible API is enabled, proceed with
        # a warning.
        warning = FLEXIBLE_SERVICE_VERIFY_WARNING.format(project)
        # If user is using a service account, add more info about what might
        # have gone wrong.
        credential = c_store.LoadIfEnabled()
        if credential:
            account_type = creds.CredentialType.FromCredentials(credential)
            if account_type in (creds.CredentialType.SERVICE_ACCOUNT,
                                creds.CredentialType.P12_SERVICE_ACCOUNT):
                warning += '\n\n{}'.format(
                    FLEXIBLE_SERVICE_VERIFY_WITH_SERVICE_ACCOUNT)
        log.warn(warning)
    except sm_exceptions.EnableServicePermissionDeniedException:
        # If enabling the Flexible API fails due to a permissions error, the
        # deployment fails.
        raise PrepareFailureError(PREPARE_FAILURE_MSG.format(project))
    except api_lib_exceptions.HttpException as err:
        # The deployment should also fail if there are unforeseen errors in
        # enabling the Flexible API. If so, display detailed information.
        err.error_format = ('Error [{status_code}] {status_message}'
                            '{error.details?'
                            '\nDetailed error information:\n{?}}')
        raise err