Пример #1
0
  def Run(self, args):
    self.ref = self.CreateReference(args)
    get_request = self.GetGetRequest(args)

    errors = []
    objects = list(request_helper.MakeRequests(
        requests=[get_request],
        http=self.http,
        batch_url=self.batch_url,
        errors=errors,
        custom_get_requests=None))
    if errors:
      utils.RaiseToolException(
          errors,
          error_message='Could not fetch resource:')

    self.original_object = objects[0]
    self.original_record = encoding.MessageToDict(self.original_object)

    # Selects only the fields that can be modified.
    field_selector = property_selector.PropertySelector(
        properties=self._resource_spec.editables)
    self.modifiable_record = field_selector.Apply(self.original_record)

    buf = cStringIO.StringIO()
    for line in _HELP.splitlines():
      buf.write('#')
      if line:
        buf.write(' ')
      buf.write(line)
      buf.write('\n')

    buf.write('\n')
    buf.write(_SerializeDict(self.modifiable_record,
                             args.format or BaseEdit.DEFAULT_FORMAT))
    buf.write('\n')

    example = _SerializeDict(
        encoding.MessageToDict(self.example_resource),
        args.format or BaseEdit.DEFAULT_FORMAT)
    _WriteResourceInCommentBlock(example, 'Example resource:', buf)

    buf.write('#\n')

    original = _SerializeDict(self.original_record,
                              args.format or BaseEdit.DEFAULT_FORMAT)
    _WriteResourceInCommentBlock(original, 'Original resource:', buf)

    file_contents = buf.getvalue()
    while True:
      file_contents = edit.OnlineEdit(file_contents)
      try:
        resources = self.ProcessEditedResource(file_contents, args)
        break
      except (ValueError, yaml.error.YAMLError,
              protorpc.messages.ValidationError,
              calliope_exceptions.ToolException) as e:
        if isinstance(e, ValueError):
          message = e.message
        else:
          message = str(e)

        if isinstance(e, calliope_exceptions.ToolException):
          problem_type = 'applying'
        else:
          problem_type = 'parsing'

        message = ('There was a problem {0} your changes: {1}'
                   .format(problem_type, message))
        if not console_io.PromptContinue(
            message=message,
            prompt_string='Would you like to edit the resource again?'):
          raise calliope_exceptions.ToolException('Edit aborted by user.')

    resources = lister.ProcessResults(
        resources=resources,
        field_selector=property_selector.PropertySelector(
            properties=None,
            transformations=self.transformations))
    for resource in resources:
      yield resource
Пример #2
0
    def ConstructInstanceFromArgs(cls,
                                  sql_messages,
                                  args,
                                  original=None,
                                  instance_ref=None):
        """Construct a Cloud SQL instance from command line args.

    Args:
      sql_messages: module, The messages module that should be used.
      args: argparse.Namespace, The CLI arg namespace.
      original: sql_messages.DatabaseInstance, The original instance, if some of
          it might be used to fill fields in the new one.
      instance_ref: reference to DatabaseInstance object, used to fill project
          and instance information.

    Returns:
      sql_messages.DatabaseInstance, The constructed (and possibly partial)
      database instance.

    Raises:
      ToolException: An error other than http error occured while executing the
          command.
    """
        settings = cls._ConstructSettingsFromArgs(sql_messages, args, original)
        cls._SetBackupConfiguration(sql_messages, settings, args, original)
        cls._SetDatabaseFlags(sql_messages, settings, args)
        cls._SetMaintenanceWindow(sql_messages, settings, args, original)

        on_premises_host_port = getattr(args, 'on_premises_host_port', None)
        if on_premises_host_port:
            if args.require_ssl:
                raise exceptions.ToolException(
                    'Argument --on-premises-host-port not '
                    'allowed with --require_ssl')
            settings.onPremisesConfiguration = sql_messages.OnPremisesConfiguration(
                hostPort=on_premises_host_port)

        storage_size = getattr(args, 'storage_size', None)
        if storage_size:
            settings.dataDiskSizeGb = int(storage_size / (1 << 30))

        # these flags are only present for the create command
        region = getattr(args, 'region', None)
        database_version = getattr(args, 'database_version', None)

        instance_resource = sql_messages.DatabaseInstance(
            region=region,
            databaseVersion=database_version,
            masterInstanceName=getattr(args, 'master_instance_name', None),
            settings=settings)

        if hasattr(args, 'master_instance_name'):
            if args.master_instance_name:
                replication = 'ASYNCHRONOUS'
                if hasattr(args,
                           'replica_type') and args.replica_type == 'FAILOVER':
                    instance_resource.replicaConfiguration = (
                        sql_messages.ReplicaConfiguration(failoverTarget=True))
            else:
                replication = 'SYNCHRONOUS'
            if not args.replication:
                instance_resource.settings.replicationType = replication

        if instance_ref:
            cls.SetProjectAndInstanceFromRef(instance_resource, instance_ref)

        if hasattr(args, 'storage_type') and args.storage_type:
            instance_resource.settings.dataDiskType = 'PD_' + args.storage_type

        if hasattr(args,
                   'failover_replica_name') and args.failover_replica_name:
            instance_resource.failoverReplica = (
                sql_messages.DatabaseInstance.FailoverReplicaValue(
                    name=args.failover_replica_name))

        if (hasattr(args, 'storage_auto_increase')
                and args.storage_auto_increase is not None):
            instance_resource.settings.storageAutoResize = args.storage_auto_increase

        if (hasattr(args, 'storage_auto_increase_limit')
                and args.IsSpecified('storage_auto_increase_limit')):
            # Resize limit should be settable if the original instance has resize
            # turned on, or if the instance to be created has resize flag.
            if (original and original.settings.storageAutoResize) or (
                    args.storage_auto_increase):
                # If the limit is set to None, we want it to be set to 0. This is a
                # backend requirement.
                instance_resource.settings.storageAutoResizeLimit = (
                    args.storage_auto_increase_limit) or 0
            else:
                raise exceptions.RequiredArgumentException(
                    '--storage-auto-increase',
                    'To set the storage capacity limit '
                    'using [--storage-auto-increase-limit], [--storage-auto-increase] '
                    'must be enabled.')

        return instance_resource
Пример #3
0
def PromptForDeletionHelper(resource_name, prompt_list, prompt_title=None):
    prompt_title = (prompt_title or
                    'The following {0} will be deleted:'.format(resource_name))
    prompt_message = ConstructList(prompt_title, prompt_list)
    if not console_io.PromptContinue(message=prompt_message):
        raise calliope_exceptions.ToolException('Deletion aborted by user.')
