def BrowseApp(project, service, version, launch_browser):
    """Let you browse the given service at the given version.

  Args:
    project: str, project ID.
    service: str, specific service, 'default' if None
    version: str, specific version, latest if None
    launch_browser: boolean, if False only print url

  Returns:
    None if the browser should open the URL
    The relevant output as a dict for calliope format to print if not

  Raises:
    MissingApplicationError: If an app does not exist.
  """
    try:
        url = deploy_command_util.GetAppHostname(app_id=project,
                                                 service=service,
                                                 version=version,
                                                 use_ssl=appinfo.SECURE_HTTPS,
                                                 deploy=False)
    except api_lib_exceptions.NotFoundError:
        log.debug('No app found:', exc_info=True)
        raise exceptions.MissingApplicationError(project)
    if check_browser.ShouldLaunchBrowser(launch_browser):
        OpenURL(url)
        return None
    else:
        return {
            'url': url,
            'service': service or 'default',
            'version': version,
        }
예제 #2
0
def _PossiblyCreateApp(api_client, project):
    """Returns an app resource, and creates it if the stars are aligned.

  App creation happens only if the current project is app-less, we are running
  in interactive mode and the user explicitly wants to.

  Args:
    api_client: Admin API client.
    project: The GCP project/app id.

  Returns:
    An app object (never returns None).

  Raises:
    MissingApplicationError: If an app does not exist and cannot be created.
  """
    try:
        return api_client.GetApplication()
    except api_lib_exceptions.NotFoundError:
        # Invariant: GCP Project does exist but (singleton) GAE app is not yet
        # created.
        #
        # Check for interactive mode, since this action is irreversible and somewhat
        # surprising. CreateAppInteractively will provide a cancel option for
        # interactive users, and MissingApplicationException includes instructions
        # for non-interactive users to fix this.
        log.debug('No app found:', exc_info=True)
        if console_io.CanPrompt():

            # Equivalent to running `gcloud app create`
            create_util.CreateAppInteractively(api_client, project)
            # App resource must be fetched again
            return api_client.GetApplication()
        raise exceptions.MissingApplicationError(project)
def _PossiblyCreateApp(api_client, project, app_create):
    """Returns an app resource, and creates it if the stars are aligned.

  App creation happens only if the current project is app-less,
  app_create is True, we are running in interactive mode and the user
  explicitly wants to.

  Args:
    api_client: Admin API client.
    project: The GCP project/app id.
    app_create: True if interactive app creation should be allowed.

  Returns:
    An app object (never returns None).

  Raises:
    MissingApplicationError: If an app does not exist and cannot be created.
  """
    try:
        return api_client.GetApplication()
    except api_lib_exceptions.NotFoundError:
        # Invariant: GCP Project does exist but (singleton) GAE app is not yet
        # created. Offer to create one if the following conditions are true:
        # 1. `app_create` is True (currently `beta` only)
        # 2. We are currently running in interactive mode
        msg = output_helpers.CREATE_APP_PROMPT.format(project=project)
        if (app_create and console_io.CanPrompt()
                and console_io.PromptContinue(message=msg)):
            # Equivalent to running `gcloud beta app create`
            create_util.CreateAppInteractively(api_client, project)
            # App resource must be fetched again
            return api_client.GetApplication()
        raise exceptions.MissingApplicationError(project)
예제 #4
0
def Describe(api_client):
    try:
        return api_client.GetApplication()
    except apitools_exceptions.HttpNotFoundError:
        log.debug('No app found:', exc_info=True)
        project = api_client.project
        raise exceptions.MissingApplicationError(project)
예제 #5
0
 def Run(self, args):
   api_client = appengine_api_client.GetApiClient()
   try:
     return api_client.GetApplication()
   except api_lib_exceptions.NotFoundError:
     log.debug('No app found:', exc_info=True)
     project = api_client.project
     raise exceptions.MissingApplicationError(project)
def _PossiblyCreateApp(api_client, project):
    """Returns an app resource, and creates it if the stars are aligned.

  App creation happens only if the current project is app-less, we are running
  in interactive mode and the user explicitly wants to.

  Args:
    api_client: Admin API client.
    project: The GCP project/app id.

  Returns:
    An app object (never returns None).

  Raises:
    MissingApplicationError: If an app does not exist and cannot be created.
  """
    try:
        return api_client.GetApplication()
    except apitools_exceptions.HttpNotFoundError:
        # Invariant: GCP Project does exist but (singleton) GAE app is not yet
        # created.
        #
        # Check for interactive mode, since this action is irreversible and somewhat
        # surprising. CreateAppInteractively will provide a cancel option for
        # interactive users, and MissingApplicationException includes instructions
        # for non-interactive users to fix this.
        log.debug('No app found:', exc_info=True)
        if console_io.CanPrompt():

            # Equivalent to running `gcloud app create`
            create_util.CreateAppInteractively(api_client, project)
            # App resource must be fetched again
            return api_client.GetApplication()
        raise exceptions.MissingApplicationError(project)
    except apitools_exceptions.HttpForbiddenError:
        active_account = properties.VALUES.core.account.Get()
        # pylint: disable=protected-access
        raise core_api_exceptions.HttpException(
            ('Permissions error fetching application [{}]. Please '
             'make sure that you have permission to view applications on the '
             'project and that {} has the App Engine Deployer '
             '(roles/appengine.deployer) role.'.format(api_client._FormatApp(),
                                                       active_account)))
