Example #1
0
    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
Example #2
0
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]
Example #3
0
    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]
Example #5
0
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
Example #6
0
    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))
Example #10
0
    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
Example #11
0
    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
Example #13
0
    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
Example #15
0
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
Example #18
0
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
Example #20
0
    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
Example #22
0
    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
Example #25
0
    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
Example #26
0
    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)])