Пример #4
0
    def Run(self, args):
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        client = holder.client

        if (args.check_interval is not None
                and (args.check_interval < CHECK_INTERVAL_LOWER_BOUND_SEC
                     or args.check_interval > CHECK_INTERVAL_UPPER_BOUND_SEC)):
            raise exceptions.ToolException(
                '[--check-interval] must not be less than {0} second or greater '
                'than {1} seconds; received [{2}] seconds.'.format(
                    CHECK_INTERVAL_LOWER_BOUND_SEC,
                    CHECK_INTERVAL_UPPER_BOUND_SEC, args.check_interval))

        if (args.timeout is not None
                and (args.timeout < TIMEOUT_LOWER_BOUND_SEC
                     or args.timeout > TIMEOUT_UPPER_BOUND_SEC)):
            raise exceptions.ToolException(
                '[--timeout] must not be less than {0} second or greater than {1} '
                'seconds; received: [{2}] seconds.'.format(
                    TIMEOUT_LOWER_BOUND_SEC, TIMEOUT_UPPER_BOUND_SEC,
                    args.timeout))

        if (args.healthy_threshold is not None
                and (args.healthy_threshold < THRESHOLD_LOWER_BOUND
                     or args.healthy_threshold > THRESHOLD_UPPER_BOUND)):
            raise exceptions.ToolException(
                '[--healthy-threshold] must be an integer between {0} and {1}, '
                'inclusive; received: [{2}].'.format(THRESHOLD_LOWER_BOUND,
                                                     THRESHOLD_UPPER_BOUND,
                                                     args.healthy_threshold))

        if (args.unhealthy_threshold is not None
                and (args.unhealthy_threshold < THRESHOLD_LOWER_BOUND
                     or args.unhealthy_threshold > THRESHOLD_UPPER_BOUND)):
            raise exceptions.ToolException(
                '[--unhealthy-threshold] must be an integer between {0} and {1}, '
                'inclusive; received [{2}].'.format(THRESHOLD_LOWER_BOUND,
                                                    THRESHOLD_UPPER_BOUND,
                                                    args.unhealthy_threshold))

        args_unset = not (args.port or args.request_path or args.check_interval
                          or args.timeout or args.healthy_threshold
                          or args.unhealthy_threshold)
        if args.description is None and args.host is None and args_unset:
            raise exceptions.ToolException(
                'At least one property must be modified.')

        http_health_check_ref = self.CreateReference(holder.resources, args)
        get_request = self.GetGetRequest(client, http_health_check_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 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, http_health_check_ref, new_object)])
Пример #5
0
 def Run(self, args):
     if six.PY3:
         raise exceptions.ToolException(
             'This command does not support python3.')
     _Run(args)