예제 #7
0
def BrowseApp(project, service=None, version=None):
    """Open the app in a browser, optionally with given service and version.

  Args:
    project: str, project ID.
    service: str, (optional) specific service, defaults to 'default'
    version: str, (optional) specific version, defaults to latest

  Raises:
    MissingApplicationError: If an app does not exist.
  """
    try:
        url = deploy_command_util.GetAppHostname(app_id=project,
                                                 service=service,
                                                 version=version,
                                                 use_ssl=appinfo.SECURE_HTTPS,
                                                 deploy=False)
    except api_lib_exceptions.NotFoundError:
        log.debug('No app found:', exc_info=True)
        raise exceptions.MissingApplicationError(project)
    OpenURL(url)
예제 #8
0
def RunDeploy(unused_self, args, enable_endpoints=False):
    """Perform a deployment based on the given args."""
    version_id = args.version or util.GenerateVersionId()
    flags.ValidateVersion(version_id)
    project = properties.VALUES.core.project.Get(required=True)
    deploy_options = DeployOptions.FromProperties(enable_endpoints)

    # Parse existing app.yamls or try to generate a new one if the directory is
    # empty.
    if not args.deployables:
        yaml_path = deploy_command_util.DEFAULT_DEPLOYABLE
        if not os.path.exists(deploy_command_util.DEFAULT_DEPLOYABLE):
            log.warning('Automatic app detection is currently in Beta')
            yaml_path = deploy_command_util.CreateAppYamlForAppDirectory(
                os.getcwd())
        app_config = yaml_parsing.AppConfigSet([yaml_path])
    else:
        app_config = yaml_parsing.AppConfigSet(args.deployables)

    services = app_config.Services()

    flags.ValidateImageUrl(args.image_url, services)

    # The new API client.
    api_client = appengine_api_client.GetApiClient()
    # pylint: disable=protected-access
    log.debug('API endpoint: [{endpoint}], API version: [{version}]'.format(
        endpoint=api_client.client.url, version=api_client.client._VERSION))
    # The legacy admin console API client.
    # The Admin Console API existed long before the App Engine Admin API, and
    # isn't being improved. We're in the process of migrating all of the calls
    # over to the Admin API, but a few things (notably config deployments) haven't
    # been ported over yet.
    ac_client = appengine_client.AppengineClient(args.server,
                                                 args.ignore_bad_certs)

    # Tell the user what is going to happen, and ask them to confirm.
    deployed_urls = output_helpers.DisplayProposedDeployment(
        project, app_config, version_id, deploy_options.promote)
    console_io.PromptContinue(cancel_on_no=True)

    # Do generic app setup if deploying any services.
    if services:
        try:
            # TODO(b/31064052): Do this before displaying the proposed deployment and
            # reuse the default hostname from the app
            app = api_client.GetApplication()
        except api_lib_exceptions.AppNotFoundError:
            raise exceptions.MissingApplicationError(project)
        # All deployment paths for a service involve uploading source to GCS.
        code_bucket_ref = args.bucket or flags.GetCodeBucket(app, project)
        metrics.CustomTimedEvent(metric_names.GET_CODE_BUCKET)
        log.debug(
            'Using bucket [{b}].'.format(b=code_bucket_ref.ToBucketUrl()))

        # Prepare Flex if any service is going to deploy an image.
        if any([m.RequiresImage() for m in services.values()]):
            deploy_command_util.DoPrepareManagedVms(ac_client)

        all_services = dict([(s.id, s) for s in api_client.ListServices()])
    else:
        code_bucket_ref = None
        all_services = {}

    new_versions = []
    deployer = ServiceDeployer(api_client, deploy_options)
    for (name, service) in services.iteritems():
        new_version = version_util.Version(project, name, version_id)
        deployer.Deploy(service, new_version, code_bucket_ref, args.image_url,
                        all_services)
        new_versions.append(new_version)
        log.status.Print('Deployed service [{0}] to [{1}]'.format(
            name, deployed_urls[name]))

    # Deploy config files.
    for (name, config) in app_config.Configs().iteritems():
        message = 'Updating config [{config}]'.format(config=name)
        with console_io.ProgressTracker(message):
            ac_client.UpdateConfig(name, config.parsed)

    PrintPostDeployHints(new_versions)

    # Return all the things that were deployed.
    return {'versions': new_versions, 'configs': app_config.Configs().keys()}