def ValidateInstanceLocation(args): """Construct a Cloud SQL instance from command line args. Args: args: argparse.Namespace, The CLI arg namespace. Raises: RequiredArgumentException: Zone is required. ConflictingArgumentsException: Zones in arguments belong to different regions. """ if args.IsSpecified('secondary_zone') and not args.IsSpecified('zone'): raise exceptions.RequiredArgumentException( '--zone', '`--zone` is required if --secondary-zone is used ' 'while creating an instance.') if args.IsSpecified('secondary_zone') and args.IsSpecified('zone'): if args.zone == args.secondary_zone: raise exceptions.ConflictingArgumentsException( 'Zones in arguments --zone and --secondary-zone are identical.' ) region_from_zone = api_util.GetRegionFromZone(args.zone) region_from_secondary_zone = api_util.GetRegionFromZone( args.secondary_zone) if region_from_zone != region_from_secondary_zone: raise exceptions.ConflictingArgumentsException( 'Zones in arguments --zone and --secondary-zone ' 'belong to different regions.')
def ValidateArgs(args): if args.main_boot_disk_size_gb: log.warn( 'The --main-boot-disk-size-gb flag is deprecated. ' 'Use equivalent --main-boot-disk-size=%sGB flag.', args.main_boot_disk_size_gb) if args.worker_boot_disk_size_gb: log.warn( 'The --worker-boot-disk-size-gb flag is deprecated. ' 'Use equivalent --worker-boot-disk-size=%sGB flag.', args.worker_boot_disk_size_gb) if args.single_node: if args.num_workers: raise exceptions.ConflictingArgumentsException( '--single-node', '--num-workers') if args.num_preemptible_workers: raise exceptions.ConflictingArgumentsException( '--single-node', '--num-preemptible-workers') if constants.ALLOW_ZERO_WORKERS_PROPERTY in args.properties: raise exceptions.InvalidArgumentException( '--properties', 'Instead of %s, use gcloud beta dataproc clusters create ' '--single-node to deploy single node clusters' % constants.ALLOW_ZERO_WORKERS_PROPERTY)
def Run(self, args): secret_ref = args.CONCEPTS.secret.Parse() if not args.remove_cmek and not args.set_kms_key: raise calliope_exceptions.MinimumArgumentException( ['--remove-cmek', '--set-kms-key']) if args.remove_cmek and args.set_kms_key: raise calliope_exceptions.ConflictingArgumentsException( self.REMOVE_AND_SET_CMEK_MESSAGE) if args.remove_cmek and args.location: raise calliope_exceptions.ConflictingArgumentsException( self.REMOVE_CMEK_AND_LOCATION_MESSAGE) # args.set_kms_key without args.location is allowed only if the secret has # a single replica. # Attempt to get the secret secret = secrets_api.Secrets().GetOrNone(secret_ref) # Secret does not exist if secret is None: raise calliope_exceptions.InvalidArgumentException( 'secret', self.SECRET_MISSING_MESSAGE.format(secret=secret_ref.Name())) if args.remove_cmek: return self._RemoveCmek(secret_ref, secret) return self._SetKmsKey(secret_ref, secret, args.set_kms_key, args.location)
def _CheckForConflictingArgs(self, args): """Check for any args that cannot appear simultaneously.""" if args.device: # If using sparse matrix syntax, can't also use legacy dimension flags. if args.device_ids: raise exceptions.ConflictingArgumentsException('--device-ids', '--device') if args.os_version_ids: raise exceptions.ConflictingArgumentsException('--os-version-ids', '--device') if args.locales: raise exceptions.ConflictingArgumentsException('--locales', '--device') if args.orientations: raise exceptions.ConflictingArgumentsException('--orientations', '--device')
def MaybeGetKmsKey(args, messages, current_value, boot_disk_prefix=False): """Gets the Cloud KMS CryptoKey reference from command arguments. Args: args: Namespaced command line arguments. messages: Compute API messages module. current_value: Current CustomerEncryptionKey value. boot_disk_prefix: If the key flags have the 'boot-disk' prefix. Returns: CustomerEncryptionKey message with the KMS key populated if args has a key. Raises: ConflictingArgumentsException if an encryption key is already populated. """ key_arg = args.CONCEPTS.kms_key key = key_arg.Parse() if bool(_GetSpecifiedKmsArgs(args)) and not key: flag = '--boot-disk-kms-key' if boot_disk_prefix else '--kms-key' raise calliope_exceptions.InvalidArgumentException( flag, 'KMS cryptokey resource was not fully specified.') if key: if current_value: raise calliope_exceptions.ConflictingArgumentsException( '--csek-key-file', *_GetSpecifiedKmsArgs(args)) return messages.CustomerEncryptionKey(kmsKeyName=key.RelativeName()) return current_value
def Run(self, args): iam_client = apis.GetClientInstance('iam', 'v1') messages = apis.GetMessagesModule('iam', 'v1') parent_name = iam_util.GetParentName(args.organization, args.project) if args.file: if args.title or args.description or args.stage or args.permissions: raise exceptions.ConflictingArgumentsException('file', 'others') role = iam_util.ParseYamlToRole(args.file, messages.Role) role.name = None role.etag = None else: role = messages.Role(title=args.title, description=args.description) if args.permissions: role.includedPermissions = args.permissions.split(',') if args.stage: role.stage = iam_util.StageTypeFromString(args.stage) if not role.title: role.title = args.role if not args.quiet: testing_permissions = util.GetTestingPermissions( iam_client, messages, iam_util.GetResourceReference(args.project, args.organization), role.includedPermissions) iam_util.TestingPermissionsWarning(testing_permissions) result = iam_client.organizations_roles.Create( messages.IamOrganizationsRolesCreateRequest( createRoleRequest=messages.CreateRoleRequest( role=role, roleId=args.role), parent=parent_name)) log.CreatedResource(args.role, kind='role') iam_util.SetRoleStageIfAlpha(result) return result
def ValidateServiceProxyFlags(args): """Validates the values of all --service-proxy related flags.""" if getattr(args, 'service_proxy', False): if args.no_scopes: # --no-scopes flag needs to be removed for adding cloud-platform scope. # This is required for TrafficDirector to work properly. raise exceptions.ConflictingArgumentsException('--service-proxy', '--no-scopes') if 'serving-ports' in args.service_proxy: try: serving_ports = list( map(int, args.service_proxy['serving-ports'].split(';'))) for port in serving_ports: if port < 1 or port > 65535: # valid port range is 1 - 65535 raise ValueError except ValueError: # an invalid port is present in the list of workload ports. raise exceptions.InvalidArgumentException( 'serving-ports', 'List of ports can only contain numbers between 1 and 65535.') if 'proxy-port' in args.service_proxy: try: proxy_port = args.service_proxy['proxy-port'] if proxy_port < 1025 or proxy_port > 65535: # valid range for proxy-port is 1025 - 65535 raise ValueError except ValueError: raise exceptions.InvalidArgumentException( 'proxy-port', 'Port value can only be between 1025 and 65535.')
def CreateRequests(self, args): group_ref = self.CreateGroupReference(args) if group_ref.Collection() == 'compute.instanceGroupManagers': service = self.compute.instanceGroupManagers method = 'ResizeAdvanced' request = self.messages.ComputeInstanceGroupManagersResizeAdvancedRequest( instanceGroupManager=group_ref.Name(), instanceGroupManagersResizeAdvancedRequest=( self.messages.InstanceGroupManagersResizeAdvancedRequest( targetSize=args.size, noCreationRetries=not args.creation_retries, )), project=group_ref.project, zone=group_ref.zone, ) else: if not args.creation_retries: raise exceptions.ConflictingArgumentsException( '--no-creation-retries', '--region') service = self.compute.regionInstanceGroupManagers method = 'Resize' request = self.messages.ComputeRegionInstanceGroupManagersResizeRequest( instanceGroupManager=group_ref.Name(), size=args.size, project=group_ref.project, region=group_ref.region, ) return [(service, method, request)]
def ValidateMeshModeFlags(args): """Validates the values of all mesh-mode related flags.""" if getattr(args, 'mesh', False): if args.no_scopes and args.mesh[ 'mode'] == mesh_mode_aux_data.MeshModes.ON: # --no-scopes flag needs to be removed for adding cloud-platform scope. # This is required for TrafficDirector to work properly. raise exceptions.ConflictingArgumentsException( '--mesh', '--no-scopes') if 'workload-ports' in args.mesh: try: workload_ports = list( map(int, args.mesh['workload-ports'].split(';'))) for port in workload_ports: if port < 1 or port > 65535: # valid port range is 1 - 65535 raise ValueError except ValueError: # an invalid port is present in the list of workload ports. raise exceptions.InvalidArgumentException( 'workload-ports', 'List of ports can only contain numbers between 1 and 65535.' )
def _ValidateArgs(self, args): if getattr(args, 'user_accounts', None) is None: return for arg in ['global', 'region', 'zone']: if getattr(args, arg, None): raise exceptions.ConflictingArgumentsException( '--user-accounts', '--' + arg)
def VerifyParent(organization, project, folder, attribute='root cloud asset'): """Verify the parent name.""" if organization is None and project is None and folder is None: raise gcloud_exceptions.RequiredArgumentException( '--organization or --project or --folder', 'Should specify the project, or organization name, or the folder for ' '{0}.'.format(attribute)) if organization and project: raise gcloud_exceptions.ConflictingArgumentsException( 'organization', 'project') if organization and folder: raise gcloud_exceptions.ConflictingArgumentsException( 'organization', 'folder') if project and folder: raise gcloud_exceptions.ConflictingArgumentsException( 'project', 'folder')
def ValidateTriggerArgs(trigger_event, trigger_resource, retry_specified, trigger_http_specified): """Check if args related function triggers are valid. Args: trigger_event: The trigger event trigger_resource: The trigger resource retry_specified: Whether or not `--retry` was specified trigger_http_specified: Whether or not `--trigger-http` was specified Raises: FunctionsError. """ # Check that Event Type is valid trigger_provider = triggers.TRIGGER_PROVIDER_REGISTRY.ProviderForEvent( trigger_event) trigger_provider_label = trigger_provider.label if trigger_provider_label != triggers.UNADVERTISED_PROVIDER_LABEL: resource_type = triggers.TRIGGER_PROVIDER_REGISTRY.Event( trigger_provider_label, trigger_event).resource_type if trigger_resource is None and resource_type != triggers.Resources.PROJECT: raise exceptions.FunctionsError( 'You must provide --trigger-resource when using ' '--trigger-event={}'.format(trigger_event)) if retry_specified and trigger_http_specified: raise calliope_exceptions.ConflictingArgumentsException( '--trigger-http', '--retry')
def Run(self, args): # Validate labels flags if args.clear_labels and (args.update_labels or args.remove_labels): conflict = '--update-labels' if args.update_labels else '--remove-labels' raise exceptions.ConflictingArgumentsException( '--clear-labels', conflict) return RunBasePatchCommand(args)
def ParseMessageBody(args): """Gets the message body from args. This is only necessary because we are deprecating the positional `ack_id`. Putting the positional and a flag in an argument group, will group flag under positional args. This would be confusing. DeprecationAction can't be used here because the positional argument is optional (nargs='?') Since this means zero or more, the DeprecationAction warn message is always triggered. This function does not exist in util.py in order to group the explanation for why this exists with the deprecated flags. Once the positional is removed, this function can be removed. Args: args (argparse.Namespace): Parsed arguments Returns: Optional[str]: message body. """ if args.message_body and args.message: raise exceptions.ConflictingArgumentsException('MESSAGE_BODY', '--message') if args.message_body is not None: log.warning(DEPRECATION_FORMAT_STR.format('MESSAGE_BODY', '--message')) return args.message_body or args.message
def _ValidateTriggerArgs(args): """Check if args related function triggers are valid. Args: args: parsed command line arguments. Raises: FunctionsError. """ # checked that Event Type is valid trigger_event = args.trigger_event trigger_resource = args.trigger_resource if trigger_event: trigger_provider = util.input_trigger_provider_registry.ProviderForEvent( trigger_event).label if not trigger_provider: raise exceptions.FunctionsError( 'Unsupported trigger_event {}'.format(trigger_event)) resource_type = util.input_trigger_provider_registry.Event( trigger_provider, trigger_event).resource_type if trigger_resource is None and resource_type != util.Resources.PROJECT: raise exceptions.FunctionsError( 'You must provide --trigger-resource when using ' '--trigger-event={}'.format(trigger_event)) if args.IsSpecified('retry') and args.IsSpecified('trigger_http'): raise calliope_exceptions.ConflictingArgumentsException( '--trigger-http', '--retry')
def GetZoneOrRegion(args, ignore_property=False, required=True): """Get a location (zone or region) from argument or property. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. ignore_property: bool, if true, will get location only from argument. required: bool, if true, lack of zone will cause raise an exception. Raises: MinimumArgumentException: if location if required and not provided. ConflictingArgumentsException: if both --zone and --region arguments provided. Returns: str, a location selected by user. """ zone = getattr(args, 'zone', None) region = getattr(args, 'region', None) if ignore_property: zone_property = None else: zone_property = properties.VALUES.compute.zone.Get() if zone and region: raise calliope_exceptions.ConflictingArgumentsException( '--zone', '--region') location = region or zone or zone_property if required and not location: raise calliope_exceptions.MinimumArgumentException( ['--zone', '--region'], 'Please specify location.') return location
def ValidateManagedInstanceGroupScopeArgs(args, resources): """Validate arguments specifying scope of the managed instance group.""" ignored_required_params = {'project': 'fake'} if args.zones and args.zone: raise exceptions.ConflictingArgumentsException('--zone', '--zones') zone_names = [] for zone in args.zones: zone_ref = resources.Parse(zone, collection='compute.zones', params=ignored_required_params) zone_names.append(zone_ref.Name()) zone_regions = set([utils.ZoneNameToRegionName(z) for z in zone_names]) if len(zone_regions) > 1: raise exceptions.InvalidArgumentException( '--zones', 'All zones must be in the same region.') elif len(zone_regions) == 1 and args.region: zone_region = zone_regions.pop() region_ref = resources.Parse(args.region, collection='compute.regions', params=ignored_required_params) region = region_ref.Name() if zone_region != region: raise exceptions.InvalidArgumentException( '--zones', 'Specified zones not in specified region.')
def Run(self, args): holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = holder.client igm_ref = self.CreateGroupReference(client, holder.resources, args) if igm_ref.Collection() == 'compute.instanceGroupManagers': service = client.apitools_client.instanceGroupManagers method = 'ResizeAdvanced' request = (client.messages. ComputeInstanceGroupManagersResizeAdvancedRequest( instanceGroupManager=igm_ref.Name(), instanceGroupManagersResizeAdvancedRequest=( client.messages. InstanceGroupManagersResizeAdvancedRequest( targetSize=args.size, noCreationRetries=not args.creation_retries, )), project=igm_ref.project, zone=igm_ref.zone)) else: if not args.creation_retries: raise exceptions.ConflictingArgumentsException( '--no-creation-retries', '--region') service = client.apitools_client.regionInstanceGroupManagers method = 'Resize' request = client.messages.ComputeRegionInstanceGroupManagersResizeRequest( instanceGroupManager=igm_ref.Name(), size=args.size, project=igm_ref.project, region=igm_ref.region) return client.MakeRequests([(service, method, request)])
def ParseAckIdsArgs(args): """Gets the list of ack_ids from args. This is only necessary because we are deprecating the positional `ack_id`. Putting the positional and a flag in an argument group, will group flag under positional args. This would be confusing. DeprecationAction can't be used here because in order to make the positional argument optional, we have to use `nargs='*'`. Since this means zero or more, the DeprecationAction warn message is always triggered. This function does not exist in util.py in order to group the explanation for why this exists with the deprecated flags. Once the positional is removed, this function can be removed. Args: args (argparse.Namespace): Parsed arguments Returns: list[str]: List of ack ids. """ if args.ack_id and args.ack_ids: raise exceptions.ConflictingArgumentsException('ACK_ID', '--ack-ids') elif not (args.ack_id or args.ack_ids): raise exceptions.MinimumArgumentException(['ACK_ID', '--ack-ids']) else: if args.ack_id: log.warning(DEPRECATION_FORMAT_STR.format('ACK_ID', '--ack-ids')) ack_ids = args.ack_id or args.ack_ids if not isinstance(ack_ids, list): ack_ids = [ack_ids] return ack_ids
def ValidateNicFlags(args): """Valiadates flags specifying network interface cards. Args: args: parsed comandline arguments. Raises: InvalidArgumentException: when it finds --network-interface that has both address, and no-address keys. ConflictingArgumentsException: when it finds --network-interface and at least one of --address, --network, --private_network_ip, or --subnet. """ network_interface = getattr(args, 'network_interface', None) if network_interface is None: return for ni in network_interface: if 'address' in ni and 'no-address' in ni: raise exceptions.InvalidArgumentException( '--network-interface', 'specifies both address and no-address for one interface') conflicting_args = [ 'address', 'network', 'private_network_ip', 'subnet'] conflicting_args_present = [ arg for arg in conflicting_args if getattr(args, arg, None)] if not conflicting_args_present: return conflicting_args = ['--{0}'.format(arg.replace('_', '-')) for arg in conflicting_args_present] raise exceptions.ConflictingArgumentsException( '--network-interface', 'all of the following: ' + ', '.join(conflicting_args))
def CheckParentFlags(args, parent_required=True): if args.folder and args.organization: raise exceptions.ConflictingArgumentsException('--folder', '--organization') if parent_required and not args.folder and not args.organization: raise exceptions.ToolException( 'Neither --folder nor --organization provided, exactly one required' )
def CheckResourceFlags(args): if args.project and args.organization: raise exceptions.ConflictingArgumentsException('--organization', '--project') if not args.project and not args.organization: raise exceptions.ToolException( 'Neither --project nor --organization provided, exactly one required' )
def Run(self, args): if args.IsSpecified('limit'): if args.IsSpecified('max_messages'): raise exceptions.ConflictingArgumentsException( '--max-messages', '--limit') max_messages = args.limit else: max_messages = args.max_messages return _Run(args, max_messages)
def _ValidateArgs(args): if (args.size is None and args.suspended_size is None and args.stopped_size is None): raise exceptions.OneOfArgumentsRequiredException( ['--size', '--suspended-size', '--stopped-size'], 'At least one of the sizes must be specified') if not args.creation_retries: if args.size is None: raise exceptions.RequiredArgumentException( '--size', 'Size must be specified when --no-creation-retries flag is used.' ) if args.suspended_size is not None: raise exceptions.ConflictingArgumentsException( '--suspended-size', '--no-creation-retries') if args.stopped_size is not None: raise exceptions.ConflictingArgumentsException( '--stopped-size', '--no-creation-retries')
def ValidateArgs(args): if args.single_node: # --num-workers and --num-preemptible-workers must be None (unspecified) # or 0 if args.num_workers: raise exceptions.ConflictingArgumentsException( '--single-node', '--num-workers') if args.num_preemptible_workers: raise exceptions.ConflictingArgumentsException( '--single-node', '--num-preemptible-workers') if constants.ALLOW_ZERO_WORKERS_PROPERTY in args.properties: raise exceptions.InvalidArgumentException( '--properties', 'Instead of %s, use gcloud beta dataproc clusters create ' '--single-node to deploy single node clusters' % constants.ALLOW_ZERO_WORKERS_PROPERTY)
def CreateRequests(self, args): """Returns a list of requests necessary for adding images.""" image = self.messages.Image( name=args.name, description=args.description, sourceType=self.messages.Image.SourceTypeValueValuesEnum.RAW, family=args.family) csek_keys = csek_utils.CsekKeyStore.FromArgs( args, self._ALLOW_RSA_ENCRYPTED_CSEK_KEYS) if csek_keys: image_ref = self.resources.Parse(args.name, collection='compute.images') image.imageEncryptionKey = csek_utils.MaybeToMessage( csek_keys.LookupKey( image_ref, raise_if_missing=args.require_csek_key_create), self.compute_client.apitools_client) # Validate parameters. if args.source_disk_zone and not args.source_disk: raise exceptions.ToolException( 'You cannot specify [--source-disk-zone] unless you are specifying ' '[--source-disk].') if args.source_disk and args.source_uri: raise exceptions.ConflictingArgumentsException( '--source-uri', '--source-disk') if not (args.source_disk or args.source_uri): raise exceptions.MinimumArgumentException([ '--source-uri', '--source-disk' ], 'Please specify either the source disk or the Google Cloud Storage ' 'URI of the disk image.') # TODO(user): use resources.REGISTRY.Parse() for GCS URIs (b/30086260). if args.source_uri: source_uri = utils.NormalizeGoogleStorageUri(args.source_uri) image.rawDisk = self.messages.Image.RawDiskValue(source=source_uri) else: source_disk_ref = flags.SOURCE_DISK_ARG.ResolveAsResource( args, self.resources, scope_lister=compute_flags.GetDefaultScopeLister( self.compute_client, self.project)) image.sourceDisk = source_disk_ref.SelfLink() image.sourceDiskEncryptionKey = csek_utils.MaybeLookupKeyMessage( csek_keys, source_disk_ref, self.compute_client.apitools_client) if args.licenses: image.licenses = args.licenses request = self.messages.ComputeImagesInsertRequest( image=image, project=self.project) return [request]
def CheckResourceFlags(args): if [bool(a) for a in [args.project, args.organization, args.folder]].count(True) > 1: raise exceptions.ConflictingArgumentsException('--organization', '--project', '--folder') if not (args.project or args.organization or args.folder): raise exceptions.ToolException( 'Neither --project nor --organization nor --folder provided, exactly ' 'one required')
def ValidateConflictsWithAutoscalingFile(args, conflicting_args): if (hasattr(args, 'autoscaling_file') and args.IsSpecified('autoscaling_file')): for arg in conflicting_args: if args.IsSpecified(arg): conflicting_flags = [ '--' + a.replace('_', '-') for a in conflicting_args ] raise exceptions.ConflictingArgumentsException( *(['--autoscaling-file'] + conflicting_flags))
def VerifyParent(organization, project, attribute='custom roles'): """Verify the parent name.""" if organization is None and project is None: raise gcloud_exceptions.RequiredArgumentException( '--organization or --project', 'Should specify the project or organization name for {0}.'.format( attribute)) if organization and project: raise gcloud_exceptions.ConflictingArgumentsException( 'organization', 'project')
def Run(self, args): if args.IsSpecified('limit'): if args.IsSpecified('max_messages'): raise exceptions.ConflictingArgumentsException('--max-messages', '--limit') max_messages = args.limit else: max_messages = args.max_messages return_immediately = not args.wait if args.IsSpecified('wait') else True return _Run(args, max_messages, return_immediately)