Пример #6
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.
    """
        adapter = self.context['api_adapter']

        cluster_refs = []
        for name in args.names:
            cluster_refs.append(adapter.ParseCluster(name))

        if not console_io.PromptContinue(message=util.ConstructList(
                'The following clusters will be deleted.', [
                    '[{name}] in [{zone}]'.format(name=ref.clusterId,
                                                  zone=adapter.Zone(ref))
                    for ref in cluster_refs
                ]),
                                         throw_if_unattended=True):
            raise exceptions.ToolException('Deletion aborted by user.')

        operations = []
        errors = []
        # Issue all deletes first
        for cluster_ref in cluster_refs:
            try:
                # Make sure it exists (will raise appropriate error if not)
                adapter.GetCluster(cluster_ref)

                op_ref = adapter.DeleteCluster(cluster_ref)
                operations.append((op_ref, cluster_ref))
            except apitools_base.HttpError as error:
                errors.append(util.GetError(error))
            except util.Error as error:
                errors.append(error)
        if args.wait:
            # Poll each operation for completion
            for operation_ref, cluster_ref in operations:
                try:
                    adapter.WaitForOperation(operation_ref,
                                             'Deleting cluster {0}'.format(
                                                 cluster_ref.clusterId),
                                             timeout_s=args.timeout)
                    # Purge cached config files
                    util.ClusterConfig.Purge(cluster_ref.clusterId,
                                             adapter.Zone(cluster_ref),
                                             cluster_ref.projectId)
                    if properties.VALUES.container.cluster.Get(
                    ) == cluster_ref.clusterId:
                        properties.PersistProperty(
                            properties.VALUES.container.cluster, None)
                    log.DeletedResource(cluster_ref)
                except apitools_base.HttpError as error:
                    errors.append(util.GetError(error))
                except util.Error as error:
                    errors.append(error)

        if errors:
            raise exceptions.ToolException(
                util.ConstructList('Some requests did not succeed:', errors))
Пример #7
0
    def GetAddress(self, messages, args, address, address_ref,
                   resource_parser):
        network_tier = self.ConstructNetworkTier(messages, args)

        if args.ip_version or (address is None and address_ref.Collection()
                               == 'compute.globalAddresses'):
            ip_version = messages.Address.IpVersionValueValuesEnum(
                args.ip_version or 'IPV4')
        else:
            # IP version is only specified in global requests if an address is not
            # specified to determine whether an ipv4 or ipv6 address should be
            # allocated.
            ip_version = None

        if args.subnet and args.network:
            raise exceptions.ConflictingArgumentsException(
                '--network', '--subnet')

        purpose = None
        if args.purpose and not args.network and not args.subnet:
            raise exceptions.MinimumArgumentException(
                ['--network', '--subnet'], ' if --purpose is specified')

        # TODO(b/36862747): get rid of args.subnet check
        if args.subnet:
            if address_ref.Collection() == 'compute.globalAddresses':
                raise exceptions.ToolException(
                    '[--subnet] may not be specified for global addresses.')
            if not args.subnet_region:
                args.subnet_region = address_ref.region
            subnetwork_url = flags.SubnetworkArgument().ResolveAsResource(
                args, resource_parser).SelfLink()
            purpose = messages.Address.PurposeValueValuesEnum(
                args.purpose or 'GCE_ENDPOINT')
            if purpose != messages.Address.PurposeValueValuesEnum.GCE_ENDPOINT:
                raise exceptions.InvalidArgumentException(
                    '--purpose',
                    'must be GCE_ENDPOINT for regional internal addresses.')
        else:
            subnetwork_url = None

        network_url = None
        if args.network:
            if address_ref.Collection() == 'compute.addresses':
                raise exceptions.InvalidArgumentException(
                    '--network',
                    'network may not be specified for regional addresses.')
            network_url = flags.NetworkArgument().ResolveAsResource(
                args, resource_parser).SelfLink()
            purpose = messages.Address.PurposeValueValuesEnum(args.purpose
                                                              or 'VPC_PEERING')
            if purpose != messages.Address.PurposeValueValuesEnum.VPC_PEERING:
                raise exceptions.InvalidArgumentException(
                    '--purpose',
                    'must be VPC_PEERING for global internal addresses.')
            if not args.prefix_length:
                raise exceptions.RequiredArgumentException(
                    '--prefix-length',
                    'prefix length is needed for reserving IP ranges.')

        if args.prefix_length:
            if purpose != messages.Address.PurposeValueValuesEnum.VPC_PEERING:
                raise exceptions.InvalidArgumentException(
                    '--prefix-length',
                    'can only be used with [--purpose VPC_PEERING].')

        return messages.Address(
            address=address,
            prefixLength=args.prefix_length,
            description=args.description,
            networkTier=network_tier,
            ipVersion=ip_version,
            name=address_ref.Name(),
            addressType=(messages.Address.AddressTypeValueValuesEnum.INTERNAL
                         if subnetwork_url or network_url else None),
            purpose=purpose,
            subnetwork=subnetwork_url,
            network=network_url)
 def Filter(self, tool_context, args):
   if not args.instance:
     raise exceptions.ToolException('argument --instance/-i is required')
Пример #9
0
    def Run(self, args):
        super(ConfigSSH, self).Run(args)

        ssh_config_file = os.path.expanduser(
            args.ssh_config_file or constants.PER_USER_SSH_CONFIG_FILE)

        instances = None
        if args.remove:
            compute_section = ''
        else:
            self.EnsureSSHKeyIsInProject(getpass.getuser())
            instances = list(self.GetInstances())
            if instances:
                compute_section = _BuildComputeSection(instances,
                                                       self.ssh_key_file)
            else:
                compute_section = ''

        existing_content = _ReadFile(ssh_config_file)
        if existing_content:
            section_re = re.compile(_COMPUTE_SECTION_RE,
                                    flags=re.MULTILINE | re.DOTALL)
            matches = len(section_re.findall(existing_content))
            if matches == 0:
                # There are no existing Compute Engine sections. If there is
                # at least one instance in the project (signified by
                # compute_section not being None), we append it to the end of
                # the configs. Otherwise, we set content to None which will
                # cause nothing to be written to the SSH config file.
                if compute_section:
                    # Ensures that there is a blank line between the existing
                    # configs and the Compute section.
                    if existing_content[-1] != '\n':
                        existing_content += '\n'
                    if existing_content[-2:] != '\n\n':
                        existing_content += '\n'
                    new_content = existing_content + compute_section

                else:
                    new_content = existing_content

            elif matches == 1:
                new_content = re.sub(section_re, compute_section,
                                     existing_content)

            else:
                raise exceptions.ToolException(
                    'Found more than one Google Compute Engine section in [{0}]. '
                    'You can either delete [{0}] and let this command recreate it for '
                    'you or you can manually delete all sections marked with '
                    '[{1}] and [{2}].'.format(ssh_config_file, _BEGIN_MARKER,
                                              _END_MARKER))

        else:
            new_content = compute_section

        if args.dry_run:
            log.out.write(new_content or '')
            return

        if new_content != existing_content:
            with open(ssh_config_file, 'w') as f:
                f.write(new_content)

        if compute_section:
            log.out.write(
                textwrap.dedent("""\
          You should now be able to use ssh/scp with your instances.
          For example, try running:

            ssh {alias}

          """.format(alias=_CreateAlias(instances[0]))))

        elif not instances and not args.remove:
            log.warn(
                'No host aliases were added to your SSH configs because you do not '
                'have any instances. Try running this command again after creating '
                'some instances.')
Пример #10
0
    def Run(self, args):
        if not os.path.exists(args.records_file):
            raise exceptions.ToolException('no such file [{0}]'.format(
                args.records_file))
        if os.path.isdir(args.records_file):
            raise exceptions.ToolException('[{0}] is a directory'.format(
                args.records_file))

        dns = self.context['dns_client']
        messages = self.context['dns_messages']
        resources = self.context['dns_resources']
        project_id = properties.VALUES.core.project.Get(required=True)

        # Get the managed-zone.
        zone_ref = resources.Parse(args.zone, collection='dns.managedZones')
        try:
            zone = dns.managedZones.Get(zone_ref.Request())
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(util.GetErrorMessage(error))

        # Get the current record-sets.
        current = {}
        for record in list_pager.YieldFromList(
                dns.resourceRecordSets,
                messages.DnsResourceRecordSetsListRequest(
                    project=project_id, managedZone=zone_ref.Name()),
                field='rrsets'):
            current[(record.name, record.type)] = record

        # Get the imported record-sets.
        try:
            with files.Context(open(args.records_file)) as import_file:
                if args.zone_file_format:
                    imported = import_util.RecordSetsFromZoneFile(
                        import_file, zone.dnsName)
                else:
                    imported = import_util.RecordSetsFromYamlFile(import_file)
        except Exception as exp:
            msg = (
                u'unable to read record-sets from specified records-file [{0}] '
                u'because [{1}]')
            msg = msg.format(args.records_file, exp.message)
            raise exceptions.ToolException(msg)

        # Get the change resulting from the imported record-sets.
        change = import_util.ComputeChange(current, imported,
                                           args.delete_all_existing,
                                           zone.dnsName,
                                           args.replace_origin_ns)
        if not change:
            msg = u'Nothing to do, all the records in [{0}] already exist.'.format(
                args.records_file)
            log.status.Print(msg)
            return None

        # Send the change to the service.
        result = dns.changes.Create(
            messages.DnsChangesCreateRequest(change=change,
                                             managedZone=zone.name,
                                             project=project_id))
        change_ref = resources.Create(collection='dns.changes',
                                      project=project_id,
                                      managedZone=zone.name,
                                      changeId=result.id)
        msg = u'Imported record-sets from [{0}] into managed-zone [{1}].'.format(
            args.records_file, zone_ref.Name())
        log.status.Print(msg)
        log.CreatedResource(change_ref)
        return result
Пример #11
0
    def Filter(self, context, args):
        """Modify the context that will be given to this group's commands when run.

    Args:
      context: {str:object}, The current context, which is a set of key-value
          pairs that can be used for common initialization among commands.
      args: argparse.Namespace: The same Namespace given to the corresponding
          .Run() invocation.

    Returns:
      The refined command context.
    """
        # Get service endpoints and ensure they are compatible with each other
        testing_url = properties.VALUES.api_endpoint_overrides.testing.Get()
        toolresults_url = properties.VALUES.api_endpoint_overrides.toolresults.Get(
        )
        log.info('Test Service endpoint: [{0}]'.format(testing_url))
        log.info('Tool Results endpoint: [{0}]'.format(toolresults_url))
        if ((toolresults_url is None
             or 'apis.com/toolresults' in toolresults_url) !=
            (testing_url is None or 'testing.googleapis' in testing_url)):
            raise exceptions.ToolException(
                'Service endpoints [{0}] and [{1}] are not compatible.'.format(
                    testing_url, toolresults_url))

        http = self.Http()

        # Create the Testing service client
        resources.SetParamDefault(api='test',
                                  collection=None,
                                  param='project',
                                  resolver=resolvers.FromProperty(
                                      properties.VALUES.core.project))
        # TODO(user) Support multiple versions when they exist
        testing_client_v1 = testing_v1.TestingV1(get_credentials=False,
                                                 url=testing_url,
                                                 http=http)
        testing_registry = resources.REGISTRY.CloneAndSwitchAPIs(
            testing_client_v1)
        context['testing_client'] = testing_client_v1
        context['testing_messages'] = testing_v1
        context['testing_registry'] = testing_registry

        # Create the Tool Results service client.
        resources.SetParamDefault(api='toolresults',
                                  collection=None,
                                  param='project',
                                  resolver=resolvers.FromProperty(
                                      properties.VALUES.core.project))
        toolresults_client_v1 = toolresults_v1beta3.ToolresultsV1beta3(
            get_credentials=False, url=toolresults_url, http=http)
        tr_registry = resources.REGISTRY.CloneAndSwitchAPIs(
            toolresults_client_v1)
        context['toolresults_client'] = toolresults_client_v1
        context['toolresults_messages'] = toolresults_v1beta3
        context['toolresults_registry'] = tr_registry

        # TODO(user): remove this message for general release.
        log.status.Print(
            '\nHave questions, feedback, or issues? Please let us know by using '
            'this Google Group:\n  https://groups.google.com/forum/#!forum'
            '/google-cloud-test-lab-external\n')

        return context
Пример #12
0
    def Run(self, args):
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        client = holder.client

        backend_service_ref = (
            flags.GLOBAL_REGIONAL_BACKEND_SERVICE_ARG.ResolveAsResource(
                args,
                holder.resources,
                scope_lister=compute_flags.GetDefaultScopeLister(client)))

        data = console_io.ReadFromFileOrStdin(args.source or '-', binary=False)

        try:
            backend_service = export_util.Import(
                message_type=client.messages.BackendService,
                stream=data,
                schema_path=self.GetSchemaPath())
        except yaml_validator.ValidationError as e:
            raise exceptions.ToolException(str(e))

        # Get existing backend service.
        try:
            backend_service_old = backend_services_utils.SendGetRequest(
                client, backend_service_ref)
        except apitools_exceptions.HttpError as error:
            if error.status_code != 404:
                raise error
            # Backend service does not exist, create a new one.
            return self.SendInsertRequest(client, backend_service_ref,
                                          backend_service)

        # No change, do not send requests to server.
        if backend_service_old == backend_service:
            return

        console_io.PromptContinue(
            message=('Backend Service [{0}] will be overwritten.').format(
                backend_service_ref.Name()),
            cancel_on_no=True)

        # populate id and fingerprint fields. These two fields are manually
        # removed from the schema files.
        backend_service.id = backend_service_old.id
        backend_service.fingerprint = backend_service_old.fingerprint

        # Unspecified fields are assumed to be cleared.
        cleared_fields = []
        if hasattr(backend_service, 'securitySettings') is None:
            cleared_fields.append('securitySettings')
        if hasattr(backend_service, 'localityLbPolicy') is None:
            cleared_fields.append('localityLbPolicy')
        if hasattr(backend_service, 'circuitBreakers') is None:
            cleared_fields.append('circuitBreakers')
        if hasattr(backend_service, 'consistentHash') is None:
            cleared_fields.append('consistentHash')
        if hasattr(backend_service, 'outlierDetection') is None:
            cleared_fields.append('outlierDetection')
        if not backend_service.customRequestHeaders:
            cleared_fields.append('customRequestHeaders')
        if self._support_flexible_cache_step_one:
            if not backend_service.customResponseHeaders:
                cleared_fields.append('customResponseHeaders')
            if backend_service.cdnPolicy:
                cdn_policy = backend_service.cdnPolicy
                if cdn_policy.defaultTtl is None:
                    cleared_fields.append('cdnPolicy.defaultTtl')
                if cdn_policy.clientTtl is None:
                    cleared_fields.append('cdnPolicy.clientTtl')
                if cdn_policy.maxTtl is None:
                    cleared_fields.append('cdnPolicy.maxTtl')
                if not cdn_policy.negativeCachingPolicy:
                    cleared_fields.append('cdnPolicy.negativeCachingPolicy')
            else:
                cleared_fields.append('cdnPolicy')

        with client.apitools_client.IncludeFields(cleared_fields):
            return self.SendPatchRequest(client, backend_service_ref,
                                         backend_service)
    def Run(self, args):
        """Run the helper command."""

        if args.method not in GitHelper.METHODS:
            if args.ignore_unknown:
                return
            raise c_exc.ToolException(
                'Unexpected method [{meth}]. One of [{methods}] expected.'.
                format(meth=args.method, methods=', '.join(GitHelper.METHODS)))

        info = self._ParseInput()
        credentialed_domains = ['source.developers.google.com']
        extra = properties.VALUES.core.credentialed_hosted_repo_domains.Get()
        if extra:
            credentialed_domains.extend(extra.split(','))
        if info.get('host') not in credentialed_domains:
            if args.ignore_unknown:
                return
            raise c_exc.ToolException(
                'Unknown host [{host}].'.format(host=info.get('host')))

        if args.method == GitHelper.GET:
            account = properties.VALUES.core.account.Get()
            try:
                cred = c_store.Load(account)
                c_store.Refresh(cred)
            except c_store.Error as e:
                sys.stderr.write(
                    textwrap.dedent("""\
            ERROR: {error}
            Run 'gcloud auth login' to log in.
            """.format(error=str(e))))
                return

            self._CheckNetrc()

            sys.stdout.write(
                textwrap.dedent("""\
          username={username}
          password={password}
          """).format(username=account, password=cred.access_token))
        elif args.method == GitHelper.STORE:
            # On OSX, there is an additional credential helper that gets called before
            # ours does.  When we return a token, it gets cached there.  Git continues
            # to get it from there first until it expires.  That command then fails,
            # and the token is deleted, but it does not retry the operation.  The next
            # command gets a new token from us and it starts working again, for an
            # hour.  This erases our credential from the other cache whenever 'store'
            # is called on us.  Because they are called first, the token will already
            # be stored there, and so we can successfully erase it to prevent caching.
            if (platforms.OperatingSystem.Current() ==
                    platforms.OperatingSystem.MACOSX):
                log.debug('Clearing OSX credential cache.')
                try:
                    input_string = 'protocol={protocol}\nhost={host}\n\n'.format(
                        protocol=info.get('protocol'), host=info.get('host'))
                    log.debug('Calling erase with input:\n%s', input_string)
                    p = subprocess.Popen(
                        ['git-credential-osxkeychain', 'erase'],
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
                    (out, err) = p.communicate(input_string)
                    if p.returncode:
                        log.debug(
                            'Failed to clear OSX keychain:\nstdout: {%s}\nstderr: {%s}',
                            out, err)
                # pylint:disable=broad-except, This can fail and should only be done as
                # best effort.
                except Exception as e:
                    log.debug('Failed to clear OSX keychain', exc_info=True)
Пример #14
0
    def _Run(self, args):
        """Returns a list of requests necessary for adding images."""
        holder = self._GetApiHolder()
        client = holder.client
        messages = client.messages
        resource_parser = holder.resources

        image_ref = Create.DISK_IMAGE_ARG.ResolveAsResource(
            args, holder.resources)
        image = messages.Image(
            name=image_ref.image,
            description=args.description,
            sourceType=messages.Image.SourceTypeValueValuesEnum.RAW,
            family=args.family)

        csek_keys = csek_utils.CsekKeyStore.FromArgs(
            args, self._ALLOW_RSA_ENCRYPTED_CSEK_KEYS)
        if csek_keys:
            image.imageEncryptionKey = csek_utils.MaybeToMessage(
                csek_keys.LookupKey(
                    image_ref, raise_if_missing=args.require_csek_key_create),
                client.apitools_client)
        image.imageEncryptionKey = kms_utils.MaybeGetKmsKey(
            args, messages, image.imageEncryptionKey)

        # 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].')

        source_image_project = args.source_image_project
        source_image = args.source_image
        source_image_family = args.source_image_family

        if source_image_project and not (source_image or source_image_family):
            raise exceptions.ToolException(
                'You cannot specify [--source-image-project] unless you are '
                'specifying [--source-image] or [--source-image-family].')

        if source_image or source_image_family:
            image_expander = image_utils.ImageExpander(client, resource_parser)
            _, source_image_ref = image_expander.ExpandImageFlag(
                user_project=image_ref.project,
                image=source_image,
                image_family=source_image_family,
                image_project=source_image_project,
                return_image_resource=True)
            image.sourceImage = source_image_ref.selfLink
            image.sourceImageEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_image_ref, client.apitools_client)

        if args.source_uri:
            source_uri = six.text_type(
                resources.REGISTRY.Parse(args.source_uri))
            image.rawDisk = messages.Image.RawDiskValue(source=source_uri)
        elif args.source_disk:
            source_disk_ref = flags.SOURCE_DISK_ARG.ResolveAsResource(
                args,
                holder.resources,
                scope_lister=compute_flags.GetDefaultScopeLister(client))
            image.sourceDisk = source_disk_ref.SelfLink()
            image.sourceDiskEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_disk_ref, client.apitools_client)
        elif hasattr(args, 'source_snapshot') and args.source_snapshot:
            source_snapshot_ref = flags.SOURCE_SNAPSHOT_ARG.ResolveAsResource(
                args,
                holder.resources,
                scope_lister=compute_flags.GetDefaultScopeLister(client))
            image.sourceSnapshot = source_snapshot_ref.SelfLink()
            image.sourceSnapshotEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_snapshot_ref, client.apitools_client)

        if args.licenses:
            image.licenses = args.licenses

        guest_os_features = getattr(args, 'guest_os_features', [])
        if guest_os_features:
            guest_os_feature_messages = []
            for feature in guest_os_features:
                gf_type = messages.GuestOsFeature.TypeValueValuesEnum(feature)
                guest_os_feature = messages.GuestOsFeature()
                guest_os_feature.type = gf_type
                guest_os_feature_messages.append(guest_os_feature)
            image.guestOsFeatures = guest_os_feature_messages

        initial_state, has_set =\
            image_utils.CreateInitialStateConfig(args, messages)
        if has_set:
            image.shieldedInstanceInitialState = initial_state

        if args.IsSpecified('storage_location'):
            image.storageLocations = [args.storage_location]

        request = messages.ComputeImagesInsertRequest(
            image=image, project=image_ref.project)

        args_labels = getattr(args, 'labels', None)
        if args_labels:
            labels = messages.Image.LabelsValue(additionalProperties=[
                messages.Image.LabelsValue.AdditionalProperty(key=key,
                                                              value=value)
                for key, value in sorted(six.iteritems(args_labels))
            ])
            request.image.labels = labels

        # --force is in GA, --force-create is in beta and deprecated.
        if args.force or getattr(args, 'force_create', None):
            request.forceCreate = True

        return client.MakeRequests(
            [(client.apitools_client.images, 'Insert', request)],
            timeout=POLL_TIMEOUT)
Пример #15
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace, All the arguments that were provided to this
        command invocation.
    Returns:
      None
    Raises:
      bigqueryError.BigqueryError: If the source and destination files are not
        both specified.
      calliope_exceptions.ToolException: If user cancels this operation.
      Exception: If an unexpected value for the --if-exists flag passed gcloud
        validation (which should never happen)
    """
        apitools_client = self.context[commands.APITOOLS_CLIENT_KEY]
        bigquery_messages = self.context[commands.BIGQUERY_MESSAGES_MODULE_KEY]
        resource_parser = self.context[commands.BIGQUERY_REGISTRY_KEY]
        project_id = properties.VALUES.core.project.Get(required=True)

        source_reference = resource_parser.Parse(args.source,
                                                 collection='bigquery.tables')
        source_reference_message = message_conversions.TableResourceToReference(
            bigquery_messages, source_reference)

        destination_resource = resource_parser.Parse(
            args.destination, collection='bigquery.tables')
        destination_reference = message_conversions.TableResourceToReference(
            bigquery_messages, destination_resource)

        if args.if_exists == 'append':
            write_disposition = 'WRITE_APPEND'
            ignore_already_exists = True
        elif args.if_exists == 'fail':
            write_disposition = 'WRITE_EMPTY'
            ignore_already_exists = False
        elif args.if_exists == 'prompt':
            write_disposition = 'WRITE_TRUNCATE'
            ignore_already_exists = False
            if bigquery_client_helper.TableExists(apitools_client,
                                                  bigquery_messages,
                                                  destination_reference):
                if not console_io.PromptContinue(prompt_string='Replace {0}'.
                                                 format(destination_resource)):
                    raise calliope_exceptions.ToolException('canceled by user')
        elif args.if_exists == 'replace':
            write_disposition = 'WRITE_TRUNCATE'
            ignore_already_exists = False
        elif args.if_exists == 'skip':
            if bigquery_client_helper.TableExists(apitools_client,
                                                  bigquery_messages,
                                                  destination_reference):
                return
        else:
            # This should be unreachable.
            raise core_exceptions.InternalError(
                'Unexpected value "{0}" for --if-exists flag.'.format(
                    args.if_exists))

        copy_config = bigquery_messages.JobConfigurationTableCopy(
            sourceTable=source_reference_message,
            destinationTable=destination_reference,
            writeDisposition=write_disposition)

        job_id = job_ids.JobIdProvider().GetJobId(args.job_id,
                                                  args.fingerprint_job_id)

        try:
            job = job_control.ExecuteJob(
                apitools_client,
                bigquery_messages,
                args,
                configuration=bigquery_messages.JobConfiguration(
                    copy=copy_config),
                project_id=project_id,
                job_id=job_id)
        except bigquery.DuplicateError as e:
            if ignore_already_exists:
                job = None
            else:
                raise e

        if job is None:
            log.status.Print('Table "{0}" already exists, skipping'.format(
                destination_resource))
        elif args. async:
            registry = self.context[commands.BIGQUERY_REGISTRY_KEY]
            job_resource = registry.Create(
                'bigquery.jobs',
                projectId=job.jobReference.projectId,
                jobId=job.jobReference.jobId)
            log.CreatedResource(job_resource)
        else:
            log.status.Print('Table [{0}] successfully copied to [{1}]'.format(
                source_reference, destination_resource))
