def _PossiblyPromote(self, all_services, new_version, wait_for_stop_version): """Promotes the new version to default (if specified by the user). Args: all_services: dict of service ID to service_util.Service objects corresponding to all pre-existing services (used to determine how to promote this version to receive all traffic, if applicable). new_version: version_util.Version describing where to deploy the service wait_for_stop_version: bool, indicating whether to wait for stop operation to finish. Raises: VersionPromotionError: if the version could not successfully promoted """ if self.deploy_options.promote: try: version_util.PromoteVersion( all_services, new_version, self.api_client, self.deploy_options.stop_previous_version, wait_for_stop_version) except apitools_exceptions.HttpError as err: err_str = six.text_type(core_api_exceptions.HttpException(err)) raise VersionPromotionError(err_str) elif self.deploy_options.stop_previous_version: log.info('Not stopping previous version because new version was ' 'not promoted.')
def testVersionResourceNonexistent(self): """Promoting a version whose current status cannot be determined.""" all_services = {} new_version = version_util.Version('prj1', 'svc1', 'v1') # Fail to lookup a Version resource, so the code doesn't know whether the # version is currently serving. self.api_client.GetVersionResource.return_value = None version_util.PromoteVersion(all_services, new_version, self.api_client, stop_previous_version=False) # Don't call StartVersion because we're not sure it's necessary. self.api_client.StartVersion.assert_not_called() self.api_client.SetDefaultVersion.assert_called_once_with('svc1', 'v1')
def testErrorFetchingVersionResource(self): """An error occurs fetching the Version resource.""" all_services = {} new_version = version_util.Version('prj1', 'svc1', 'v1') # Fail to lookup a Version resource, so the code doesn't know whether the # version is currently serving. self.api_client.GetVersionResource.side_effect = ( apitools_exceptions.CommunicationError('failed')) version_util.PromoteVersion(all_services, new_version, self.api_client, stop_previous_version=False) # Don't call StartVersion because we're not sure it's necessary. self.api_client.StartVersion.assert_not_called() self.api_client.SetDefaultVersion.assert_called_once_with('svc1', 'v1')
def testVersionAlreadyServing(self): """Promoting a version that is already serving.""" all_services = {} new_version = version_util.Version('prj1', 'svc1', 'v1') # New version is already deployed and serving. version_resource = self.messages.Version() version_resource.servingStatus = ( self.messages.Version.ServingStatusValueValuesEnum.SERVING) self.api_client.GetVersionResource.return_value = version_resource version_util.PromoteVersion(all_services, new_version, self.api_client, stop_previous_version=False) # Don't call StartVersion because it's already started. self.api_client.StartVersion.assert_not_called() self.api_client.SetDefaultVersion.assert_called_once_with('svc1', 'v1')
def testStartStoppedVersion(self): """Verifies that a stopped version is started before promoting it.""" all_services = {} new_version = version_util.Version('prj1', 'svc1', 'v1') # New version is already deployed but is STOPPED. version_resource = self.messages.Version() version_resource.servingStatus = ( self.messages.Version.ServingStatusValueValuesEnum.STOPPED) self.api_client.GetVersionResource.return_value = version_resource version_util.PromoteVersion(all_services, new_version, self.api_client, stop_previous_version=False) # Start the new version before promoting it. self.api_client.StartVersion.assert_called_once_with('svc1', 'v1', block=True) self.api_client.SetDefaultVersion.assert_called_once_with('svc1', 'v1')
def Deploy(self, service, new_version, code_bucket_ref, image, all_services): """Deploy the given service. Performs all deployment steps for the given service (if applicable): * Enable endpoints (for beta deployments) * Build and push the Docker image (Flex only, if image_url not provided) * Upload files (non-hermetic deployments) * Create the new version * Promote the version to receieve all traffic (if --promote given (default)) * Stop the previous version (if new version promoted and --stop-previous-version given (default)) Args: service: yaml_parsing.ServiceYamlInfo, service configuration to be deployed new_version: version_util.Version describing where to deploy the service code_bucket_ref: cloud_storage.BucketReference where the service's files have been uploaded image: str or None, the URL for the Docker image to be deployed (if image already exists). all_services: dict of service ID to service_util.Service objects corresponding to all pre-existing services (used to determine how to promote this version to receive all traffic, if applicable). """ log.status.Print( 'Beginning deployment of service [{service}]...'.format( service=new_version.service)) # If the app has enabled Endpoints API Management features, pass # control to the cloud_endpoints handler. # The cloud_endpoints handler calls the Service Management APIs and # creates an endpoints/service.json file on disk which will need to # be bundled into the app Docker image. if self.deploy_options.enable_endpoints: cloud_endpoints.ProcessEndpointsService(service, new_version.project) # Build and Push the Docker image if necessary for this service. if service.RequiresImage(): log.warning( 'Deployment of App Engine Flexible Environment apps is ' 'currently in Beta') if not image: image = deploy_command_util.BuildAndPushDockerImage( new_version.project, service, new_version.id, code_bucket_ref) else: image = None manifest = _UploadFiles(service, code_bucket_ref) # Actually create the new version of the service. message = 'Updating service [{service}]'.format( service=new_version.service) with console_io.ProgressTracker(message): self.api_client.DeployService(new_version.service, new_version.id, service, manifest, image) metrics.CustomTimedEvent(metric_names.DEPLOY_API) if self.deploy_options.promote: try: version_util.PromoteVersion( all_services, new_version, self.api_client, self.deploy_options.stop_previous_version) except calliope_exceptions.HttpException as err: raise VersionPromotionError(err) elif self.deploy_options.stop_previous_version: log.info( 'Not stopping previous version because new version was ' 'not promoted.')