def Modify(self, resources, args, instance_ref, existing): replacement = encoding.CopyProtoMessage(existing) if args.disk: disk_ref = self.ParseDiskRef(resources, args, instance_ref) replacement.disks = [ disk for disk in existing.disks if not disk.source or resources.ParseURL( disk.source).RelativeName() != disk_ref.RelativeName() ] if len(existing.disks) == len(replacement.disks): raise compute_exceptions.ArgumentError( 'Disk [{0}] is not attached to instance [{1}] in zone [{2}].' .format(disk_ref.Name(), instance_ref.instance, instance_ref.zone)) else: replacement.disks = [ disk for disk in existing.disks if disk.deviceName != args.device_name ] if len(existing.disks) == len(replacement.disks): raise compute_exceptions.ArgumentError( 'No disk with device name [{0}] is attached to instance [{1}] in ' 'zone [{2}].'.format(args.device_name, instance_ref.instance, instance_ref.zone)) return replacement
def GetHealthCheckUris(args, resource_resolver, resource_parser): """Returns health check URIs from arguments.""" health_check_refs = [] if args.http_health_checks: health_check_refs.extend( resource_resolver.HTTP_HEALTH_CHECK_ARG.ResolveAsResource( args, resource_parser)) if getattr(args, 'https_health_checks', None): health_check_refs.extend( resource_resolver.HTTPS_HEALTH_CHECK_ARG.ResolveAsResource( args, resource_parser)) if getattr(args, 'health_checks', None): if health_check_refs: raise compute_exceptions.ArgumentError( 'Mixing --health-checks with --http-health-checks or with ' '--https-health-checks is not supported.') else: health_check_refs.extend( resource_resolver.HEALTH_CHECK_ARG.ResolveAsResource( args, resource_parser, default_scope=compute_scope.ScopeEnum.GLOBAL)) if health_check_refs and getattr(args, 'no_health_checks', None): raise compute_exceptions.ArgumentError( 'Combining --health-checks, --http-health-checks, or ' '--https-health-checks with --no-health-checks is not supported.') return [health_check_ref.SelfLink() for health_check_ref in health_check_refs]
def Run(self, args): """Issues a TargetPools.RemoveInstance request.""" holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = holder.client if args.zone and not args.instances_zone: args.instances_zone = args.zone log.warning( 'The --zone flag is deprecated. Use equivalent ' '--instances-zone=%s flag.', args.instances_zone) instance_refs = self.INSTANCE_ARG.ResolveAsResource( args, holder.resources, scope_lister=compute_flags.GetDefaultScopeLister(client)) instances = [ client.messages.InstanceReference(instance=instance_ref.SelfLink()) for instance_ref in instance_refs ] # This check to make sure the regions for the instances are the same is not # really necessary, but it does allow for a fast fail if the user passes in # instances from different regions. unique_regions = set( utils.ZoneNameToRegionName(instance_ref.zone) for instance_ref in instance_refs) if len(unique_regions) > 1: raise compute_exceptions.ArgumentError( 'Instances must all be in the same region as the target pool.') region = unique_regions.pop() # Check that the region of the instances is the same as target pool region. if args.region and region != args.region: raise compute_exceptions.ArgumentError( 'Instances must all be in the same region as the target pool.') args.region = region target_pool_ref = self.TARGET_POOL_ARG.ResolveAsResource( args, holder.resources) request = client.messages.ComputeTargetPoolsRemoveInstanceRequest( region=target_pool_ref.region, project=target_pool_ref.project, targetPool=target_pool_ref.Name(), targetPoolsRemoveInstanceRequest=( client.messages.TargetPoolsRemoveInstanceRequest( instances=instances))) return client.MakeRequests([(client.apitools_client.targetPools, 'RemoveInstance', request)])
def GetAttachedDiskByName(self, resources, name, instance_ref, instance): """Gets an attached disk with the specified disk name. First, we attempt to parse the provided disk name to find the possible disks that it may describe. Next, we iterate over the attached disks to find the ones that match the possible disks. If the disk can match multiple disks, we prompt the user to choose one. Args: resources: resources.Registry, The resource registry name: str, name of the attached disk. instance_ref: Reference of the instance instance. instance: Instance object. Returns: An attached disk object. Raises: exceptions.ArgumentError: If a disk with name cannot be found attached to the instance or if the user does not choose a specific disk when prompted. """ possible_disks = self._GetPossibleDisks(resources, name, instance_ref) matched_attached_disks = [] for attached_disk in instance.disks: parsed_disk = instance_utils.ParseDiskResourceFromAttachedDisk( resources, attached_disk) for d in possible_disks: if d and d.RelativeName() == parsed_disk.RelativeName(): matched_attached_disks.append(attached_disk) if not matched_attached_disks: raise compute_exceptions.ArgumentError( 'Disk [{}] is not attached to instance [{}] in zone [{}].'. format(name, instance_ref.instance, instance_ref.zone)) elif len(matched_attached_disks) == 1: return matched_attached_disks[0] choice_names = [] for attached_disk in matched_attached_disks: disk_ref = instance_utils.ParseDiskResourceFromAttachedDisk( resources, attached_disk) choice_names.append(disk_ref.RelativeName()) idx = console_io.PromptChoice( options=choice_names, message='[{}] matched multiple disks. Choose one:'.format(name)) if idx is None: raise compute_exceptions.ArgumentError( 'Found multiple disks matching [{}] attached to instance [{}] ' 'in zone [{}].'.format(name, instance_ref.instance, instance_ref.zone)) return matched_attached_disks[idx]
def ParseTemplate(template_file, params=None, params_from_file=None): """Parse and apply params into a template file. Args: template_file: The path to the file to open and parse. params: a dict of param-name -> param-value params_from_file: a dict of param-name -> param-file Returns: The parsed template dict Raises: yaml.Error: When the template file cannot be read or parsed. ArgumentError: If any params are not provided. ValidationError: if the YAML file is invalid. """ params = params or {} params_from_file = params_from_file or {} joined_params = dict(params) for key, file_path in six.iteritems(params_from_file): if key in joined_params: raise exceptions.DuplicateError('Duplicate param key: ' + key) try: joined_params[key] = files.ReadFileContents(file_path) except files.Error as e: raise exceptions.ArgumentError( 'Could not load param key "{0}" from file "{1}": {2}'.format( key, file_path, e.strerror)) template = yaml.load_path(template_file) if not isinstance(template, dict) or 'template' not in template: raise exceptions.ValidationError( 'Invalid template format. Root must be a mapping with single ' '"template" value') (template, missing_params, used_params) = ReplaceTemplateParams(template, joined_params) if missing_params: raise exceptions.ArgumentError( 'Some parameters were present in the template but not provided on ' 'the command line: ' + ', '.join(sorted(missing_params))) unused_params = set(joined_params.keys()) - used_params if unused_params: raise exceptions.ArgumentError( 'Some parameters were specified on the command line but not referenced ' 'in the template: ' + ', '.join(sorted(unused_params))) return template
def _Modify(self, client, resources, backend_service_ref, args, existing): replacement = encoding.CopyProtoMessage(existing) group_ref = self._GetGroupRef(args, resources, client) group_uri = group_ref.SelfLink() for backend in existing.backends: if group_uri == backend.group: if (group_ref.Collection() == 'compute.instanceGroups' or group_ref.Collection() == 'compute.networkEndpointGroups'): scope = 'zone' elif group_ref.Collection() == 'compute.regionInstanceGroups': scope = 'region' raise exceptions.ArgumentError( 'Backend [{}] in {} [{}] already exists in backend service ' '[{}].'.format(group_ref.Name(), scope, getattr(group_ref, scope), backend_service_ref.Name())) if args.balancing_mode: balancing_mode = client.messages.Backend.BalancingModeValueValuesEnum( args.balancing_mode) else: balancing_mode = None backend = self._CreateBackendMessage(client.messages, group_uri, balancing_mode, args) replacement.backends.append(backend) return replacement
def _Modify(args, existing): """Returns a modified URL map message.""" replacement = encoding.CopyProtoMessage(existing) # Removes the path matcher. new_path_matchers = [] path_matcher_found = False for path_matcher in existing.pathMatchers: if path_matcher.name == args.path_matcher_name: path_matcher_found = True else: new_path_matchers.append(path_matcher) if not path_matcher_found: raise compute_exceptions.ArgumentError( 'No path matcher with the name [{0}] was found.'.format( args.path_matcher_name)) replacement.pathMatchers = new_path_matchers # Removes all host rules that refer to the path matcher. new_host_rules = [] for host_rule in existing.hostRules: if host_rule.pathMatcher != args.path_matcher_name: new_host_rules.append(host_rule) replacement.hostRules = new_host_rules return replacement
def Run(self, args): if not args.all and not args.keys: raise exceptions.ArgumentError( 'One of [--all] or [--keys] must be provided.') holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = holder.client project_ref = self.CreateReference(holder.resources) get_request = self.GetGetRequest(client, project_ref) objects = client.MakeRequests([get_request]) new_object = self.Modify(client, args, objects[0]) # If existing object is equal to the proposed object or if # Modify() returns None, then there is no work to be done, so we # print the resource and return. if not new_object or objects[0] == new_object: log.status.Print( 'No change requested; skipping update for [{0}].'.format( objects[0].name)) return objects return client.MakeRequests( [self.GetSetRequest(client, project_ref, new_object)])
def GetAttachedDiskByDeviceName(self, resources, device_name, instance_ref, instance): """Gets an attached disk with the specified device name. Args: resources: resources.Registry, The resource registry device_name: str, device name of the attached disk. instance_ref: Reference of the instance instance. instance: Instance object. Returns: An attached disk object. Raises: compute_exceptions.ArgumentError: If a disk with device name cannot be found attached to the instance. """ for disk in instance.disks: if disk.deviceName == device_name: return disk raise compute_exceptions.ArgumentError( 'No disk with device name [{}] is attached to instance [{}] ' 'in zone [{}].'.format(device_name, instance_ref.instance, instance_ref.zone))
def Modify(self, client, resources, backend_service_ref, args, existing): replacement = encoding.CopyProtoMessage(existing) group_ref = self._GetGroupRef(args, resources, client) group_uri = group_ref.RelativeName() backend_idx = None for i, backend in enumerate(existing.backends): if group_uri == resources.ParseURL(backend.group).RelativeName(): backend_idx = i if backend_idx is None: scope_value = getattr(group_ref, 'region', None) if scope_value is None: scope_value = getattr(group_ref, 'zone', None) scope = 'zone' else: scope = 'region' raise exceptions.ArgumentError( 'Backend [{0}] in {1} [{2}] is not a backend of backend service ' '[{3}].'.format(group_ref.Name(), scope, scope_value, backend_service_ref.Name())) else: replacement.backends.pop(backend_idx) return replacement
def _GetOriginalIpCidrRange(self, client, subnetwork_ref): subnetwork = self._GetSubnetwork(client, subnetwork_ref) if not subnetwork: raise compute_exceptions.ArgumentError( 'Subnet [{subnet}] was not found in region {region}.'.format( subnet=subnetwork_ref.Name(), region=subnetwork_ref.region)) return subnetwork.ipCidrRange
def BytesToMb(size): """Converts a disk size in bytes to MB.""" if not size: return None if size % constants.BYTES_IN_ONE_MB != 0: raise compute_exceptions.ArgumentError( 'Disk size must be a multiple of 1 MB. Did you mean [{0}MB]?'. format(size // constants.BYTES_IN_ONE_MB + 1)) return size // constants.BYTES_IN_ONE_MB
def Run(self, args): """Issues a request necessary for setting a backup target pool.""" holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = holder.client target_pool_ref = self.TARGET_POOL_ARG.ResolveAsResource( args, holder.resources, scope_lister=compute_flags.GetDefaultScopeLister(client)) if args.backup_pool: args.backup_pool_region = target_pool_ref.region backup_pool_ref = self.BACKUP_POOL_ARG.ResolveAsResource( args, holder.resources) target_reference = client.messages.TargetReference( target=backup_pool_ref.SelfLink()) else: target_reference = client.messages.TargetReference() if args.backup_pool and args.failover_ratio is None: raise compute_exceptions.ArgumentError( '[--failover-ratio] must be provided when setting a backup pool.' ) if args.failover_ratio is not None and (args.failover_ratio < 0 or args.failover_ratio > 1): raise compute_exceptions.ArgumentError( '[--failover-ratio] must be a number between 0 and 1, inclusive.' ) request = client.messages.ComputeTargetPoolsSetBackupRequest( targetPool=target_pool_ref.Name(), targetReference=target_reference, failoverRatio=args.failover_ratio, region=target_pool_ref.region, project=target_pool_ref.project) return client.MakeRequests([(client.apitools_client.targetPools, 'SetBackup', request)])
def _Modify(args, existing): """Returns a modified URL map message.""" replacement = encoding.CopyProtoMessage(existing) path_matcher_to_remove = None new_host_rules = [] for host_rule in existing.hostRules: if args.host in host_rule.hosts: path_matcher_to_remove = host_rule.pathMatcher else: new_host_rules.append(host_rule) if not path_matcher_to_remove: raise compute_exceptions.ArgumentError( 'No host rule contains the host [{0}].'.format(args.host)) replacement.hostRules = new_host_rules path_matcher_is_used_by_other_rules = False for host_rule in replacement.hostRules: if host_rule.pathMatcher == path_matcher_to_remove: path_matcher_is_used_by_other_rules = True break if not path_matcher_is_used_by_other_rules: if args.delete_orphaned_path_matcher: replacement.pathMatchers = [ path_matcher for path_matcher in existing.pathMatchers if path_matcher.name != path_matcher_to_remove ] else: raise compute_exceptions.ArgumentError( 'This operation will orphan the path matcher [{0}]. To ' 'delete the orphan path matcher, rerun this command with ' '[--delete-orphaned-path-matcher] or use [gcloud compute ' 'url-maps edit] to modify the URL map by hand.'.format( host_rule.pathMatcher)) return replacement
def ParseDestPorts(dest_ports, message_classes): """Parses protocol:port mappings for --dest-ports command line.""" dest_port_list = [] for spec in dest_ports or []: match = LEGAL_SPECS.match(spec) if not match: raise exceptions.ArgumentError( 'Organization security policy rules must be of the form {0}; ' 'received [{1}].'.format(ALLOWED_METAVAR, spec)) if match.group('ports'): ports = [match.group('ports')] else: ports = [] dest_port = message_classes.SecurityPolicyRuleMatcherConfigDestinationPort( ipProtocol=match.group('protocol'), ports=ports) dest_port_list.append(dest_port) return dest_port_list
def _Run(args, holder, ssl_certificate_ref): """Make a SslCertificates.Insert request.""" client = holder.client if args.domains: if ssl_certificates_utils.IsRegionalSslCertificatesRef( ssl_certificate_ref): raise compute_exceptions.ArgumentError( '--domains flag is not supported for regional certificates') request = client.messages.ComputeSslCertificatesInsertRequest( sslCertificate=client.messages.SslCertificate( type=client.messages.SslCertificate.TypeValueValuesEnum. MANAGED, name=ssl_certificate_ref.Name(), managed=client.messages.SslCertificateManagedSslCertificate( domains=args.domains), description=args.description), project=ssl_certificate_ref.project) collection = client.apitools_client.sslCertificates else: certificate = files.ReadFileContents(args.certificate) private_key = files.ReadFileContents(args.private_key) if ssl_certificates_utils.IsRegionalSslCertificatesRef( ssl_certificate_ref): request = client.messages.ComputeRegionSslCertificatesInsertRequest( sslCertificate=client.messages.SslCertificate( name=ssl_certificate_ref.Name(), certificate=certificate, privateKey=private_key, description=args.description), region=ssl_certificate_ref.region, project=ssl_certificate_ref.project) collection = client.apitools_client.regionSslCertificates else: request = client.messages.ComputeSslCertificatesInsertRequest( sslCertificate=client.messages.SslCertificate( name=ssl_certificate_ref.Name(), certificate=certificate, privateKey=private_key, description=args.description), project=ssl_certificate_ref.project) collection = client.apitools_client.sslCertificates return client.MakeRequests([(collection, 'Insert', request)])
def ParseLayer4Configs(layer4_conifigs, message_classes): """Parses protocol:port mappings for --layer4-configs command line.""" layer4_config_list = [] for spec in layer4_conifigs or []: match = LEGAL_SPECS.match(spec) if not match: raise exceptions.ArgumentError( 'Organization firewall policy rules must be of the form {0}; ' 'received [{1}].'.format(ALLOWED_METAVAR, spec)) if match.group('ports'): ports = [match.group('ports')] else: ports = [] layer4_conifig = ( message_classes.FirewallPolicyRuleMatcherLayer4Config( ipProtocol=match.group('protocol'), ports=ports)) layer4_config_list.append(layer4_conifig) return layer4_config_list
def _CheckMissingArgument(args, certificate_map): """Checks for missing argument.""" all_args = [ 'ssl_certificates', 'url_map', 'quic_override', 'ssl_policy', 'clear_ssl_policy' ] err_msg_args = [ '[--ssl-certificates]', '[--url-map]', '[--quic-override]', '[--ssl-policy]', '[--clear-ssl-policy]' ] if certificate_map: all_args.append('certificate_map') err_msg_args.append('[--certificate-map]') all_args.append('clear_certificate_map') err_msg_args.append('[--clear-certificate-map]') if not sum(args.IsSpecified(arg) for arg in all_args): raise compute_exceptions.ArgumentError( 'You must specify at least one of %s or %s.' % (', '.join(err_msg_args[:-1]), err_msg_args[-1]))
def _Modify(self, client, resources, backend_service_ref, args, existing): replacement = encoding.CopyProtoMessage(existing) group_ref = self._GetGroupRef(args, resources, client) backend_to_update = None for backend in replacement.backends: # At most one backend will match if group_ref.RelativeName() == resources.ParseURL( backend.group).RelativeName(): backend_to_update = backend break if not backend_to_update: scope_type = None scope_name = None if hasattr(group_ref, 'zone'): scope_type = 'zone' scope_name = group_ref.zone if hasattr(group_ref, 'region'): scope_type = 'region' scope_name = group_ref.region raise exceptions.ArgumentError( 'No backend with name [{0}] in {1} [{2}] is part of the backend ' 'service [{3}].'.format(group_ref.Name(), scope_type, scope_name, backend_service_ref.Name())) if args.description: backend_to_update.description = args.description elif args.description is not None: backend_to_update.description = None self._ModifyBalancingModeArgs(client, args, backend_to_update) if backend_to_update is not None and args.failover is not None: backend_to_update.failover = args.failover return replacement
def Run(self, args): holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = holder.client if not args.bucket and args.prefix: raise compute_exceptions.ArgumentError( '[--prefix] cannot be specified when unsetting the usage bucket.' ) bucket_uri = None if args.bucket: bucket_uri = six.text_type(resources.REGISTRY.Parse(args.bucket)) request = client.messages.ComputeProjectsSetUsageExportBucketRequest( project=properties.VALUES.core.project.GetOrFail(), usageExportLocation=client.messages.UsageExportLocation( bucketName=bucket_uri, reportNamePrefix=args.prefix, )) return client.MakeRequests([(client.apitools_client.projects, 'SetUsageExportBucket', request)])
def ParseRules(rules, message_classes, action=ActionType.ALLOW): """Parses protocol:port mappings from --allow or --rules command line.""" rule_value_list = [] for spec in rules or []: match = LEGAL_SPECS.match(spec) if not match: raise compute_exceptions.ArgumentError( 'Firewall rules must be of the form {0}; received [{1}].'.format( ALLOWED_METAVAR, spec)) if match.group('ports'): ports = [match.group('ports')] else: ports = [] if action == ActionType.ALLOW: rule = message_classes.Firewall.AllowedValueListEntry( IPProtocol=match.group('protocol'), ports=ports) else: rule = message_classes.Firewall.DeniedValueListEntry( IPProtocol=match.group('protocol'), ports=ports) rule_value_list.append(rule) return rule_value_list
def Run(self, args, holder): """Issues request necessary to create a target instance.""" client = holder.client target_instance_ref = self.TARGET_INSTANCE_ARG.ResolveAsResource( args, holder.resources, scope_lister=compute_flags.GetDefaultScopeLister(client)) if target_instance_ref.zone and not args.instance_zone: args.instance_zone = target_instance_ref.zone instance_ref = self.INSTANCE_ARG.ResolveAsResource( args, holder.resources) if target_instance_ref.zone != instance_ref.zone: raise compute_exceptions.ArgumentError( 'Target instance zone must match the virtual machine instance zone.' ) target_instance = client.messages.TargetInstance( description=args.description, name=target_instance_ref.Name(), instance=instance_ref.SelfLink()) if args.IsSpecified('network'): target_instance.network = flags.NETWORK_ARG.ResolveAsResource( args, holder.resources).SelfLink() request = client.messages.ComputeTargetInstancesInsertRequest( targetInstance=target_instance, project=target_instance_ref.project, zone=target_instance_ref.zone) return client.MakeRequests([(client.apitools_client.targetInstances, 'Insert', request)])
def _CreateRegionalRequests(self, holder, args, backend_services_ref): """Returns a regional backend service create request.""" if (not args.cache_key_include_host or not args.cache_key_include_protocol or not args.cache_key_include_query_string or args.cache_key_query_string_blacklist is not None or args.cache_key_query_string_whitelist is not None): raise compute_exceptions.ArgumentError( 'Custom cache key flags cannot be used for regional requests.') if (self._support_multinic and args.IsSpecified('network') and args.load_balancing_scheme != 'INTERNAL'): raise exceptions.InvalidArgumentException( '--network', 'can only specify network for INTERNAL backend service.') backend_service = self._CreateRegionBackendService(holder, args, backend_services_ref) client = holder.client if args.connection_draining_timeout is not None: backend_service.connectionDraining = client.messages.ConnectionDraining( drainingTimeoutSec=args.connection_draining_timeout) if args.custom_request_header is not None: backend_service.customRequestHeaders = args.custom_request_header if args.custom_response_header is not None: backend_service.customResponseHeaders = args.custom_response_header backend_services_utils.ApplyFailoverPolicyArgs(client.messages, args, backend_service, self._support_failover) if (self._support_advanced_load_balancing and args.service_lb_policy is not None): backend_service.serviceLbPolicy = reference_utils.BuildServiceLbPolicyUrl( project_name=backend_services_ref.project, location=backend_services_ref.region, policy_name=args.service_lb_policy) if args.service_bindings is not None: raise exceptions.InvalidArgumentException( '--service-bindings', 'Service bindings are allowed only for global backend services.') if self._support_subsetting: backend_services_utils.ApplySubsettingArgs( client, args, backend_service, self._support_subsetting_subset_size) backend_services_utils.ApplyConnectionTrackingPolicyArgs( client, args, backend_service, support_strong_session_affinity=self._support_strong_session_affinity) self._ApplyIapArgs(client.messages, args.iap, backend_service) if args.session_affinity is not None: backend_service.sessionAffinity = ( client.messages.BackendService.SessionAffinityValueValuesEnum( args.session_affinity)) if args.port_name is not None: backend_service.portName = args.port_name if self._support_multinic and args.IsSpecified('network'): backend_service.network = flags.NETWORK_ARG.ResolveAsResource( args, holder.resources).SelfLink() if self._support_weighted_lb and args.locality_lb_policy is not None: backend_service.localityLbPolicy = ( client.messages.BackendService.LocalityLbPolicyValueValuesEnum( args.locality_lb_policy)) request = client.messages.ComputeRegionBackendServicesInsertRequest( backendService=backend_service, region=backend_services_ref.region, project=backend_services_ref.project) return [(client.apitools_client.regionBackendServices, 'Insert', request)]
def _ModifyBase(client, args, existing): """Modifications to the URL map that are shared between release tracks. Args: client: The compute client. args: the argparse arguments that this command was invoked with. existing: the existing URL map message. Returns: A modified URL map message. """ replacement = encoding.CopyProtoMessage(existing) if not args.new_hosts and not args.existing_host: new_hosts = ['*'] else: new_hosts = args.new_hosts # If --new-hosts is given, we check to make sure none of those # hosts already exist and once the check succeeds, we create the # new host rule. if new_hosts: new_hosts = set(new_hosts) for host_rule in existing.hostRules: for host in host_rule.hosts: if host in new_hosts: raise compute_exceptions.ArgumentError( 'Cannot create a new host rule with host [{0}] because the ' 'host is already part of a host rule that references the path ' 'matcher [{1}].'.format(host, host_rule.pathMatcher)) replacement.hostRules.append( client.messages.HostRule(hosts=sorted(new_hosts), pathMatcher=args.path_matcher_name)) # If --existing-host is given, we check to make sure that the # corresponding host rule will not render a patch matcher # orphan. If the check succeeds, we change the path matcher of the # host rule. If the check fails, we remove the path matcher if # --delete-orphaned-path-matcher is given otherwise we fail. else: target_host_rule = None for host_rule in existing.hostRules: for host in host_rule.hosts: if host == args.existing_host: target_host_rule = host_rule break if target_host_rule: break if not target_host_rule: raise compute_exceptions.ArgumentError( 'No host rule with host [{0}] exists. Check your spelling or ' 'use [--new-hosts] to create a new host rule.'.format( args.existing_host)) path_matcher_orphaned = True for host_rule in replacement.hostRules: if host_rule == target_host_rule: host_rule.pathMatcher = args.path_matcher_name continue if host_rule.pathMatcher == target_host_rule.pathMatcher: path_matcher_orphaned = False break if path_matcher_orphaned: # A path matcher will be orphaned, so now we determine whether # we should delete the path matcher or report an error. if args.delete_orphaned_path_matcher: replacement.pathMatchers = [ path_matcher for path_matcher in existing.pathMatchers if path_matcher.name != target_host_rule.pathMatcher ] else: raise compute_exceptions.ArgumentError( 'This operation will orphan the path matcher [{0}]. To ' 'delete the orphan path matcher, rerun this command with ' '[--delete-orphaned-path-matcher] or use [gcloud compute ' 'url-maps edit] to modify the URL map by hand.'.format( host_rule.pathMatcher)) return replacement
def Run(self, args): instances_flags.ValidateDiskFlags( args, enable_kms=self._support_kms, enable_snapshots=True, enable_source_snapshot_csek=self._support_source_snapshot_csek, enable_image_csek=self._support_image_csek) instances_flags.ValidateImageFlags(args) instances_flags.ValidateLocalSsdFlags(args) instances_flags.ValidateNicFlags(args) instances_flags.ValidateServiceAccountAndScopeArgs(args) instances_flags.ValidateAcceleratorArgs(args) instances_flags.ValidateNetworkTierArgs(args) instances_flags.ValidateReservationAffinityGroup(args) instances_flags.ValidateNetworkPerformanceConfigsArgs(args) instances_flags.ValidateInstanceScheduling( args, support_max_run_duration=self._support_max_run_duration) holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) compute_client = holder.client resource_parser = holder.resources instance_refs = instance_utils.GetInstanceRefs(args, compute_client, holder) if len(instance_refs) > 1 and args.IsSpecified('address'): raise exceptions.BadArgumentException( '--address', 'Multiple instances were specified for creation. --address flag can ' 'be used when creating a single instance.') requests = self._CreateRequests(args, instance_refs, instance_refs[0].project, instance_refs[0].zone, compute_client, resource_parser, holder) if not args.async_: # TODO(b/63664449): Replace this with poller + progress tracker. try: # Using legacy MakeRequests (which also does polling) here until # replaced by api_lib.utils.waiter. return compute_client.MakeRequests(requests) except exceptions.ToolException as e: invalid_machine_type_message_regex = ( r'Invalid value for field \'resource.machineType\': .+. ' r'Machine type with name \'.+\' does not exist in zone \'.+\'\.' ) if re.search(invalid_machine_type_message_regex, six.text_type(e)): raise compute_exceptions.ArgumentError( six.text_type(e) + '\nUse `gcloud compute machine-types list --zones` to see the ' 'available machine types.') raise errors_to_collect = [] responses = compute_client.BatchRequests(requests, errors_to_collect) for r in responses: err = getattr(r, 'error', None) if err: errors_to_collect.append(poller.OperationErrors(err.errors)) if errors_to_collect: raise core_exceptions.MultiError(errors_to_collect) operation_refs = [ holder.resources.Parse(r.selfLink) for r in responses ] log.status.Print( 'NOTE: The users will be charged for public IPs when VMs ' 'are created.') for instance_ref, operation_ref in zip(instance_refs, operation_refs): log.status.Print( 'Instance creation in progress for [{}]: {}'.format( instance_ref.instance, operation_ref.SelfLink())) log.status.Print( 'Use [gcloud compute operations describe URI] command ' 'to check the status of the operation(s).') if not args.IsSpecified('format'): # For async output we need a separate format. Since we already printed in # the status messages information about operations there is nothing else # needs to be printed. args.format = 'disable' return responses
def Run(self, args): """Issue API requests for route creation, callable from multiple tracks.""" holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) client = holder.client network_uri = self.NETWORK_ARG.ResolveAsResource( args, holder.resources).SelfLink() route_ref = self.ROUTE_ARG.ResolveAsResource(args, holder.resources) if args.next_hop_instance: next_hop_instance_uri = self.INSTANCE_ARG.ResolveAsResource( args, holder.resources, scope_lister=instance_flags.GetInstanceZoneScopeLister( client)).SelfLink() else: if args.next_hop_instance_zone: raise compute_exceptions.ArgumentError( '[--next-hop-instance-zone] can only be specified in conjunction ' 'with [--next-hop-instance].') next_hop_instance_uri = None if args.next_hop_gateway: next_hop_gateway_ref = flags.NEXT_HOP_GATEWAY_ARG.ResolveAsResource( args, holder.resources) next_hop_gateway_uri = next_hop_gateway_ref.SelfLink() else: next_hop_gateway_uri = None next_hop_vpn_tunnel_uri = None if args.next_hop_vpn_tunnel: next_hop_vpn_tunnel_uri = self.VPN_TUNNEL_ARG.ResolveAsResource( args, holder.resources, scope_lister=compute_flags.GetDefaultScopeLister( client)).SelfLink() elif args.next_hop_vpn_tunnel_region: raise compute_exceptions.ArgumentError( '[--next-hop-vpn-tunnel-region] can only be specified in ' 'conjunction with [--next-hop-vpn-tunnel].') next_hop_ilb_uri = None if args.next_hop_ilb: try: ipaddress.ip_address(args.next_hop_ilb) if args.next_hop_ilb_region: raise exceptions.InvalidArgumentException( '--next-hop-ilb-region', 'This should not be specified if ' 'an IP address is used for [--next-hop-ilb].') next_hop_ilb_uri = args.next_hop_ilb except ValueError: next_hop_ilb_uri = self.ILB_ARG.ResolveAsResource( args, holder.resources, scope_lister=compute_flags.GetDefaultScopeLister( client)).SelfLink() elif args.next_hop_ilb_region: raise exceptions.InvalidArgumentException( '--next-hop-ilb-region', 'This can only be specified in ' 'conjunction with [--next-hop-ilb].') request = client.messages.ComputeRoutesInsertRequest( project=route_ref.project, route=client.messages.Route( description=args.description, destRange=args.destination_range, name=route_ref.Name(), network=network_uri, nextHopInstance=next_hop_instance_uri, nextHopIp=args.next_hop_address, nextHopGateway=next_hop_gateway_uri, nextHopVpnTunnel=next_hop_vpn_tunnel_uri, priority=args.priority, tags=args.tags, )) request.route.nextHopIlb = next_hop_ilb_uri return client.MakeRequests([(client.apitools_client.routes, 'Insert', request)])