Пример #16
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 exceptions.ToolException(
            '[--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 exceptions.ToolException(
          '[--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:
      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.ToolException(
          '[--next-hop-ilb-region] 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)])
Пример #17
0
def ConvertToJsonObject(json_string):
    """Tries to convert the JSON string into JsonObject."""
    try:
        return extra_types.JsonProtoDecoder(json_string)
    except Exception as e:
        raise exceptions.ToolException('Invalid JSON value: %s' % e.message)
Пример #18
0
def ComputeChange(current,
                  to_be_imported,
                  replace_all=False,
                  origin=None,
                  replace_origin_ns=False):
    """Returns a change for importing the given record-sets.

  Args:
    current: dict, (name, type) keyed dict of current record-sets.
    to_be_imported: dict, (name, type) keyed dict of record-sets to be imported.
    replace_all: bool, Whether the record-sets to be imported should replace the
      current record-sets.
    origin: string, the name of the apex zone ex. "foo.com"
    replace_origin_ns: bool, Whether origin NS records should be imported.

  Raises:
    ToolException: If conflicting CNAME records are found.

  Returns:
    A Change that describes the actions required to import the given
    record-sets.
  """
    messages = core_apis.GetMessagesModule('dns', 'v1')
    change = messages.Change()
    change.additions = []
    change.deletions = []

    current_keys = set(current.keys())
    keys_to_be_imported = set(to_be_imported.keys())

    intersecting_keys = current_keys.intersection(keys_to_be_imported)
    if not replace_all and intersecting_keys:
        raise exceptions.ToolException(
            'Conflicting records for the following (name type): {0}'.format([
                _NameAndType(current[key]) for key in sorted(intersecting_keys)
            ]))

    for key in intersecting_keys:
        current_record = current[key]
        record_to_be_imported = to_be_imported[key]
        rdtype = rdatatype.from_text(key[1])
        if not _FilterOutRecord(current_record.name, rdtype, origin,
                                replace_origin_ns):
            replacement = _RDATA_REPLACEMENTS[rdtype](current_record,
                                                      record_to_be_imported)
            if replacement:
                change.deletions.append(current_record)
                change.additions.append(replacement)

    for key in keys_to_be_imported.difference(current_keys):
        change.additions.append(to_be_imported[key])

    for key in current_keys.difference(keys_to_be_imported):
        current_record = current[key]
        rdtype = rdatatype.from_text(key[1])
        if rdtype is rdatatype.SOA:
            change.deletions.append(current_record)
            change.additions.append(NextSOARecordSet(current_record))
        elif replace_all and not _FilterOutRecord(current_record.name, rdtype,
                                                  origin, replace_origin_ns):
            change.deletions.append(current_record)

    # If the only change is an SOA increment, there is nothing to be done.
    if IsOnlySOAIncrement(change):
        return None

    change.additions.sort(key=_NameAndType)
    change.deletions.sort(key=_NameAndType)
    return change
Пример #19
0
    def Run(self, args):
        """Connects to a Cloud SQL instance.

    Args:
      args: argparse.Namespace, The arguments that this command was invoked
          with.

    Returns:
      If no exception is raised this method does not return. A new process is
      started and the original one is killed.
    Raises:
      HttpException: An http error response was received while executing api
          request.
      ToolException: An error other than http error occured while executing the
          command.
    """
        # TODO(b/62055495): Replace ToolExceptions with specific exceptions.
        client = api_util.SqlClient(api_util.API_VERSION_DEFAULT)
        sql_client = client.sql_client
        sql_messages = client.sql_messages

        validate.ValidateInstanceName(args.instance)
        instance_ref = client.resource_parser.Parse(
            args.instance,
            params={'project': properties.VALUES.core.project.GetOrFail},
            collection='sql.instances')

        acl_name = _WhitelistClientIP(instance_ref, sql_client, sql_messages,
                                      client.resource_parser)

        # Get the client IP that the server sees. Sadly we can only do this by
        # checking the name of the authorized network rule.
        retryer = retry.Retryer(max_retrials=2, exponential_sleep_multiplier=2)
        try:
            instance_info, client_ip = retryer.RetryOnResult(
                _GetClientIP,
                [instance_ref, sql_client, acl_name],
                should_retry_if=lambda x, s: x[1] is None,  # client_ip is None
                sleep_ms=500)
        except retry.RetryException:
            raise exceptions.ToolException(
                'Could not whitelist client IP. Server '
                'did not reply with the whitelisted IP.')

        # Check for the mysql or psql executable based on the db version.
        db_type = instance_info.databaseVersion.split('_')[0]
        exe_name = constants.DB_EXE.get(db_type, 'mysql')
        exe = files.FindExecutableOnPath(exe_name)
        if not exe:
            raise exceptions.ToolException(
                '{0} client not found.  Please install a {1} client and make sure '
                'it is in PATH to be able to connect to the database instance.'
                .format(exe_name.title(), exe_name))

        # Check the version of IP and decide if we need to add ipv4 support.
        ip_type = network.GetIpVersion(client_ip)
        if ip_type == network.IP_VERSION_4:
            if instance_info.settings.ipConfiguration.ipv4Enabled:
                ip_address = instance_info.ipAddresses[0].ipAddress
            else:
                # TODO(b/36049930): ask user if we should enable ipv4 addressing
                message = (
                    'It seems your client does not have ipv6 connectivity and '
                    'the database instance does not have an ipv4 address. '
                    'Please request an ipv4 address for this database instance.'
                )
                raise exceptions.ToolException(message)
        elif ip_type == network.IP_VERSION_6:
            ip_address = instance_info.ipv6Address
        else:
            raise exceptions.ToolException('Could not connect to SQL server.')

        # We have everything we need, time to party!
        flags = constants.EXE_FLAGS[exe_name]
        sql_args = [exe_name, flags['hostname'], ip_address]
        if args.user:
            sql_args.extend([flags['user'], args.user])
        sql_args.append(flags['password'])

        execution_utils.Exec(sql_args)
Пример #20
0
 def RaiseOnPromptFailure():
   """Call this to raise an exn when prompt cannot read from input stream."""
   phrases = ('one of ', 'flags') if len(flag_names) > 1 else ('', 'flag')
   raise calliope_exceptions.ToolException(
       'Unable to prompt. Specify {0}the [{1}] {2}.'.format(
           phrases[0], ', '.join(flag_names), phrases[1]))
Пример #21
0
def _CreateRequests(cmd, args):
    """Make API requests for route creation, callable from multiple tracks."""

    network_uri = cmd.CreateGlobalReference(
        args.network, resource_type='networks').SelfLink()

    if args.next_hop_instance:
        next_hop_instance_uri = cmd.CreateZonalReference(
            args.next_hop_instance,
            args.next_hop_instance_zone,
            flag_names=['--next-hop-instance-zone'],
            resource_type='instances').SelfLink()
    else:
        if args.next_hop_instance_zone:
            raise exceptions.ToolException(
                '[--next-hop-instance-zone] can only be specified in conjunction '
                'with [--next-hop-instance].')
        next_hop_instance_uri = None

    if args.next_hop_gateway:
        # TODO(b/18201355): This is hack.
        #
        # There is currently no "gateways" resource type in the Compute
        # API, however, the API does accept a "gateways" URI. We need to
        # extend the resources module to allow for arbitrary URI
        # patterns to be registered. With the logic below, a URI value
        # for --next-hop-gateway will not work.
        next_hop_gateway_uri = (cmd.compute.url + 'projects/' + cmd.project +
                                '/global/gateways/' + args.next_hop_gateway)
    else:
        next_hop_gateway_uri = None

    route_ref = cmd.CreateGlobalReference(args.name)

    next_hop_vpn_tunnel_uri = None

    if args.next_hop_vpn_tunnel:
        next_hop_vpn_tunnel_uri = cmd.CreateRegionalReference(
            args.next_hop_vpn_tunnel,
            args.next_hop_vpn_tunnel_region,
            flag_names=['--next-hop-vpn-tunnel'],
            resource_type='vpnTunnels').SelfLink()
    elif args.next_hop_vpn_tunnel_region:
        raise exceptions.ToolException(
            '[--next-hop-vpn-tunnel-region] can only be specified in '
            'conjunction with [--next-hop-vpn-tunnel].')

    request = cmd.messages.ComputeRoutesInsertRequest(
        project=cmd.project,
        route=cmd.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,
        ))
    return [request]
Пример #22
0
    def Run(self, args):
        """Returns a list of requests necessary for adding images."""
        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        client = holder.client
        messages = client.messages
        resource_parser = holder.resources

        image_ref = Create.DISK_IMAGE_ARG.ResolveAsResource(
            args, holder.resources)
        image = messages.Image(
            name=image_ref.image,
            description=args.description,
            sourceType=messages.Image.SourceTypeValueValuesEnum.RAW,
            family=args.family)

        csek_keys = csek_utils.CsekKeyStore.FromArgs(
            args, self._ALLOW_RSA_ENCRYPTED_CSEK_KEYS)
        if csek_keys:
            image.imageEncryptionKey = csek_utils.MaybeToMessage(
                csek_keys.LookupKey(
                    image_ref, raise_if_missing=args.require_csek_key_create),
                client.apitools_client)
        image.imageEncryptionKey = kms_utils.MaybeGetKmsKey(
            args, image_ref.project, client.apitools_client,
            image.imageEncryptionKey)

        # 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].')

        source_image_project = getattr(args, 'source_image_project', None)
        source_image = getattr(args, 'source_image', None)
        source_image_family = getattr(args, 'source_image_family', None)

        if source_image_project and not (source_image or source_image_family):
            raise exceptions.ToolException(
                'You cannot specify [--source-image-project] unless you are '
                'specifying [--source-image] or [--source-image-family].')

        if source_image or source_image_family:
            image_expander = image_utils.ImageExpander(client, resource_parser)
            _, source_image_ref = image_expander.ExpandImageFlag(
                user_project=image_ref.project,
                image=source_image,
                image_family=source_image_family,
                image_project=source_image_project,
                return_image_resource=True)
            image.sourceImage = source_image_ref.selfLink
            image.sourceImageEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_image_ref, client.apitools_client)

        # TODO(b/30086260): use resources.REGISTRY.Parse() for GCS URIs.
        if args.source_uri:
            source_uri = utils.NormalizeGoogleStorageUri(args.source_uri)
            image.rawDisk = messages.Image.RawDiskValue(source=source_uri)
        elif args.source_disk:
            source_disk_ref = flags.SOURCE_DISK_ARG.ResolveAsResource(
                args,
                holder.resources,
                scope_lister=compute_flags.GetDefaultScopeLister(client))
            image.sourceDisk = source_disk_ref.SelfLink()
            image.sourceDiskEncryptionKey = csek_utils.MaybeLookupKeyMessage(
                csek_keys, source_disk_ref, client.apitools_client)

        if args.licenses:
            image.licenses = args.licenses

        guest_os_features = getattr(args, 'guest_os_features', [])
        if guest_os_features:
            guest_os_feature_messages = []
            for feature in guest_os_features:
                gf_type = messages.GuestOsFeature.TypeValueValuesEnum(feature)
                guest_os_feature = messages.GuestOsFeature()
                guest_os_feature.type = gf_type
                guest_os_feature_messages.append(guest_os_feature)
            image.guestOsFeatures = guest_os_feature_messages

        request = messages.ComputeImagesInsertRequest(
            image=image, project=image_ref.project)

        args_labels = getattr(args, 'labels', None)
        if args_labels:
            labels = messages.Image.LabelsValue(additionalProperties=[
                messages.Image.LabelsValue.AdditionalProperty(key=key,
                                                              value=value)
                for key, value in sorted(args_labels.iteritems())
            ])
            request.image.labels = labels

        # --force is in GA, --force-create is in beta and deprecated.
        if args.force or getattr(args, 'force_create', None):
            request.forceCreate = True

        return client.MakeRequests([(client.apitools_client.images, 'Insert',
                                     request)])
