def UnidentifiedDirMatcher(path, stager):
  """Generate a Service from a potential app directory.

  This function is a path matcher that returns if and only if:
  - `path` points to an `<app-dir>` where the fingerprinter identifies a runtime
    and the user opts in to writing an `app.yaml` into `<app-dir>.

  If the runtime and environment match an entry in the stager, the service will
  be staged into a directory.

  Args:
    path: str, Unsanitized absolute path, may point to a directory or a file of
        any type. There is no guarantee that it exists.
    stager: staging.Stager, stager that will be invoked if there is a runtime
        and environment match.

  Raises:
    staging.StagingCommandFailedError, staging command failed.

  Returns:
    Service, fully populated with entries that respect a potentially
        staged deployable service, or None if the path does not fulfill the
        requirements described above.
  """
  if os.path.isdir(path):
    log.warning('Automatic app detection is currently in Beta')
    yaml = deploy_command_util.CreateAppYamlForAppDirectory(path)
    return ServiceYamlMatcher(yaml, stager)
def RunDeploy(unused_self, args, enable_endpoints=False, app_create=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, app_create)

    # 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()

    if not args.skip_image_url_validation:
        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)

    app = _PossiblyCreateApp(api_client, project, deploy_options.app_create)

    # Tell the user what is going to happen, and ask them to confirm.
    deployed_urls = output_helpers.DisplayProposedDeployment(
        app, project, app_config, version_id, deploy_options.promote)
    console_io.PromptContinue(cancel_on_no=True)
    if services:
        # Do generic app setup if deploying any services.
        # 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 = []
    stager = staging.GetNoopStager(
    ) if args.skip_staging else staging.GetStager()
    deployer = ServiceDeployer(api_client, stager, 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 progress_tracker.ProgressTracker(message):
            ac_client.UpdateConfig(name, config.parsed)

    updated_configs = app_config.Configs().keys()

    PrintPostDeployHints(new_versions, updated_configs)

    # Return all the things that were deployed.
    return {'versions': new_versions, 'configs': updated_configs}
Beispiel #3
0
def RunDeploy(args,
              enable_endpoints=False,
              app_create=False,
              use_beta_stager=False):
    """Perform a deployment based on the given args.

  Args:
    args: argparse.Namespace, An object that contains the values for the
        arguments specified in the ArgsDeploy() function.
    enable_endpoints: Enable Cloud Endpoints for the deployed app.
    app_create: Offer to create an app if current GCP project is appless.
    use_beta_stager: Use the stager registry defined for the beta track rather
        than the default stager registry.

  Returns:
    A dict on the form `{'versions': new_versions, 'configs': updated_configs}`
    where new_versions is a list of version_util.Version, and updated_configs
    is a list of config file identifiers, see yaml_parsing.ConfigYamlInfo.
  """
    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, app_create)

    # 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)

    # If applicable, sort services by order they were passed to the command.
    services = app_config.Services()

    if not args.skip_image_url_validation:
        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)

    app = _PossiblyCreateApp(api_client, project, deploy_options.app_create)

    if properties.VALUES.app.use_gsutil.GetBool():
        log.warning(
            'Your gcloud installation has a deprecated config property '
            'enabled: [app/use_gsutil], which will be removed in a '
            'future version.  Run `gcloud config unset app/use_gsutil` to '
            'switch to the recommended approach.  If you encounter any '
            'issues, please report using `gcloud feedback`.  To revert '
            'temporarily, run `gcloud config set app/use_gsutil True`.\n')

    # Tell the user what is going to happen, and ask them to confirm.
    deployed_urls = output_helpers.DisplayProposedDeployment(
        app, project, app_config, version_id, deploy_options.promote)
    console_io.PromptContinue(cancel_on_no=True)
    if services:
        # Do generic app setup if deploying any services.
        # 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 = []
    if args.skip_staging:
        stager = staging.GetNoopStager()
    elif use_beta_stager:
        stager = staging.GetBetaStager()
    else:
        stager = staging.GetStager()
    deployer = ServiceDeployer(api_client, stager, 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 progress_tracker.ProgressTracker(message):
            ac_client.UpdateConfig(name, config.parsed)

    updated_configs = app_config.Configs().keys()

    PrintPostDeployHints(new_versions, updated_configs)

    # Return all the things that were deployed.
    return {'versions': new_versions, 'configs': updated_configs}
def RunDeploy(
        args,
        enable_endpoints=False,
        use_beta_stager=False,
        runtime_builder_strategy=runtime_builders.RuntimeBuilderStrategy.NEVER,
        use_service_management=False,
        check_for_stopped=False):
    """Perform a deployment based on the given args.

  Args:
    args: argparse.Namespace, An object that contains the values for the
        arguments specified in the ArgsDeploy() function.
    enable_endpoints: Enable Cloud Endpoints for the deployed app.
    use_beta_stager: Use the stager registry defined for the beta track rather
        than the default stager registry.
    runtime_builder_strategy: runtime_builders.RuntimeBuilderStrategy, when to
      use the new CloudBuild-based runtime builders (alternative is old
      externalized runtimes).
    use_service_management: bool, whether to use servicemanagement API to
      enable the Appengine Flexible API for a Flexible deployment.
    check_for_stopped: bool, whether to check if the app is stopped before
      deploying.

  Returns:
    A dict on the form `{'versions': new_versions, 'configs': updated_configs}`
    where new_versions is a list of version_util.Version, and updated_configs
    is a list of config file identifiers, see yaml_parsing.ConfigYamlInfo.
  """
    project = properties.VALUES.core.project.Get(required=True)
    deploy_options = DeployOptions.FromProperties(
        enable_endpoints, runtime_builder_strategy=runtime_builder_strategy)

    # 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)

    # If applicable, sort services by order they were passed to the command.
    services = app_config.Services()

    if not args.skip_image_url_validation:
        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)

    app = _PossiblyCreateApp(api_client, project)
    if check_for_stopped:
        _RaiseIfStopped(api_client, app)
    app = _PossiblyRepairApp(api_client, app)

    # Tell the user what is going to happen, and ask them to confirm.
    version_id = args.version or util.GenerateVersionId()
    deployed_urls = output_helpers.DisplayProposedDeployment(
        app, project, app_config, version_id, deploy_options.promote)
    console_io.PromptContinue(cancel_on_no=True)
    if services:
        # Do generic app setup if deploying any services.
        # All deployment paths for a service involve uploading source to GCS.
        metrics.CustomTimedEvent(metric_names.GET_CODE_BUCKET_START)
        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()]):
            if use_service_management:
                deploy_command_util.PossiblyEnableFlex(project)
            else:
                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 = []
    if args.skip_staging:
        stager = staging.GetNoopStager()
    elif use_beta_stager:
        stager = staging.GetBetaStager()
    else:
        stager = staging.GetStager()
    deployer = ServiceDeployer(api_client, stager, deploy_options)

    # Track whether a service has been deployed yet, for metrics.
    service_deployed = False
    for name, service in services.iteritems():
        if not service_deployed:
            metrics.CustomTimedEvent(metric_names.FIRST_SERVICE_DEPLOY_START)
        new_version = version_util.Version(project, name, version_id)
        deployer.Deploy(service, new_version, code_bucket_ref, args.image_url,
                        all_services, app.gcrDomain)
        new_versions.append(new_version)
        log.status.Print('Deployed service [{0}] to [{1}]'.format(
            name, deployed_urls[name]))
        if not service_deployed:
            metrics.CustomTimedEvent(metric_names.FIRST_SERVICE_DEPLOY)
        service_deployed = True

    # Deploy config files.
    if app_config.Configs():
        metrics.CustomTimedEvent(metric_names.UPDATE_CONFIG_START)
    for (name, config) in app_config.Configs().iteritems():
        message = 'Updating config [{config}]'.format(config=name)
        with progress_tracker.ProgressTracker(message):
            ac_client.UpdateConfig(name, config.parsed)
    if app_config.Configs():
        metrics.CustomTimedEvent(metric_names.UPDATE_CONFIG)

    updated_configs = app_config.Configs().keys()

    PrintPostDeployHints(new_versions, updated_configs)

    # Return all the things that were deployed.
    return {'versions': new_versions, 'configs': updated_configs}