def DeployModule(self, module_name, version_id, module_config, manifest, image): """Updates and deploys new app versions based on given config. Args: module_name: str, The module to deploy. version_id: str, The version of the module to deploy. module_config: AppInfoExternal, Module info parsed from a module yaml file. manifest: Dictionary mapping source files to Google Cloud Storage locations. image: The name of the container image. Returns: A Version resource representing the deployed version. """ version_resource = self._CreateVersionResource(module_config, manifest, version_id, image) create_request = self.messages.AppengineAppsModulesVersionsCreateRequest( name=self._FormatModule(app_id=self.project, module_name=module_name), version=version_resource) operation = requests.MakeRequest( self.client.apps_modules_versions.Create, create_request) log.debug('Received operation: [{operation}]'.format( operation=operation.name)) return operations.WaitForOperation(self.client.apps_operations, operation)
def SetTrafficSplit(self, module_name, allocations, shard_by='UNSPECIFIED', migrate=False): """Sets the traffic split of the given modules. Args: module_name: str, The module name allocations: A dict mapping version ID to traffic split. shard_by: A ShardByValuesEnum value specifying how to shard the traffic. migrate: Whether or not to migrate traffic. Returns: Long running operation. """ # Create a traffic split where 100% of traffic goes to the specified # version. traffic_split = encoding.PyValueToMessage(self.messages.TrafficSplit, { 'allocations': allocations, 'shardBy': shard_by }) update_module_request = self.messages.AppengineAppsModulesPatchRequest( name=self._FormatModule(app_id=self.project, module_name=module_name), module=self.messages.Module(split=traffic_split), migrateTraffic=migrate, mask='split') operation = requests.MakeRequest(self.client.apps_modules.Patch, update_module_request) return operations.WaitForOperation(self.client.apps_operations, operation)
def CreateApp(self, location): """Creates an App Engine app within the current cloud project. Creates a new singleton app within the currently selected Cloud Project. The action is one-time and irreversible. Args: location: str, The location (region) of the app, i.e. "us-central" Raises: googlecloudsdk.api_lib.app.exceptions.ConflictError if app already exists Returns: A long running operation. """ create_request = self.messages.AppengineAppsCreateRequest( application=self.messages.Application(id=self.project, location=location)) operation = requests.MakeRequest(self.client.apps.Create, create_request) log.debug('Received operation: [{operation}]'.format( operation=operation.name)) return operations.WaitForOperation(self.client.apps_operations, operation)
def SetServingStatus(self, service_name, version_id, serving_status, block=True): """Sets the serving status of the specified version. Args: service_name: str, The service name version_id: str, The version to delete. serving_status: The serving status to set. block: bool, whether to block on the completion of the operation Returns: The completed Operation if block is True, or the Operation to wait on otherwise. """ patch_request = self.messages.AppengineAppsServicesVersionsPatchRequest( name=self._FormatVersion(app_id=self.project, service_name=service_name, version_id=version_id), version=self.messages.Version(servingStatus=serving_status), mask='servingStatus') operation = requests.MakeRequest( self.client.apps_services_versions.Patch, patch_request) if block: return operations.WaitForOperation(self.client.apps_operations, operation) else: return operation
def _WaitAndStreamLogs(self, build_op, logs_bucket, build_id, logs_uri): """Wait for a Cloud Build to finish, optionally streaming logs.""" log.status.Print( 'Started cloud build [{build_id}].'.format(build_id=build_id)) if logs_bucket: log_object = self.CLOUDBUILD_LOGFILE_FMT_STRING.format( build_id=build_id) log_tailer = cloudbuild_logs.LogTailer(bucket=logs_bucket, obj=log_object) log_loc = None if logs_uri: log.status.Print('To see logs in the Cloud Console: ' + logs_uri) log_loc = 'at ' + logs_uri else: log.status.Print('Logs can be found in the Cloud Console.') log_loc = 'in the Cloud Console.' op = operations.WaitForOperation( operation_service=self.client.operations, operation=build_op, retry_interval=self._RETRY_INTERVAL, max_retries=self._MAX_RETRIES, retry_callback=log_tailer.Poll) # Poll the logs one final time to ensure we have everything. We know this # final poll will get the full log contents because GCS is strongly # consistent and Container Builder waits for logs to finish pushing before # marking the build complete. log_tailer.Poll(is_last=True) else: op = operations.WaitForOperation( operation_service=self.client.operations, operation=build_op, retry_interval=self._RETRY_INTERVAL, max_retries=self._MAX_RETRIES) final_status = _GetStatusFromOp(op) if final_status != self.CLOUDBUILD_SUCCESS: raise BuildFailedError('Cloud build failed with status ' + final_status + '. Check logs ' + log_loc)
def ExecuteCloudBuild(project, source_uri, output_image, cloudbuild_client): """Execute a call to Argo CloudBuild service and wait for it to finish. Args: project: the cloud project ID. source_uri: GCS object containing source to build; eg, gs://my-bucket/v1/foo/some.version.stuff. output_image: GCR location for the output docker image; eg, gcr.io/test-argo/hardcoded-output-tag. cloudbuild_client: client to the Argo Cloud Build service. Raises: BuildFailedError: when the build fails. """ (source_bucket, source_object) = cloud_storage.ParseGcsUri(source_uri) # TODO(user): Consider building multiple output images in a single call # to Argo Cloud Builder. build_op = cloudbuild_client.projects_builds.Create( cloudbuild_v1.CloudbuildProjectsBuildsCreateRequest( projectId=project, build=cloudbuild_v1.Build( source=cloudbuild_v1.Source( storageSource=cloudbuild_v1.StorageSource( bucket=source_bucket, object=source_object, ), ), steps=[ cloudbuild_v1.BuildStep(name=CLOUDBUILD_BUILDER, args=[output_image]) ], images=[output_image], ), )) # Build ops are named "operation/build/{project_id}/{build_id}". build_id = build_op.name.split('/')[-1] log.status.Print( 'Started cloud build [{build_id}].'.format(build_id=build_id)) logs_uri = CLOUDBUILD_LOGS_URI_TEMPLATE.format(project_id=project, build_id=build_id) # TODO(user): wait for job to be scheduled before printing logs uri. # Alternatively, it would be nice if we wrote a single line to the logs prior # to returning from the Create call. log.status.Print('Logs at: ' + logs_uri) message = 'Waiting for cloud build [{build_id}]'.format(build_id=build_id) with console_io.ProgressTracker(message): op = operations.WaitForOperation(cloudbuild_client.operations, build_op) final_status = _GetStatusFromOp(op) if final_status != CLOUDBUILD_SUCCESS: raise BuildFailedError('Cloud build failed with status ' + final_status + '. Check logs at ' + logs_uri)
def DeleteService(self, service_name): """Deletes the specified service. Args: service_name: str, Name of the service to delete. Returns: The completed Operation. """ delete_request = self.messages.AppengineAppsServicesDeleteRequest( name=self._GetServiceRelativeName(service_name=service_name)) operation = requests.MakeRequest(self.client.apps_services.Delete, delete_request) return operations.WaitForOperation(self.client.apps_operations, operation)
def DeleteInstance(self, res): """Delete a Flexible instance. Args: res: A googleclousdk.core.Resource object. Returns: The completed Operation. """ request = self.messages.AppengineAppsServicesVersionsInstancesDeleteRequest( name=res.RelativeName()) operation = requests.MakeRequest( self.client.apps_services_versions_instances.Delete, request) return operations.WaitForOperation(self.client.apps_operations, operation)
def DeleteService(self, service_name): """Deletes the specified service. Args: service_name: str, Name of the service to delete. Returns: The completed Operation. """ delete_request = self.messages.AppengineAppsModulesDeleteRequest( name=self._FormatModule(app_id=self.project, module_name=service_name)) operation = requests.MakeRequest(self.client.apps_modules.Delete, delete_request) return operations.WaitForOperation(self.client.apps_operations, operation)
def DeleteVersion(self, service_name, version_id): """Deletes the specified version of the given service. Args: service_name: str, The service name version_id: str, The version to delete. Returns: The completed Operation. """ delete_request = self.messages.AppengineAppsServicesVersionsDeleteRequest( name=self._FormatVersion(service_name=service_name, version_id=version_id)) operation = requests.MakeRequest( self.client.apps_services_versions.Delete, delete_request) return operations.WaitForOperation(self.client.apps_operations, operation)
def DeleteVersion(self, module_name, version_id): """Deletes the specified version of the given module. Args: module_name: str, The module name version_id: str, The version to set as default. Returns: A Version resource representing the deleted version. """ delete_request = self.messages.AppengineAppsModulesVersionsDeleteRequest( name=self._FormatVersion(app_id=self.project, module_name=module_name, version_id=version_id)) operation = requests.MakeRequest( self.client.apps_modules_versions.Delete, delete_request) return operations.WaitForOperation(self.client.apps_operations, operation)
def DeleteInstance(self, service, version, instance): """Delete a Flexible instance. Args: service: str, The service id version: str, The version id instance: str, The instance id Returns: The completed Operation. """ request = self.messages.AppengineAppsServicesVersionsInstancesDeleteRequest( name=self._FormatInstance(app_id=self.project, service_name=service, version_id=version, instance_id=instance)) operation = requests.MakeRequest( self.client.apps_services_versions_instances.Delete, request) return operations.WaitForOperation(self.client.apps_operations, operation)
def SetServingStatus(self, service_name, version_id, serving_status): """Sets the serving status of the specified version. Args: service_name: str, The service name version_id: str, The version to delete. serving_status: The serving status to set. Returns: The completed Operation. """ patch_request = self.messages.AppengineAppsServicesVersionsPatchRequest( name=self._FormatVersion(app_id=self.project, service_name=service_name, version_id=version_id), version=self.messages.Version(servingStatus=serving_status), mask='servingStatus') operation = requests.MakeRequest( self.client.apps_services_versions.Patch, patch_request) return operations.WaitForOperation(self.client.apps_operations, operation)
def DeployService(self, service_name, version_id, service_config, manifest, image, endpoints_info=None): """Updates and deploys new app versions based on given config. Args: service_name: str, The service to deploy. version_id: str, The version of the service to deploy. service_config: AppInfoExternal, Service info parsed from a service yaml file. manifest: Dictionary mapping source files to Google Cloud Storage locations. image: The name of the container image. endpoints_info: EndpointsServiceInfo, Endpoints service info to be added to the AppInfoExternal configuration. Only provided when Endpoints API Management feature is enabled. Returns: A Version resource representing the deployed version. """ version_resource = self._CreateVersionResource(service_config, manifest, version_id, image, endpoints_info) create_request = self.messages.AppengineAppsServicesVersionsCreateRequest( name=self._FormatService(app_id=self.project, service_name=service_name), version=version_resource) operation = requests.MakeRequest( self.client.apps_services_versions.Create, create_request) log.debug('Received operation: [{operation}]'.format( operation=operation.name)) return operations.WaitForOperation(self.client.apps_operations, operation)
def ExecuteCloudBuild(project, bucket_ref, object_name, output_image, cloudbuild_client, http): """Execute a call to CloudBuild service and wait for it to finish. Args: project: the cloud project ID. bucket_ref: Reference to GCS bucket containing source to build. object_name: GCS object name containing source to build. output_image: GCR location for the output docker image; eg, gcr.io/test-gae/hardcoded-output-tag. cloudbuild_client: client to the Cloud Build service. http: an http provider that can be used to create api clients. Raises: BuildFailedError: when the build fails. """ builder = properties.VALUES.app.container_builder_image.Get() log.debug('Using builder image: [{0}]'.format(builder)) logs_bucket = bucket_ref.bucket build_op = cloudbuild_client.projects_builds.Create( cloudbuild_v1.CloudbuildProjectsBuildsCreateRequest( projectId=project, build=cloudbuild_v1.Build( source=cloudbuild_v1.Source( storageSource=cloudbuild_v1.StorageSource( bucket=bucket_ref.bucket, object=object_name, ), ), steps=[ cloudbuild_v1.BuildStep(name=builder, args=[output_image]) ], images=[output_image], logsBucket=logs_bucket, ), )) # Find build ID from operation metadata and print the logs URL. build_id = None if build_op.metadata is not None: for prop in build_op.metadata.additionalProperties: if prop.key == 'build': for build_prop in prop.value.object_value.properties: if build_prop.key == 'id': build_id = build_prop.value.string_value break break if build_id is None: raise BuildFailedError('Could not determine build ID') log.status.Print( 'Started cloud build [{build_id}].'.format(build_id=build_id)) log_object = CLOUDBUILD_LOGFILE_FMT_STRING.format(build_id=build_id) log_tailer = cloud_storage.LogTailer(http=http, bucket=logs_bucket, obj=log_object) logs_uri = CLOUDBUILD_LOGS_URI_TEMPLATE.format(project_id=project, build_id=build_id) log.status.Print('To see logs in the Cloud Console: ' + logs_uri) op = operations.WaitForOperation( operation_service=cloudbuild_client.operations, operation=build_op, retry_interval=1, max_retries=60 * 60, retry_callback=log_tailer.Poll) # Poll the logs one final time to ensure we have everything. We know this # final poll will get the full log contents because GCS is strongly consistent # and Container Builder waits for logs to finish pushing before marking the # build complete. log_tailer.Poll(is_last=True) final_status = _GetStatusFromOp(op) if final_status != CLOUDBUILD_SUCCESS: raise BuildFailedError('Cloud build failed with status ' + final_status + '. Check logs at ' + logs_uri)