Пример #23
0
    def MonitorTestExecutionProgress(self, test_id):
        """Monitor and report the progress of a single running test.

    This method prints more detailed test progress messages for the case where
    the matrix has exactly one supported test configuration.

    Args:
      test_id: str, the unique id of the single supported test in the matrix.

    Raises:
      ToolException if the Test service reports a backend error.
    """
        states = self._messages.TestExecution.StateValueValuesEnum
        last_state = ''
        error = ''
        progress = []
        last_progress_len = 0

        while True:
            status = self._GetTestExecutionStatus(test_id)
            timestamp = self._clock().strftime(_TIMESTAMP_FORMAT)
            # Check for optional error and progress details
            details = status.testDetails
            if details:
                error = details.errorMessage or ''
                progress = details.progressMessages or []

            # Progress is cumulative, so only print what's new since the last update.
            for msg in progress[last_progress_len:]:
                log.status.Print('{0} {1}'.format(timestamp, msg.rstrip()))
            last_progress_len = len(progress)

            if status.state == states.ERROR:
                raise exceptions.ToolException(
                    'Firebase Test Lab infrastructure failure: {e}'.format(
                        e=error),
                    exit_code=exit_code.INFRASTRUCTURE_ERR)

            if status.state == states.UNSUPPORTED_ENVIRONMENT:
                msg = (
                    'Device dimensions are not compatible: {d}. '
                    'Please use "gcloud beta test android devices list" to '
                    'determine which device dimensions are compatible.'.format(
                        d=_FormatInvalidDimension(status.environment)))
                raise exceptions.ToolException(
                    msg, exit_code=exit_code.UNSUPPORTED_ENV)

            # Inform user of test progress, typically PENDING -> RUNNING -> FINISHED
            if status.state != last_state:
                last_state = status.state
                log.status.Print('{0} Test is {1}'.format(
                    timestamp, self._state_names[last_state]))

            if status.state in self._completed_execution_states:
                break

            self._SleepForStatusInterval()

        # Even if the single TestExecution is done, we also need to wait for the
        # matrix to reach a finalized state before monitoring is done.
        matrix = self.GetTestMatrixStatus()
        while matrix.state not in self.completed_matrix_states:
            log.debug('Matrix not yet complete, still in state: %s',
                      matrix.state)
            self._SleepForStatusInterval()
            matrix = self.GetTestMatrixStatus()
        self._LogTestComplete(matrix.state)
        return
