def SetHubMembershipPath(ref, args, request): """Sets the cluster.hub.membership field with a relative resource path. Args: ref: reference to the membership object. args: command line arguments. request: API request to be issued Returns: modified request """ release_track = args.calliope_command.ReleaseTrack() msgs = util.GetMessagesModule(release_track) if flags.FlagIsExplicitlySet(args, 'hub_membership'): # Populate hub membership with a relative resource path using the same # project as the cluster, and --hub-membership as the membership id. hub_membership = resources.REGISTRY.Create( 'gkehub.projects.locations.memberships', projectsId=ref.projectsId, locationsId='global', # All Hub memberships are global. membershipsId=args.hub_membership) request.cluster.hub.membership = hub_membership.RelativeName() elif flags.FlagIsExplicitlySet(args, 'fleet_project'): request.cluster.fleet = msgs.Fleet() request.cluster.fleet.project = 'projects/' + args.fleet_project else: request.cluster.fleet = msgs.Fleet() request.cluster.fleet.project = 'projects/' + ref.projectsId return request
def ClearMaintenanceWindow(ref, args, request): """Clears cluster.maintenance_policy in the request if --clear-maintenance-window flag is specified. Args: ref: reference to the cluster object. args: command line arguments. request: API request to be issued Returns: modified request """ del ref # unused argument if not flags.FlagIsExplicitlySet(args, "clear_maintenance_window"): return request if not args.clear_maintenance_window: raise exceptions.BadArgumentException("--no-clear-maintenance-window", "The flag is not supported") if request.cluster is None: release_track = args.calliope_command.ReleaseTrack() request.cluster = util.GetMessagesModule(release_track).Cluster() request.cluster.maintenancePolicy = None _AddFieldToUpdateMask("maintenancePolicy", request) return request
def Run(self, args): """Deploy a container to Cloud Run.""" service_ref = flags.GetService(args) image = args.image # Build an image from source if source specified. if flags.FlagIsExplicitlySet(args, 'source'): # Create a tag for the image creation if image is None and not args.IsSpecified('config'): image = 'gcr.io/{projectID}/cloud-run-source-deploy/{service}:{tag}'.format( projectID=properties.VALUES.core.project.Get(required=True), service=service_ref.servicesId, tag=uuid.uuid4().hex) messages = cloudbuild_util.GetMessagesModule() build_config = submit_util.CreateBuildConfig( image, args.no_cache, messages, args.substitutions, args.config, args.IsSpecified('source'), False, args.source, args.gcs_source_staging_dir, args.ignore_file, args.gcs_log_dir, args.machine_type, args.disk_size) submit_util.Build(messages, args.async_, build_config) # Deploy a container with an image conn_context = connection_context.GetConnectionContext( args, flags.Product.RUN, self.ReleaseTrack()) config_changes = flags.GetConfigurationChanges(args) with serverless_operations.Connect(conn_context) as operations: image_change = config_changes_mod.ImageChange(image) changes = [image_change] if config_changes: changes.extend(config_changes) service = operations.GetService(service_ref) allow_unauth = GetAllowUnauth(args, operations, service_ref, service) pretty_print.Info(GetStartDeployMessage(conn_context, service_ref)) has_latest = (service is None or traffic.LATEST_REVISION_KEY in service.spec_traffic) deployment_stages = stages.ServiceStages( include_iam_policy_set=allow_unauth is not None, include_route=has_latest) header = 'Deploying...' if service else 'Deploying new service...' with progress_tracker.StagedProgressTracker( header, deployment_stages, failure_message='Deployment failed', suppress_output=args.async_) as tracker: operations.ReleaseService( service_ref, changes, tracker, asyn=args.async_, allow_unauthenticated=allow_unauth, prefetch=service) if args.async_: pretty_print.Success( 'Service [{{bold}}{serv}{{reset}}] is deploying ' 'asynchronously.'.format(serv=service_ref.servicesId)) else: pretty_print.Success(GetSuccessMessageForSynchronousDeploy( operations, service_ref))
def ValidateClearVpcConnector(service, args): """Validates that the VPC connector can be safely removed. Does nothing if 'clear_vpc_connector' is not present in args with value True. Args: service: A Cloud Run service object. args: Namespace object containing the specified command line arguments. Raises: exceptions.ConfigurationError: If the command cannot prompt and VPC egress is set to 'all' or 'all-traffic'. console_io.OperationCancelledError: If the user answers no to the confirmation prompt. """ if (service is None or not flags.FlagIsExplicitlySet(args, 'clear_vpc_connector') or not args.clear_vpc_connector): return if flags.FlagIsExplicitlySet(args, 'vpc_egress'): egress = args.vpc_egress elif container_resource.EGRESS_SETTINGS_ANNOTATION in service.template_annotations: egress = service.template_annotations[ container_resource.EGRESS_SETTINGS_ANNOTATION] else: # --vpc-egress flag not specified and egress settings not set on service. return if (egress != container_resource.EGRESS_SETTINGS_ALL and egress != container_resource.EGRESS_SETTINGS_ALL_TRAFFIC): return if console_io.CanPrompt(): console_io.PromptContinue( message= 'Removing the VPC connector from this service will clear the ' 'VPC egress setting and route outbound traffic to the public internet.', default=False, cancel_on_no=True) else: raise exceptions.ConfigurationError( 'Cannot remove VPC connector with VPC egress set to "{}". Set' ' `--vpc-egress=private-ranges-only` or run this command ' 'interactively and provide confirmation to continue.'.format( egress))
def SetAdminUsers(ref, args, request): """Sets the cluster.authorization.admin_users to the user if unspecified. Args: ref: reference to the membership object. args: command line arguments. request: API request to be issued Returns: modified request """ del ref # unused argument # If the argument is set, don't change it. if flags.FlagIsExplicitlySet(args, 'admin_users'): return request if properties.VALUES.auth.credential_file_override.Get() is not None: raise gcloud_exceptions.RequiredArgumentException( '--admin-users', 'Required if auth/credential_file_override is defined.') release_track = args.calliope_command.ReleaseTrack() msgs = util.GetMessagesModule(release_track) service_account_override = properties.VALUES.auth.impersonate_service_account.Get( ) request.cluster.authorization = msgs.Authorization() request.cluster.authorization.adminUsers = msgs.ClusterUser() if service_account_override is not None: request.cluster.authorization.adminUsers.username = service_account_override else: default_account = properties.VALUES.core.account.Get() if default_account is None: raise gcloud_exceptions.RequiredArgumentException( '--admin-users', 'Required if no account is active and --impersonate-service-account is undefined.' ) request.cluster.authorization.adminUsers.username = default_account return request
def Run(self, args): """Deploy a container to Cloud Run.""" platform = flags.GetAndValidatePlatform(args, self.ReleaseTrack(), flags.Product.RUN) include_build = flags.FlagIsExplicitlySet(args, 'source') if not include_build and not args.IsSpecified('image'): if console_io.CanPrompt(): args.source = flags.PromptForDefaultSource() include_build = True else: raise c_exceptions.RequiredArgumentException( '--image', 'Requires a container image to deploy (e.g. ' '`gcr.io/cloudrun/hello:latest`) if no build source is provided.' ) service_ref = args.CONCEPTS.service.Parse() flags.ValidateResource(service_ref) # Obtaining the connection context prompts the user to select a region if # one hasn't been provided. We want to do this prior to preparing a source # deploy so that we can use that region for the Artifact Registry repo. conn_context = connection_context.GetConnectionContext( args, flags.Product.RUN, self.ReleaseTrack()) build_type = None image = None pack = None source = None operation_message = 'Deploying container to' repo_to_create = None # Build an image from source if source specified if include_build: source = args.source ar_repo = docker_util.DockerRepo( project_id=properties.VALUES.core.project.Get(required=True), location_id=artifact_registry.RepoRegion( args, cluster_location=(conn_context.cluster_location if platform == platforms.PLATFORM_GKE else None)), repo_id='cloud-run-source-deploy') if artifact_registry.ShouldCreateRepository(ar_repo): repo_to_create = ar_repo # The image is built with latest tag. After build, the image digest # from the build result will be added to the image of the service spec. args.image = '{repo}/{service}'.format( repo=ar_repo.GetDockerString(), service=service_ref.servicesId) # Use GCP Buildpacks if Dockerfile doesn't exist docker_file = source + '/Dockerfile' if os.path.exists(docker_file): build_type = BuildType.DOCKERFILE else: pack = [{'image': args.image}] build_type = BuildType.BUILDPACKS image = None if pack else args.image operation_message = ( 'Building using {build_type} and deploying container' ' to').format(build_type=build_type.value) pretty_print.Info( messages_util.GetBuildEquivalentForSourceRunMessage( service_ref.servicesId, pack, source)) # Deploy a container with an image changes = flags.GetServiceConfigurationChanges(args) changes.insert( 0, config_changes.DeleteAnnotationChange( k8s_object.BINAUTHZ_BREAKGLASS_ANNOTATION)) changes.append( config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack())) with serverless_operations.Connect(conn_context) as operations: service = operations.GetService(service_ref) allow_unauth = GetAllowUnauth(args, operations, service_ref, service) resource_change_validators.ValidateClearVpcConnector(service, args) pretty_print.Info( messages_util.GetStartDeployMessage(conn_context, service_ref, operation_message)) has_latest = (service is None or traffic.LATEST_REVISION_KEY in service.spec_traffic) deployment_stages = stages.ServiceStages( include_iam_policy_set=allow_unauth is not None, include_route=has_latest, include_build=include_build, include_create_repo=repo_to_create is not None, ) header = None if include_build: header = 'Building and deploying' else: header = 'Deploying' if service is None: header += ' new service' header += '...' with progress_tracker.StagedProgressTracker( header, deployment_stages, failure_message='Deployment failed', suppress_output=args.async_) as tracker: service = operations.ReleaseService( service_ref, changes, tracker, asyn=args.async_, allow_unauthenticated=allow_unauth, prefetch=service, build_image=image, build_pack=pack, build_source=source, repo_to_create=repo_to_create) if args.async_: pretty_print.Success( 'Service [{{bold}}{serv}{{reset}}] is deploying ' 'asynchronously.'.format(serv=service.name)) else: service = operations.GetService(service_ref) pretty_print.Success( messages_util.GetSuccessMessageForSynchronousDeploy( service)) return service
def Run(self, args): """Deploy a container to Cloud Run.""" flags.GetAndValidatePlatform(args, self.ReleaseTrack(), flags.Product.RUN) service_ref = args.CONCEPTS.service.Parse() flags.ValidateResource(service_ref) build_type = None image = None pack = None source = None include_build = flags.FlagIsExplicitlySet(args, 'source') operation_message = 'Deploying container' # Build an image from source if source specified if include_build: # Create a tag for the image creation source = args.source if not args.IsSpecified('image'): args.image = 'gcr.io/{projectID}/cloud-run-source-deploy/{service}:{tag}'.format( projectID=properties.VALUES.core.project.Get( required=True), service=service_ref.servicesId, tag=uuid.uuid4().hex) # Use GCP Buildpacks if Dockerfile doesn't exist docker_file = args.source + '/Dockerfile' if os.path.exists(docker_file): build_type = BuildType.DOCKERFILE else: pack = [{'image': args.image}] build_type = BuildType.BUILDPACKS image = None if pack else args.image operation_message = 'Building using {build_type} and deploying container'.format( build_type=build_type.value) elif not args.IsSpecified('image'): raise c_exceptions.RequiredArgumentException( '--image', 'Requires a container image to deploy (e.g. ' '`gcr.io/cloudrun/hello:latest`) if no build source is provided.' ) # Deploy a container with an image conn_context = connection_context.GetConnectionContext( args, flags.Product.RUN, self.ReleaseTrack()) changes = flags.GetConfigurationChanges(args) changes.insert( 0, config_changes.DeleteAnnotationChange( k8s_object.BINAUTHZ_BREAKGLASS_ANNOTATION)) changes.append( config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack())) with serverless_operations.Connect(conn_context) as operations: service = operations.GetService(service_ref) allow_unauth = GetAllowUnauth(args, operations, service_ref, service) resource_change_validators.ValidateClearVpcConnector(service, args) pretty_print.Info( messages_util.GetStartDeployMessage(conn_context, service_ref, operation_message)) has_latest = (service is None or traffic.LATEST_REVISION_KEY in service.spec_traffic) deployment_stages = stages.ServiceStages( include_iam_policy_set=allow_unauth is not None, include_route=has_latest, include_build=include_build) header = None if include_build: header = 'Building and deploying' else: header = 'Deploying' if service is None: header += ' new service' header += '...' with progress_tracker.StagedProgressTracker( header, deployment_stages, failure_message='Deployment failed', suppress_output=args.async_) as tracker: service = operations.ReleaseService( service_ref, changes, tracker, asyn=args.async_, allow_unauthenticated=allow_unauth, prefetch=service, build_image=image, build_pack=pack, build_source=source) if args.async_: pretty_print.Success( 'Service [{{bold}}{serv}{{reset}}] is deploying ' 'asynchronously.'.format(serv=service.name)) else: service = operations.GetService(service_ref) pretty_print.Success( messages_util.GetSuccessMessageForSynchronousDeploy( service)) return service