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}
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}