Пример #24
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)

        if self._support_reservation:
            instances_flags.ValidateReservationAffinityGroup(args)

        holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
        compute_client = holder.client
        resource_parser = holder.resources

        instance_refs = instance_utils.GetInstanceRefs(args, compute_client,
                                                       holder)

        requests = self._CreateRequests(args, instance_refs, 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 exceptions.ToolException(
                        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
Пример #25
0
    def Run(self, args):
        super(Scp, self).Run(args)

        file_specs = []

        # Parses the positional arguments.
        for arg in args.sources + [args.destination]:
            if ssh_utils.IsScpLocalPath(arg):
                file_specs.append(LocalFile(arg))
            else:
                user_host, file_path = arg.split(':', 1)
                user_host_parts = user_host.split('@', 1)
                if len(user_host_parts) == 1:
                    user = ssh_utils.GetDefaultSshUsername(
                        warn_on_account_user=True)
                    instance = user_host_parts[0]
                else:
                    user, instance = user_host_parts
                file_specs.append(RemoteFile(user, instance, file_path))

        log.debug('Normalized arguments: %s', file_specs)

        # Validates the positional arguments.
        # TODO(b/21515495): Look into relaxing these conditions.
        sources = file_specs[:-1]
        destination = file_specs[-1]
        if isinstance(destination, LocalFile):
            for source in sources:
                if isinstance(source, LocalFile):
                    raise exceptions.ToolException(
                        'All sources must be remote files when the destination '
                        'is local.')

        else:  # RemoteFile
            for source in sources:
                if isinstance(source, RemoteFile):
                    raise exceptions.ToolException(
                        'All sources must be local files when the destination '
                        'is remote.')

        instances = set()
        for file_spec in file_specs:
            if isinstance(file_spec, RemoteFile):
                instances.add(file_spec.instance_name)

        if len(instances) > 1:
            raise exceptions.ToolException(
                'Copies must involve exactly one virtual machine instance; '
                'your invocation refers to [{0}] instances: [{1}].'.format(
                    len(instances), ', '.join(sorted(instances))))

        instance_ref = self.CreateZonalReference(instances.pop(), args.zone)
        instance = self.GetInstance(instance_ref)
        external_ip_address = ssh_utils.GetExternalIPAddress(instance)

        # Builds the scp command.
        scp_args = [self.scp_executable]
        if not args.plain:
            scp_args.extend(self.GetDefaultFlags())

        # apply args
        if args.quiet:
            scp_args.append('-q')
        if args.port:
            scp_args.extend(['-P', args.port])
        if args.recurse:
            scp_args.append('-r')
        if args.compress:
            scp_args.append('-C')
        if args.scp_flag:
            scp_args.extend(args.scp_flag)

        for file_spec in file_specs:
            if isinstance(file_spec, LocalFile):
                scp_args.append(file_spec.file_path)

            else:
                scp_args.append('{0}:{1}'.format(
                    ssh_utils.UserHost(file_spec.user, external_ip_address),
                    file_spec.file_path))

        self.ActuallyRun(args, scp_args, user, instance)
Пример #26
0
    def Run(self, args):
        super(CopyFiles, self).Run(args)

        file_specs = []

        # Parses the positional arguments.
        for arg in args.sources + [args.destination]:
            if ssh.IsScpLocalPath(arg):
                file_specs.append(LocalFile(arg))
            else:
                user_host, file_path = arg.split(':', 1)
                user_host_parts = user_host.split('@', 1)
                if len(user_host_parts) == 1:
                    user = ssh.GetDefaultSshUsername(warn_on_account_user=True)
                    source_instance = user_host_parts[0]
                else:
                    user, source_instance = user_host_parts
                file_specs.append(RemoteFile(user, source_instance, file_path))

        log.debug('Normalized arguments: %s', file_specs)

        # Validates the positional arguments.
        # TODO(user): Look into relaxing these conditions.
        sources = file_specs[:-1]
        destination = file_specs[-1]
        if isinstance(destination, LocalFile):
            for source in sources:
                if isinstance(source, LocalFile):
                    raise exceptions.ToolException(
                        'All sources must be remote files when the destination '
                        'is local.')

        else:  # RemoteFile
            for source in sources:
                if isinstance(source, RemoteFile):
                    raise exceptions.ToolException(
                        'All sources must be local files when the destination '
                        'is remote.')

        destination_instances = set()
        for file_spec in file_specs:
            if isinstance(file_spec, RemoteFile):
                destination_instances.add(file_spec.instance_name)

        if len(destination_instances) > 1:
            raise exceptions.ToolException(
                'Copies must involve exactly one virtual machine instance; '
                'your invocation refers to [{0}] instances: [{1}].'.format(
                    len(destination_instances),
                    ', '.join(sorted(destination_instances))))

        source_instance_ref = instance_flags.SSH_INSTANCE_RESOLVER.ResolveResources(
            [source_instance],
            compute_scope.ScopeEnum.ZONE,
            args.zone,
            self.resources,
            scope_lister=flags.GetDefaultScopeLister(self.compute_client,
                                                     self.project))[0]
        source_instance = self.GetInstance(source_instance_ref)
        external_ip_address = ssh_utils.GetExternalIPAddress(source_instance)

        # Builds the scp command.
        scp_args = [self.env.scp]
        if not args.plain:
            scp_args.extend(ssh.GetDefaultFlags(self.keys.key_file))
            host_key_alias = self.HostKeyAlias(source_instance)
            scp_args.extend(
                ssh.GetHostKeyArgs(host_key_alias, args.plain,
                                   args.strict_host_key_checking))
            scp_args.append('-r')

        for file_spec in file_specs:
            if isinstance(file_spec, LocalFile):
                scp_args.append(file_spec.file_path)

            else:
                scp_args.append('{0}:{1}'.format(
                    ssh.UserHost(file_spec.user, external_ip_address),
                    file_spec.file_path))

        self.ActuallyRun(args, scp_args, user, source_instance,
                         source_instance_ref.project)
Пример #27
0
def BackupConfiguration(sql_messages,
                        instance=None,
                        backup_enabled=None,
                        backup_location=None,
                        backup_start_time=None,
                        enable_bin_log=None,
                        enable_point_in_time_recovery=None):
  """Generates the backup configuration for the instance.

  Args:
    sql_messages: module, The messages module that should be used.
    instance: sql_messages.DatabaseInstance, the original instance, if the
      previous state is needed.
    backup_enabled: boolean, True if backup should be enabled.
    backup_location: string, location where to store backups by default.
    backup_start_time: string, start time of backup specified in 24-hour format.
    enable_bin_log: boolean, True if binary logging should be enabled.
    enable_point_in_time_recovery: boolean, True if point-in-time recovery
      (using write-ahead log archiving) should be enabled.

  Returns:
    sql_messages.BackupConfiguration object, or None

  Raises:
    ToolException: Bad combination of arguments.
  """
  should_generate_config = any([
      backup_location is not None,
      backup_start_time,
      enable_bin_log is not None,
      enable_point_in_time_recovery is not None,
      not backup_enabled,
  ])

  if not should_generate_config:
    return None

  if not instance or not instance.settings.backupConfiguration:
    backup_config = sql_messages.BackupConfiguration(
        kind='sql#backupConfiguration',
        startTime='00:00',
        enabled=backup_enabled)
  else:
    backup_config = instance.settings.backupConfiguration

  if backup_location is not None:
    backup_config.location = backup_location
    backup_config.enabled = True
  if backup_start_time:
    backup_config.startTime = backup_start_time
    backup_config.enabled = True
  if not backup_enabled:
    if backup_location is not None or backup_start_time:
      raise exceptions.ToolException(
          'Argument --no-backup not allowed with --backup_location or '
          '--backup-start-time')
    backup_config.enabled = False

  if enable_bin_log is not None:
    backup_config.binaryLogEnabled = enable_bin_log

  if enable_point_in_time_recovery is not None:
    backup_config.pointInTimeRecoveryEnabled = enable_point_in_time_recovery

  return backup_config
Пример #28
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace, All the arguments that were provided to this
        command invocation.

    Raises:
       ToolException: if no query was provided.

    Returns:
      If the --dry_run or --async flag was specified, None; otherwise, a
      SchemaAndRows object.
    """
        apitools_client = self.context[commands.APITOOLS_CLIENT_KEY]
        bigquery_messages = self.context[commands.BIGQUERY_MESSAGES_MODULE_KEY]
        resource_parser = self.context[commands.BIGQUERY_REGISTRY_KEY]
        project_id = properties.VALUES.core.project.Get(required=True)
        if not args.sql_query:
            raise exceptions.ToolException('No query string provided')
        destination_table = args.append_to or args.write_to
        if destination_table:
            output_resource = resource_parser.Parse(
                destination_table, collection='bigquery.tables')
            output_reference = message_conversions.TableResourceToReference(
                bigquery_messages, output_resource)
        else:
            output_reference = None
        query_configuration = bigquery_messages.JobConfigurationQuery(
            allowLargeResults=args.allow_large_results,
            createDisposition='CREATE_NEVER' if args.require_cache else None,
            # Set defaultDataset here if we choose to support a
            # --default-dataset-in-query flag.
            destinationTable=output_reference,
            flattenResults=not args.structured,
            preserveNulls=None,
            priority='BATCH' if args.batch else None,
            query=args.sql_query,
            useQueryCache=args.use_cache,
            writeDisposition=((args.append_to and 'WRITE_APPEND')
                              or (args.write_to and 'WRITE_TRUNCATE')))
        job = job_control.ExecuteJob(
            apitools_client,
            bigquery_messages,
            args,
            configuration=bigquery_messages.JobConfiguration(
                query=query_configuration, dryRun=args.dry_run),
            async=args. async,
            project_id=project_id,
            job_id=job_ids.JobIdProvider().GetJobId(args.job_id,
                                                    args.fingerprint_job_id))

        if args.dry_run:
            log.Print(
                'Query successfully validated. Assuming the tables are not '
                'modified, running this query will process {0} bytes of data.'.
                format(job.statistics.query.totalBytesProcessed))
        elif args. async:
            job_resource = resource_parser.Create(
                'bigquery.jobs',
                projectId=job.jobReference.projectId,
                jobId=job.jobReference.jobId)
            log.CreatedResource(job_resource)
        else:
            return schema_and_rows.GetJobSchemaAndRows(apitools_client,
                                                       bigquery_messages,
                                                       job.jobReference,
                                                       args.start_row,
                                                       args.limit)
Пример #29
0
  def Run(self, args):
    super(CopyFiles, self).Run(args)

    file_specs = []

    # Parses the positional arguments.
    for arg in args.sources + [args.destination]:
      # If the argument begins with "./" or "/", then we are dealing
      # with a local file that can potentially contain colons, so we
      # avoid splitting on colons. The case of remote files containing
      # colons is handled below by splitting only on the first colon.
      if arg.startswith('./') or arg.startswith('/'):
        file_specs.append(LocalFile(arg))
        continue

      host_file_parts = arg.split(':', 1)
      if len(host_file_parts) == 1:
        file_specs.append(LocalFile(host_file_parts[0]))
      else:
        user_host, file_path = host_file_parts
        user_host_parts = user_host.split('@', 1)
        if len(user_host_parts) == 1:
          user = getpass.getuser()
          instance = user_host_parts[0]
        else:
          user, instance = user_host_parts

        file_specs.append(RemoteFile(user, instance, file_path))

    logging.debug('Normalized arguments: %s', file_specs)

    # Validates the positional arguments.
    # TODO(user): Look into relaxing these conditions.
    sources = file_specs[:-1]
    destination = file_specs[-1]
    if isinstance(destination, LocalFile):
      for source in sources:
        if isinstance(source, LocalFile):
          raise exceptions.ToolException(
              'All sources must be remote files when the destination '
              'is local.')

    else:  # RemoteFile
      for source in sources:
        if isinstance(source, RemoteFile):
          raise exceptions.ToolException(
              'All sources must be local files when the destination '
              'is remote.')

    instances = set()
    for file_spec in file_specs:
      if isinstance(file_spec, RemoteFile):
        instances.add(file_spec.instance_name)

    if len(instances) > 1:
      raise exceptions.ToolException(
          'Copies must involve exactly one virtual machine instance; '
          'your invocation refers to [{0}] instances: [{1}].'.format(
              len(instances), ', '.join(sorted(instances))))

    instance_ref = self.CreateZonalReference(instances.pop(), args.zone)
    external_ip_address = self.GetInstanceExternalIpAddress(instance_ref)

    # Builds the scp command.
    scp_args = [self.scp_executable]
    if not args.plain:
      scp_args.extend(self.GetDefaultFlags())
      scp_args.append('-r')

    for file_spec in file_specs:
      if isinstance(file_spec, LocalFile):
        scp_args.append(file_spec.file_path)

      else:
        scp_args.append('{0}:{1}'.format(
            ssh_utils.UserHost(file_spec.user, external_ip_address),
            file_spec.file_path))

    self.ActuallyRun(args, scp_args, user, external_ip_address)
Пример #30
0
  def Run(self, args):
    if not args.all and not args.keys:
      raise calliope_exceptions.ToolException(
          'One of [--all] or [--keys] must be provided.')

    return super(BaseMetadataRemover, self).Run(args)