Пример #1
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:
      Cluster message for the successfully created cluster.

    Raises:
      ToolException, if creation failed.
    """
        client = self.context['container_client']
        messages = self.context['container_messages']
        cluster_ref = util.ParseCluster(args.name, self.context)

        if args.password:
            password = args.password
        else:
            password = ''.join(
                random.SystemRandom().choice(string.ascii_letters +
                                             string.digits) for _ in range(16))

        node_config = messages.NodeConfig()
        if args.machine_type:
            node_config.machineType = args.machine_type
        if args.source_image:
            node_config.sourceImage = args.source_image
        node_config.serviceAccounts = self.CreateServiceAccountMessages(
            args, messages)

        create_cluster_req = messages.CreateClusterRequest(
            cluster=messages.Cluster(
                name=cluster_ref.clusterId,
                numNodes=args.num_nodes,
                nodeConfig=node_config,
                masterAuth=messages.MasterAuth(user=args.user,
                                               password=password),
                enableCloudLogging=args.enable_cloud_logging))
        if args.cluster_api_version:
            create_cluster_req.cluster.clusterApiVersion = args.cluster_api_version
        if args.network:
            create_cluster_req.cluster.network = args.network
        if args.container_ipv4_cidr:
            create_cluster_req.cluster.containerIpv4Cidr = args.container_ipv4_cidr

        req = messages.ContainerProjectsZonesClustersCreateRequest(
            createClusterRequest=create_cluster_req,
            projectId=cluster_ref.projectId,
            zoneId=cluster_ref.zoneId)

        cluster = None
        try:
            operation = client.projects_zones_clusters.Create(req)

            if not args.wait:
                return util.DescribeCluster(cluster_ref, self.context)

            operation = util.WaitForOperation(
                operation, cluster_ref.projectId, self.context,
                'Creating cluster {0}'.format(cluster_ref.clusterId))

            # Get Cluster
            cluster = util.DescribeCluster(cluster_ref, self.context)
        except apitools_base.HttpError as error:
            raise exceptions.HttpException(util.GetError(error))

        log.CreatedResource(cluster_ref)
        # Persist cluster config
        c_config = util.ClusterConfig.Persist(cluster, cluster_ref.projectId,
                                              self.cli)
        if c_config:
            if not c_config.has_certs:
                # Purge config so we retry the cert fetch on next kubectl command
                util.ClusterConfig.Purge(cluster.name, cluster.zone,
                                         cluster_ref.projectId)
                # Exit with non-success returncode if certs could not be fetched
                self.exit_code = 1
            else:
                # Set current-context to new cluster if one is not already set
                kubeconfig = kconfig.Kubeconfig.Default()
                if not kubeconfig.current_context:
                    kubeconfig.SetCurrentContext(c_config.kube_context)
                    kubeconfig.SaveToFile()

        return cluster
Пример #2
0
class Create(base.CreateCommand):
    """Create a cluster for running containers."""
    @staticmethod
    def Args(parser):
        _Args(parser)
        _AddAdditionalZonesFlag(parser, deprecated=True)
        flags.AddNodeLocationsFlag(parser)
        flags.AddAddonsFlags(parser)
        flags.AddClusterAutoscalingFlags(parser)
        flags.AddDiskTypeFlag(parser, suppressed=True)
        flags.AddEnableAutoRepairFlag(parser, for_create=True)
        flags.AddEnableKubernetesAlphaFlag(parser)
        flags.AddEnableLegacyAuthorizationFlag(parser)
        flags.AddIPAliasFlags(parser)
        flags.AddLabelsFlag(parser)
        flags.AddLocalSSDFlag(parser)
        flags.AddMaintenanceWindowFlag(parser)
        flags.AddMasterAuthorizedNetworksFlags(parser)
        flags.AddMinCpuPlatformFlag(parser)
        flags.AddNetworkPolicyFlags(parser)
        flags.AddNodeTaintsFlag(parser)
        flags.AddPreemptibleFlag(parser)
        flags.AddDeprecatedClusterNodeIdentityFlags(parser)

    def ParseCreateOptions(self, args):
        return ParseCreateOptionsBase(args)

    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:
      Cluster message for the successfully created cluster.

    Raises:
      util.Error, if creation failed.
    """
        if args. async and not args.IsSpecified('format'):
            args.format = util.OPERATIONS_FORMAT

        util.CheckKubectlInstalled()

        adapter = self.context['api_adapter']
        location_get = self.context['location_get']
        location = location_get(args)

        cluster_ref = adapter.ParseCluster(args.name, location)
        options = self.ParseCreateOptions(args)

        if options.enable_kubernetes_alpha:
            console_io.PromptContinue(
                message=constants.KUBERNETES_ALPHA_PROMPT,
                throw_if_unattended=True,
                cancel_on_no=True)

        if getattr(args, 'region', None):
            # TODO(b/68496825): Remove this completely after regional clusters beta
            # launch.
            if self._release_track == base.ReleaseTrack.ALPHA:
                console_io.PromptContinue(
                    message=constants.KUBERNETES_REGIONAL_CHARGES_PROMPT,
                    throw_if_unattended=True,
                    cancel_on_no=True)

        if options.enable_autorepair is not None:
            log.status.Print(
                messages.AutoUpdateUpgradeRepairMessage(
                    options.enable_autorepair, 'autorepair'))

        if options.enable_autoupgrade is not None:
            log.status.Print(
                messages.AutoUpdateUpgradeRepairMessage(
                    options.enable_autoupgrade, 'autoupgrade'))

        if options.accelerators is not None:
            log.status.Print(constants.KUBERNETES_GPU_LIMITATION_MSG)

        operation = None
        try:
            operation_ref = adapter.CreateCluster(cluster_ref, options)
            if args. async:
                return adapter.GetCluster(cluster_ref)

            operation = adapter.WaitForOperation(operation_ref,
                                                 'Creating cluster {0}'.format(
                                                     cluster_ref.clusterId),
                                                 timeout_s=args.timeout)
            cluster = adapter.GetCluster(cluster_ref)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

        log.CreatedResource(cluster_ref)
        cluster_url = util.GenerateClusterUrl(cluster_ref)
        log.status.Print('To inspect the contents of your cluster, go to: ' +
                         cluster_url)
        if operation.detail:
            # Non-empty detail on a DONE create operation should be surfaced as
            # a warning to end user.
            log.warning(operation.detail)

        try:
            util.ClusterConfig.Persist(cluster, cluster_ref.projectId)
        except kconfig.MissingEnvVarError as error:
            log.warning(error)

        return [cluster]
Пример #3
0
    def Run(self, args):
        """Run 'deployments delete'.

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

    Returns:
      If --async=true, returns Operation to poll.
      Else, returns boolean indicating whether insert operation succeeded.

    Raises:
      HttpException: An http error response was received while executing api
          request.
      ToolException: The deployment deletion operation encountered an error.
    """
        client = self.context['deploymentmanager-client']
        messages = self.context['deploymentmanager-messages']
        project = properties.VALUES.core.project.Get(required=True)

        prompt_message = ('The following deployments will be deleted:\n- ' +
                          '\n- '.join(args.deployment_name))
        if not args.quiet:
            if not console_io.PromptContinue(message=prompt_message,
                                             default=False):
                raise exceptions.ToolException('Deletion aborted by user.')

        operations = []
        for deployment_name in args.deployment_name:
            try:
                operation = client.deployments.Delete(
                    messages.DeploymentmanagerDeploymentsDeleteRequest(
                        project=project,
                        deployment=deployment_name,
                    ))
            except apitools_base.HttpError as error:
                raise exceptions.HttpException(dm_v2_util.GetError(error))
            if args. async:
                operations.append(operation)
            else:
                op_name = operation.name
                try:
                    dm_v2_util.WaitForOperation(op_name, project, self.context,
                                                'delete', OPERATION_TIMEOUT)
                    log.status.Print('Delete operation ' + op_name +
                                     ' completed successfully.')
                except (exceptions.ToolException, DeploymentManagerError):
                    log.error('Delete operation ' + op_name +
                              ' has errors or failed to complete within in ' +
                              str(OPERATION_TIMEOUT) + ' seconds.')
                except apitools_base.HttpError as error:
                    raise exceptions.HttpException(dm_v2_util.GetError(error))
                try:
                    completed_operation = client.operations.Get(
                        messages.DeploymentmanagerOperationsGetRequest(
                            project=project,
                            operation=op_name,
                        ))
                except apitools_base.HttpError as error:
                    raise exceptions.HttpException(dm_v2_util.GetError(error))
                operations.append(completed_operation)

        return operations
Пример #4
0
  def Run(self, args):
    """Run 'deployments stop'.

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

    Returns:
      If --async=true, returns Operation to poll.
      Else, returns boolean indicating whether stop operation succeeded.

    Raises:
      HttpException: An http error response was received while executing api
          request.
    """
    if args.fingerprint:
      fingerprint = dm_util.DecodeFingerprint(args.fingerprint)
    else:
      # If no fingerprint is present, default to an empty fingerprint.
      # TODO(b/34966984): Remove the empty default after cleaning up all
      # deployments that has no fingerprint
      fingerprint = dm_v2_util.FetchDeploymentFingerprint(
          dm_base.GetClient(),
          dm_base.GetMessages(),
          dm_base.GetProject(),
          args.deployment_name) or ''
    try:
      operation = dm_base.GetClient().deployments.Stop(
          dm_base.GetMessages().DeploymentmanagerDeploymentsStopRequest(
              project=dm_base.GetProject(),
              deployment=args.deployment_name,
              deploymentsStopRequest=(
                  dm_base.GetMessages().DeploymentsStopRequest(
                      fingerprint=fingerprint)
              ),
          )
      )
    except apitools_exceptions.HttpError as error:
      raise exceptions.HttpException(error, dm_v2_util.HTTP_ERROR_FORMAT)
    if args.async:
      return operation
    else:
      op_name = operation.name
      try:
        dm_write.WaitForOperation(op_name,
                                  'stop',
                                  dm_base.GetProject(),
                                  timeout=OPERATION_TIMEOUT)
        log.status.Print('Stop operation ' + op_name
                         + ' completed successfully.')
      except apitools_exceptions.HttpError as error:
        raise exceptions.HttpException(error, dm_v2_util.HTTP_ERROR_FORMAT)
      try:
        # Fetch a list of the stopped resources.
        response = dm_base.GetClient().resources.List(
            dm_base.GetMessages().DeploymentmanagerResourcesListRequest(
                project=dm_base.GetProject(),
                deployment=args.deployment_name,
            )
        )
        # TODO(b/36055861): Pagination
        return response.resources if response.resources else []
      except apitools_exceptions.HttpError as error:
        raise exceptions.HttpException(error, dm_v2_util.HTTP_ERROR_FORMAT)
Пример #5
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:
      Cluster message for the successfully created cluster.

    Raises:
      util.Error, if creation failed.
    """
        util.CheckKubectlInstalled()
        if not args.password:
            args.password = ''.join(
                random.SystemRandom().choice(string.ascii_letters +
                                             string.digits) for _ in range(16))

        adapter = self.context['api_adapter']

        if not args.scopes:
            args.scopes = []
        cluster_ref = adapter.ParseCluster(args.name)
        options = self.ParseCreateOptions(args)

        operation = None
        try:
            operation_ref = adapter.CreateCluster(cluster_ref, options)
            if not args.wait:
                return adapter.GetCluster(cluster_ref)

            operation = adapter.WaitForOperation(operation_ref,
                                                 'Creating cluster {0}'.format(
                                                     cluster_ref.clusterId),
                                                 timeout_s=args.timeout)
            cluster = adapter.GetCluster(cluster_ref)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(util.GetError(error))

        log.CreatedResource(cluster_ref)
        if operation.detail:
            # Non-empty detail on a DONE create operation should be surfaced as
            # a warning to end user.
            log.warning(operation.detail)
        # Persist cluster config
        current_context = kconfig.Kubeconfig.Default().current_context
        c_config = util.ClusterConfig.Persist(cluster, cluster_ref.projectId)
        if not c_config.has_certs:
            # Purge config so we retry the cert fetch on next kubectl command
            util.ClusterConfig.Purge(cluster.name, cluster.zone,
                                     cluster_ref.projectId)
            # reset current context
            if current_context:
                kubeconfig = kconfig.Kubeconfig.Default()
                kubeconfig.SetCurrentContext(current_context)
                kubeconfig.SaveToFile()
            raise util.Error(
                NO_CERTS_ERROR_FMT.format(
                    command=' '.join(args.command_path[:-1] +
                                     ['get-credentials', cluster.name])))
        return cluster
Пример #6
0
 def Func(*args, **kwargs):
     if args and args[0].startswith('projects/'):
         raise sdk_ex.HttpException('Topics and/or subscription names'
                                    ' should not start with the prefix'
                                    ' "projects/"')
     return f(*args, **kwargs)
Пример #7
0
def RunBaseCreateCommand(args, release_track):
    """Creates a new Cloud SQL instance.

  Args:
    args: argparse.Namespace, The arguments that this command was invoked with.
    release_track: base.ReleaseTrack, the release track that this was run under.

  Returns:
    A dict object representing the operations resource describing the create
    operation if the create was successful.
  Raises:
    HttpException: A http error response was received while executing api
        request.
  """
    client = common_api_util.SqlClient(common_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')

    # Get the region, tier, and database version from the master if these fields
    # are not specified.
    # TODO(b/64266672): Remove once API does not require these fields.
    if args.IsSpecified('master_instance_name'):
        master_instance_ref = client.resource_parser.Parse(
            args.master_instance_name,
            params={'project': properties.VALUES.core.project.GetOrFail},
            collection='sql.instances')
        try:
            master_instance_resource = sql_client.instances.Get(
                sql_messages.SqlInstancesGetRequest(
                    project=instance_ref.project,
                    instance=master_instance_ref.instance))
        except apitools_exceptions.HttpError as error:
            # TODO(b/64292220): Remove once API gives helpful error message.
            log.debug('operation : %s', six.text_type(master_instance_ref))
            exc = exceptions.HttpException(error)
            if resource_property.Get(
                    exc.payload.content,
                    resource_lex.ParseKey('error.errors[0].reason'),
                    None) == 'notAuthorized':
                msg = (
                    'You are either not authorized to access the master instance or '
                    'it does not exist.')
                raise exceptions.HttpException(msg)
            raise
        if not args.IsSpecified('region'):
            args.region = master_instance_resource.region
        if not args.IsSpecified('database_version'):
            args.database_version = master_instance_resource.databaseVersion
        if not args.IsSpecified('tier') and master_instance_resource.settings:
            args.tier = master_instance_resource.settings.tier
        # Check for CMEK usage; warn the user about replica inheriting the setting.
        if master_instance_resource.diskEncryptionConfiguration:
            command_util.ShowCmekWarning('replica', 'the master instance')

    # --root-password is required when creating SQL Server instances
    if args.IsSpecified(
            'database_version') and args.database_version.startswith(
                'SQLSERVER') and not args.IsSpecified('root_password'):
        raise exceptions.RequiredArgumentException(
            '--root-password',
            '`--root-password` is required when creating SQL Server instances.'
        )

    instance_resource = (
        command_util.InstancesV1Beta4.ConstructCreateInstanceFromArgs(
            sql_messages,
            args,
            instance_ref=instance_ref,
            release_track=release_track))

    # TODO(b/122660263): Remove when V1 instances are no longer supported.
    # V1 instances are deprecated. Prompt to continue if one is being created.
    if api_util.IsInstanceV1(instance_resource):
        log.warning(
            'First Generation instances will be automatically upgraded '
            'to Second Generation starting March 4th, 2020, and First Generation '
            'will be fully decommissioned on March 25, 2020. We recommend you '
            'create a Second Generation instance.')
        console_io.PromptContinue(cancel_on_no=True)

    if args.pricing_plan == 'PACKAGE':
        console_io.PromptContinue(
            'Charges will begin accruing immediately. Really create Cloud '
            'SQL instance?',
            cancel_on_no=True)

    operation_ref = None
    try:
        result_operation = sql_client.instances.Insert(instance_resource)

        operation_ref = client.resource_parser.Create(
            'sql.operations',
            operation=result_operation.name,
            project=instance_ref.project)

        if args.async_:
            if not args.IsSpecified('format'):
                args.format = 'default'
            return sql_client.operations.Get(
                sql_messages.SqlOperationsGetRequest(
                    project=operation_ref.project,
                    operation=operation_ref.operation))

        operations.OperationsV1Beta4.WaitForOperation(
            sql_client,
            operation_ref,
            'Creating Cloud SQL instance',
            # TODO(b/138403566): Remove the override once we improve creation times.
            max_wait_seconds=680)

        log.CreatedResource(instance_ref)

        new_resource = sql_client.instances.Get(
            sql_messages.SqlInstancesGetRequest(
                project=instance_ref.project, instance=instance_ref.instance))
        return new_resource
    except apitools_exceptions.HttpError as error:
        log.debug('operation : %s', six.text_type(operation_ref))
        exc = exceptions.HttpException(error)
        if resource_property.Get(
                exc.payload.content,
                resource_lex.ParseKey('error.errors[0].reason'),
                None) == 'errorMaxInstancePerLabel':
            msg = resource_property.Get(exc.payload.content,
                                        resource_lex.ParseKey('error.message'),
                                        None)
            raise exceptions.HttpException(msg)
        raise
Пример #8
0
def RunBaseCreateCommand(args, release_track):
    """Creates a new Cloud SQL instance.

  Args:
    args: argparse.Namespace, The arguments that this command was invoked with.
    release_track: base.ReleaseTrack, the release track that this was run under.

  Returns:
    A dict object representing the operations resource describing the create
    operation if the create was successful.
  Raises:
    HttpException: A http error response was received while executing api
        request.
    ArgumentError: An argument supplied by the user was incorrect, such as
      specifying an invalid CMEK configuration or attempting to create a V1
      instance.
    RequiredArgumentException: A required argument was not supplied by the user,
      such as omitting --root-password on a SQL Server instance.
  """
    client = common_api_util.SqlClient(common_api_util.API_VERSION_DEFAULT)
    sql_client = client.sql_client
    sql_messages = client.sql_messages

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

    # Get the region, tier, and database version from the master if these fields
    # are not specified.
    # TODO(b/64266672): Remove once API does not require these fields.
    if args.IsSpecified('master_instance_name'):
        master_instance_ref = client.resource_parser.Parse(
            args.master_instance_name,
            params={'project': properties.VALUES.core.project.GetOrFail},
            collection='sql.instances')
        try:
            master_instance_resource = sql_client.instances.Get(
                sql_messages.SqlInstancesGetRequest(
                    project=instance_ref.project,
                    instance=master_instance_ref.instance))
        except apitools_exceptions.HttpError as error:
            # TODO(b/64292220): Remove once API gives helpful error message.
            log.debug('operation : %s', six.text_type(master_instance_ref))
            exc = exceptions.HttpException(error)
            if resource_property.Get(
                    exc.payload.content,
                    resource_lex.ParseKey('error.errors[0].reason'),
                    None) == 'notAuthorized':
                msg = (
                    'You are either not authorized to access the master instance or '
                    'it does not exist.')
                raise exceptions.HttpException(msg)
            raise
        if not args.IsSpecified('region'):
            args.region = master_instance_resource.region
        if not args.IsSpecified('database_version'):
            args.database_version = master_instance_resource.databaseVersion.name
        if not args.IsSpecified('tier') and not (
                args.IsSpecified('cpu') or args.IsSpecified('memory')
        ) and master_instance_resource.settings:
            args.tier = master_instance_resource.settings.tier

        # Validate master/replica CMEK configurations.
        if master_instance_resource.diskEncryptionConfiguration:
            if args.region == master_instance_resource.region:
                # Warn user that same-region replicas inherit their master's CMEK
                # configuration.
                command_util.ShowCmekWarning('replica', 'the master instance')
            elif not args.IsSpecified('disk_encryption_key'):
                # Raise error that cross-region replicas require their own CMEK key if
                # the master is CMEK.
                raise exceptions.RequiredArgumentException(
                    '--disk-encryption-key',
                    '`--disk-encryption-key` is required when creating a cross-region '
                    'replica of an instance with customer-managed encryption.')
            else:
                command_util.ShowCmekWarning('replica')
        elif args.IsSpecified('disk_encryption_key'):
            # Raise error that cross-region replicas cannot be CMEK encrypted if their
            # master is not.
            raise sql_exceptions.ArgumentError(
                '`--disk-encryption-key` cannot be specified when creating a replica '
                'of an instance without customer-managed encryption.')

    # --root-password is required when creating SQL Server instances
    if args.IsSpecified(
            'database_version') and args.database_version.startswith(
                'SQLSERVER') and not args.IsSpecified('root_password'):
        raise exceptions.RequiredArgumentException(
            '--root-password',
            '`--root-password` is required when creating SQL Server instances.'
        )

    if not args.backup:
        if args.IsSpecified('enable_bin_log'):
            raise sql_exceptions.ArgumentError(
                '`--enable-bin-log` cannot be specified when --no-backup is '
                'specified')
        elif args.IsSpecified('enable_point_in_time_recovery'):
            raise sql_exceptions.ArgumentError(
                '`--enable-point-in-time-recovery` cannot be specified when '
                '--no-backup is specified')

    instance_resource = (
        command_util.InstancesV1Beta4.ConstructCreateInstanceFromArgs(
            sql_messages,
            args,
            instance_ref=instance_ref,
            release_track=release_track))

    # TODO(b/122660263): Remove when V1 instances are no longer supported.
    # V1 instances are deprecated.
    # Note that the exception type is intentionally vague because the user may not
    # have directly supplied the offending argument.  For example, creating a read
    # replica defaults its tier to that of its master.
    if api_util.IsInstanceV1(sql_messages, instance_resource):
        raise sql_exceptions.ArgumentError(
            'First Generation instances can no longer be created.')

    operation_ref = None
    try:
        result_operation = sql_client.instances.Insert(instance_resource)

        operation_ref = client.resource_parser.Create(
            'sql.operations',
            operation=result_operation.name,
            project=instance_ref.project)

        if args.async_:
            if not args.IsSpecified('format'):
                args.format = 'default'
            return sql_client.operations.Get(
                sql_messages.SqlOperationsGetRequest(
                    project=operation_ref.project,
                    operation=operation_ref.operation))

        operations.OperationsV1Beta4.WaitForOperation(
            sql_client,
            operation_ref,
            'Creating Cloud SQL instance',
            # TODO(b/138403566): Remove the override once we improve creation times.
            max_wait_seconds=680)

        log.CreatedResource(instance_ref)

        new_resource = sql_client.instances.Get(
            sql_messages.SqlInstancesGetRequest(
                project=instance_ref.project, instance=instance_ref.instance))
        return new_resource
    except apitools_exceptions.HttpError as error:
        log.debug('operation : %s', six.text_type(operation_ref))
        exc = exceptions.HttpException(error)
        if resource_property.Get(
                exc.payload.content,
                resource_lex.ParseKey('error.errors[0].reason'),
                None) == 'errorMaxInstancePerLabel':
            msg = resource_property.Get(exc.payload.content,
                                        resource_lex.ParseKey('error.message'),
                                        None)
            raise exceptions.HttpException(msg)
        raise
Пример #9
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:
      Cluster message for the successfully created cluster.

    Raises:
      util.Error, if creation failed.
    """
    util.CheckKubectlInstalled()

    adapter = self.context['api_adapter']

    if not args.scopes:
      args.scopes = []
    cluster_ref = adapter.ParseCluster(args.name)
    options = self.ParseCreateOptions(args)

    if options.enable_kubernetes_alpha:
      console_io.PromptContinue(message=constants.KUBERNETES_ALPHA_PROMPT,
                                throw_if_unattended=True,
                                cancel_on_no=True)

    if options.enable_autorepair is not None:
      log.status.Print(messages.AutoUpdateUpgradeRepairMessage(
          options.enable_autorepair, 'autorepair'))

    if options.enable_autoupgrade is not None:
      log.status.Print(messages.AutoUpdateUpgradeRepairMessage(
          options.enable_autoupgrade, 'autoupgrade'))

    operation = None
    try:
      operation_ref = adapter.CreateCluster(cluster_ref, options)
      if args.async:
        return adapter.GetCluster(cluster_ref)

      operation = adapter.WaitForOperation(
          operation_ref,
          'Creating cluster {0}'.format(cluster_ref.clusterId),
          timeout_s=args.timeout)
      cluster = adapter.GetCluster(cluster_ref)
    except apitools_exceptions.HttpError as error:
      raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

    log.CreatedResource(cluster_ref)
    if operation.detail:
      # Non-empty detail on a DONE create operation should be surfaced as
      # a warning to end user.
      log.warning(operation.detail)

    try:
      util.ClusterConfig.Persist(cluster, cluster_ref.projectId)
    except kconfig.MissingEnvVarError as error:
      log.warning(error.message)

    return cluster
Пример #10
0
 def CatchHTTPErrorRaiseHTTPException(*args, **kwargs):
   try:
     for result in func(*args, **kwargs):
       yield result
   except apitools_exceptions.HttpError as error:
     raise exceptions.HttpException(GetError(error))
Пример #11
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_ref = adapter.ParseCluster(args.name)
    # Make sure it exists (will raise appropriate error if not)
    adapter.GetCluster(cluster_ref)

    # locations will be None if additional-zones was specified, an empty list
    # if it was specified with no argument, or a populated list if zones were
    # provided. We want to distinguish between the case where it isn't
    # specified (and thus shouldn't be passed on to the API) and the case where
    # it's specified as wanting no additional zones, in which case we must pass
    # the cluster's primary zone to the API.
    # TODO(b/29578401): Remove the hasattr once the flag is GA.
    locations = None
    if hasattr(args, 'additional_zones') and args.additional_zones is not None:
      locations = sorted([cluster_ref.zone] + args.additional_zones)

    if args.generate_password or args.set_password:
      if args.generate_password:
        password = ''
        options = api_adapter.SetMasterAuthOptions(
            action=api_adapter.SetMasterAuthOptions.GENERATE_PASSWORD,
            password=password)
      else:
        password = raw_input('Please enter the new password:'******'Updating {0}'.format(cluster_ref.clusterId))

      log.UpdatedResource(cluster_ref)
Пример #12
0
 def CatchHTTPErrorRaiseHTTPException(*args, **kwargs):
   try:
     return func(*args, **kwargs)
   except apitools_exceptions.HttpError as error:
     raise exceptions.HttpException(GetError(error))
Пример #13
0
  def Run(self, args):
    """Creates a new Cloud SQL instance.

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

    Returns:
      A dict object representing the operations resource describing the create
      operation if the create was successful.
    Raises:
      HttpException: A http error response was received while executing api
          request.
      ToolException: An error other than http error occured while executing the
          command.
    """

    sql_client = self.context['sql_client']
    sql_messages = self.context['sql_messages']
    resources = self.context['registry']

    validate.ValidateInstanceName(args.instance)
    instance_ref = resources.Parse(args.instance, collection='sql.instances')
    instance_resource = instances.InstancesV1Beta4.ConstructInstanceFromArgs(
        sql_messages, args, instance_ref=instance_ref)

    if args.pricing_plan == 'PACKAGE':
      if not console_io.PromptContinue(
          'Charges will begin accruing immediately. Really create Cloud '
          'SQL instance?'):
        raise exceptions.ToolException('canceled by the user.')

    operation_ref = None
    try:
      result_operation = sql_client.instances.Insert(instance_resource)

      operation_ref = resources.Create(
          'sql.operations',
          operation=result_operation.name,
          project=instance_ref.project)

      if args.async:
        return sql_client.operations.Get(
            sql_messages.SqlOperationsGetRequest(
                project=operation_ref.project,
                operation=operation_ref.operation))

      operations.OperationsV1Beta4.WaitForOperation(
          sql_client, operation_ref, 'Creating Cloud SQL instance')

      log.CreatedResource(instance_ref)

      new_resource = sql_client.instances.Get(
          sql_messages.SqlInstancesGetRequest(
              project=instance_ref.project,
              instance=instance_ref.instance))
      cache = remote_completion.RemoteCompletion()
      cache.AddToCache(instance_ref.SelfLink())
      return new_resource
    except apitools_exceptions.HttpError as error:
      log.debug('operation : %s', str(operation_ref))
      exc = exceptions.HttpException(error)
      if resource_property.Get(exc.payload.content,
                               resource_lex.ParseKey('error.errors[0].reason'),
                               None) == 'errorMaxInstancePerLabel':
        msg = resource_property.Get(exc.payload.content,
                                    resource_lex.ParseKey('error.message'),
                                    None)
        raise exceptions.HttpException(msg)
      raise
Пример #14
0
def _WhitelistClientIP(instance_ref,
                       sql_client,
                       sql_messages,
                       resources,
                       minutes=5):
    """Add CLIENT_IP to the authorized networks list.

  Makes an API call to add CLIENT_IP to the authorized networks list.
  The server knows to interpret the string CLIENT_IP as the address with which
  the client reaches the server. This IP will be whitelisted for 1 minute.

  Args:
    instance_ref: resources.Resource, The instance we're connecting to.
    sql_client: apitools.BaseApiClient, A working client for the sql version
        to be used.
    sql_messages: module, The module that defines the messages for the sql
        version to be used.
    resources: resources.Registry, The registry that can create resource refs
        for the sql version to be used.
    minutes: How long the client IP will be whitelisted for, in minutes.

  Returns:
    string, The name of the authorized network rule. Callers can use this name
    to find out the IP the client reached the server with.
  Raises:
    HttpException: An http error response was received while executing api
        request.
    ResourceNotFoundError: The SQL instance was not found.
  """
    time_of_connection = network.GetCurrentTime()

    acl_name = 'sql connect at time {0}'.format(time_of_connection)
    user_acl = sql_messages.AclEntry(
        name=acl_name,
        expirationTime=iso_duration.Duration(
            minutes=minutes).GetRelativeDateTime(time_of_connection),
        value='CLIENT_IP')

    try:
        original = sql_client.instances.Get(
            sql_messages.SqlInstancesGetRequest(
                project=instance_ref.project, instance=instance_ref.instance))
    except apitools_exceptions.HttpError as error:
        if error.status_code == httplib.FORBIDDEN:
            raise exceptions.ResourceNotFoundError(
                'There was no instance found at {} or you are not authorized to '
                'connect to it.'.format(instance_ref.RelativeName()))
        raise calliope_exceptions.HttpException(error)

    original.settings.ipConfiguration.authorizedNetworks.append(user_acl)
    try:
        patch_request = sql_messages.SqlInstancesPatchRequest(
            databaseInstance=original,
            project=instance_ref.project,
            instance=instance_ref.instance)
        result = sql_client.instances.Patch(patch_request)
    except apitools_exceptions.HttpError as error:
        raise calliope_exceptions.HttpException(error)

    operation_ref = resources.Create('sql.operations',
                                     operation=result.name,
                                     project=instance_ref.project)
    message = ('Whitelisting your IP for incoming connection for '
               '{0} {1}'.format(minutes, text.Pluralize(minutes, 'minute')))

    operations.OperationsV1Beta4.WaitForOperation(sql_client, operation_ref,
                                                  message)

    return acl_name
  def Run(self, args):
    """Run 'deployments update'.

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

    Returns:
      If --async=true, returns Operation to poll.
      Else, returns a struct containing the list of resources and list of
        outputs in the deployment.

    Raises:
      HttpException: An http error response was received while executing api
          request.
    """
    deployment_ref = self.resources.Parse(
        args.deployment_name,
        params={'project': properties.VALUES.core.project.GetOrFail},
        collection='deploymentmanager.deployments')
    if not args.IsSpecified('format') and args.async:
      args.format = flags.OPERATION_FORMAT

    patch_request = False
    deployment = self.messages.Deployment(
        name=deployment_ref.deployment,
    )

    if not (args.config is None and args.template is None
            and args.composite_type is None):
      deployment.target = importer.BuildTargetConfig(
          self.messages,
          config=args.config,
          template=args.template,
          composite_type=args.composite_type,
          properties=args.properties)
    elif (self.ReleaseTrack() in [base.ReleaseTrack.ALPHA,
                                  base.ReleaseTrack.BETA]
          and args.manifest_id):
      deployment.target = importer.BuildTargetConfigFromManifest(
          self.client, self.messages,
          dm_base.GetProject(),
          deployment_ref.deployment, args.manifest_id, args.properties)
    # Get the fingerprint from the deployment to update.
    try:
      current_deployment = self.client.deployments.Get(
          self.messages.DeploymentmanagerDeploymentsGetRequest(
              project=dm_base.GetProject(),
              deployment=deployment_ref.deployment
          )
      )

      if args.fingerprint:
        deployment.fingerprint = dm_util.DecodeFingerprint(args.fingerprint)
      else:
        # If no fingerprint is present, default to an empty fingerprint.
        # TODO(b/34966984): Remove the empty default after cleaning up all
        # deployments that has no fingerprint
        deployment.fingerprint = current_deployment.fingerprint or ''

      # Get the credential from the deployment to update.
      if self.ReleaseTrack() in [base.ReleaseTrack.ALPHA] and args.credential:
        deployment.credential = dm_util.CredentialFrom(self.messages,
                                                       args.credential)

      # Update the labels of the deployment

      deployment.labels = self._GetUpdatedDeploymentLabels(
          args, current_deployment)
      # If no config or manifest_id are specified, but try to update labels,
      # only add patch_request header when directly updating a non-previewed
      # deployment

      no_manifest = (self.ReleaseTrack() is
                     base.ReleaseTrack.GA) or not args.manifest_id
      patch_request = not args.config and no_manifest and (
          bool(args.update_labels) or bool(args.remove_labels))
      if args.description is None:
        deployment.description = current_deployment.description
      elif not args.description or args.description.isspace():
        deployment.description = None
      else:
        deployment.description = args.description
    except apitools_exceptions.HttpError as error:
      raise exceptions.HttpException(error, dm_api_util.HTTP_ERROR_FORMAT)

    if patch_request:
      args.format = flags.DEPLOYMENT_FORMAT
    try:
      # Necessary to handle API Version abstraction below
      parsed_delete_flag = Update._delete_policy_flag_map.GetEnumForChoice(
          args.delete_policy).name
      parsed_create_flag = Update._create_policy_flag_map.GetEnumForChoice(
          args.create_policy).name
      request = self.messages.DeploymentmanagerDeploymentsUpdateRequest(
          deploymentResource=deployment,
          project=dm_base.GetProject(),
          deployment=deployment_ref.deployment,
          preview=args.preview,
          createPolicy=(self.messages.DeploymentmanagerDeploymentsUpdateRequest.
                        CreatePolicyValueValuesEnum(parsed_create_flag)),
          deletePolicy=(self.messages.DeploymentmanagerDeploymentsUpdateRequest.
                        DeletePolicyValueValuesEnum(parsed_delete_flag)))
      client = self.client
      client.additional_http_headers['X-Cloud-DM-Patch'] = patch_request
      operation = client.deployments.Update(request)

      # Fetch and print the latest fingerprint of the deployment.
      updated_deployment = dm_api_util.FetchDeployment(
          self.client, self.messages, dm_base.GetProject(),
          deployment_ref.deployment)
      if patch_request:
        if args.async:
          log.warn('Updating Deployment metadata is synchronous, --async flag '
                   'is ignored.')
        log.status.Print('Update deployment metadata completed successfully.')
        return updated_deployment
      dm_util.PrintFingerprint(updated_deployment.fingerprint)
    except apitools_exceptions.HttpError as error:
      raise exceptions.HttpException(error, dm_api_util.HTTP_ERROR_FORMAT)
    if args.async:
      return operation
    else:
      op_name = operation.name
      try:
        dm_write.WaitForOperation(self.client,
                                  self.messages,
                                  op_name,
                                  'update',
                                  dm_base.GetProject(),
                                  timeout=OPERATION_TIMEOUT)
        log.status.Print('Update operation ' + op_name
                         + ' completed successfully.')
      except apitools_exceptions.HttpError as error:
        raise exceptions.HttpException(error, dm_api_util.HTTP_ERROR_FORMAT)

      return dm_api_util.FetchResourcesAndOutputs(
          self.client, self.messages, dm_base.GetProject(),
          deployment_ref.deployment,
          self.ReleaseTrack() is base.ReleaseTrack.ALPHA)
Пример #16
0
 def CatchHTTPErrorRaiseHTTPExceptionFn(*args, **kwargs):
   try:
     return func(*args, **kwargs)
   except apitools_exceptions.HttpError as error:
     core_exceptions.reraise(
         base_exceptions.HttpException(GetHttpErrorMessage(error)))
Пример #17
0
    def Run(self, args):
        """Run 'deployments create'.

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

    Returns:
      If --async=true, returns Operation to poll.
      Else, returns a struct containing the list of resources and list of
        outputs in the deployment.

    Raises:
      HttpException: An http error response was received while executing api
          request.
      ConfigError: Config file could not be read or parsed, or the
          deployment creation operation encountered an error.
    """
        if ((not args.IsSpecified('format')) and
            (args. async or getattr(args, 'automatic_rollback', False))):
            args.format = flags.OPERATION_FORMAT

        deployment = self.messages.Deployment(
            name=args.
            deployment_name,  # TODO(b/37913150): Use resource parser.
            target=importer.BuildTargetConfig(self.messages, args.config,
                                              args.properties),
        )

        self._SetMetadata(args, deployment)

        try:
            operation = self.client.deployments.Insert(
                self.messages.DeploymentmanagerDeploymentsInsertRequest(
                    project=dm_base.GetProject(),
                    deployment=deployment,
                    preview=args.preview,
                ))

            # Fetch and print the latest fingerprint of the deployment.
            fingerprint = dm_api_util.FetchDeploymentFingerprint(
                self.client, self.messages, dm_base.GetProject(),
                args.deployment_name)
            dm_util.PrintFingerprint(fingerprint)

        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(error,
                                           dm_api_util.HTTP_ERROR_FORMAT)
        if args. async:
            return operation
        else:
            op_name = operation.name
            try:
                dm_write.WaitForOperation(self.client,
                                          self.messages,
                                          op_name,
                                          operation_description='create',
                                          project=dm_base.GetProject(),
                                          timeout=OPERATION_TIMEOUT)
                log.status.Print('Create operation ' + op_name +
                                 ' completed successfully.')
            except apitools_exceptions.HttpError as error:
                # TODO(b/37911296): Use gcloud default error handling.
                raise exceptions.HttpException(error,
                                               dm_api_util.HTTP_ERROR_FORMAT)
            except dm_exceptions.OperationError as error:
                response = self._HandleOperationError(error, args, operation,
                                                      dm_base.GetProject())
                return response

            return dm_api_util.FetchResourcesAndOutputs(
                self.client, self.messages, dm_base.GetProject(),
                args.deployment_name)
Пример #18
0
  def Run(self, args):
    api_version = 'v1'
    # If in the future there are differences between API version, do NOT use
    # this patter of checking ReleaseTrack. Break this into multiple classes.
    if self.ReleaseTrack() == base.ReleaseTrack.BETA:
      api_version = 'v1beta2'
    elif self.ReleaseTrack() == base.ReleaseTrack.ALPHA:
      api_version = 'v1alpha2'

    if not os.path.exists(args.records_file):
      raise import_util.RecordsFileNotFound(
          'Specified record file [{0}] not found.'.format(args.records_file))
    if os.path.isdir(args.records_file):
      raise import_util.RecordsFileIsADirectory(
          'Specified record file [{0}] is a directory'.format(
              args.records_file))

    dns = util.GetApiClient(api_version)

    # Get the managed-zone.
    zone_ref = util.GetRegistry(api_version).Parse(
        args.zone,
        params={
            'project': properties.VALUES.core.project.GetOrFail,
        },
        collection='dns.managedZones')

    try:
      zone = dns.managedZones.Get(
          dns.MESSAGES_MODULE.DnsManagedZonesGetRequest(
              project=zone_ref.project,
              managedZone=zone_ref.managedZone))
    except apitools_exceptions.HttpError as error:
      raise calliope_exceptions.HttpException(error)

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

    # Get the imported record-sets.
    try:
      with files.FileReader(args.records_file) as import_file:
        if args.zone_file_format:
          imported = import_util.RecordSetsFromZoneFile(
              import_file, zone.dnsName, api_version=api_version)
        else:
          imported = import_util.RecordSetsFromYamlFile(
              import_file, api_version=api_version)
    except Exception as exp:
      msg = ('Unable to read record-sets from specified records-file [{0}] '
             'because [{1}]')
      msg = msg.format(args.records_file, exp.message)
      raise import_util.UnableToReadRecordsFile(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,
                                       api_version=api_version)
    if not change:
      msg = '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(
        dns.MESSAGES_MODULE.DnsChangesCreateRequest(
            change=change,
            managedZone=zone.name,
            project=zone_ref.project))
    change_ref = util.GetRegistry(api_version).Create(
        collection='dns.changes',
        project=zone_ref.project,
        managedZone=zone.name,
        changeId=result.id)
    msg = '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
Пример #19
0
 def Func(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except api_ex.HttpError as e:
         raise sdk_ex.HttpException(
             json.loads(e.content)['error']['message'])
Пример #20
0
    def Run(self, args):
        """Run 'deployments create'.

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

    Returns:
      If --async=true, returns Operation to poll.
      Else, returns a struct containing the list of resources and list of
        outputs in the deployment.

    Raises:
      HttpException: An http error response was received while executing api
          request.
      ConfigError: Config file could not be read or parsed, or the
          deployment creation operation encountered an error.
    """
        deployment_ref = self.resources.Parse(
            args.deployment_name,
            params={'project': properties.VALUES.core.project.GetOrFail},
            collection='deploymentmanager.deployments')
        if (not args.IsSpecified('format')) and (args. async):
            args.format = flags.OPERATION_FORMAT

        deployment = self.messages.Deployment(
            name=deployment_ref.deployment,
            target=importer.BuildTargetConfig(
                self.messages,
                config=args.config,
                template=args.template,
                composite_type=args.composite_type,
                properties=args.properties))

        self._SetMetadata(args, deployment)

        try:
            operation = self.client.deployments.Insert(
                self._BuildRequest(args=args,
                                   project=dm_base.GetProject(),
                                   deployment=deployment))

            # Fetch and print the latest fingerprint of the deployment.
            fingerprint = dm_api_util.FetchDeploymentFingerprint(
                self.client, self.messages, dm_base.GetProject(),
                deployment_ref.deployment)
            dm_util.PrintFingerprint(fingerprint)

        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(error,
                                           dm_api_util.HTTP_ERROR_FORMAT)
        if args. async:
            return operation
        else:
            op_name = operation.name
            try:
                operation = dm_write.WaitForOperation(
                    self.client,
                    self.messages,
                    op_name,
                    operation_description='create',
                    project=dm_base.GetProject(),
                    timeout=OPERATION_TIMEOUT)
                dm_util.LogOperationStatus(operation, 'Create')
            except apitools_exceptions.HttpError as error:
                # TODO(b/37911296): Use gcloud default error handling.
                raise exceptions.HttpException(error,
                                               dm_api_util.HTTP_ERROR_FORMAT)
            except dm_exceptions.OperationError as error:
                response = self._HandleOperationError(error, args, operation,
                                                      dm_base.GetProject(),
                                                      deployment_ref)
                if getattr(args, 'automatic_rollback', False):
                    args.format = flags.OPERATION_FORMAT
                return response

            return dm_api_util.FetchResourcesAndOutputs(
                self.client, self.messages, dm_base.GetProject(),
                deployment_ref.deployment,
                self.ReleaseTrack() is base.ReleaseTrack.ALPHA)
Пример #21
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']
        location_get = self.context['location_get']
        location = location_get(args)
        cluster_ref = adapter.ParseCluster(args.name, location)
        # Make sure it exists (will raise appropriate error if not)
        cluster = adapter.GetCluster(cluster_ref)

        # locations will be None if additional-zones was specified, an empty list
        # if it was specified with no argument, or a populated list if zones were
        # provided. We want to distinguish between the case where it isn't
        # specified (and thus shouldn't be passed on to the API) and the case where
        # it's specified as wanting no additional zones, in which case we must pass
        # the cluster's primary zone to the API.
        # TODO(b/29578401): Remove the hasattr once the flag is GA.
        locations = None
        if hasattr(args,
                   'additional_zones') and args.additional_zones is not None:
            locations = sorted([cluster_ref.zone] + args.additional_zones)
        if hasattr(args, 'node_locations') and args.node_locations is not None:
            locations = sorted(args.node_locations)

        if args.username is not None or args.enable_basic_auth is not None:
            flags.MungeBasicAuthFlags(args)
            options = api_adapter.SetMasterAuthOptions(
                action=api_adapter.SetMasterAuthOptions.SET_USERNAME,
                username=args.username,
                password=args.password)

            try:
                op_ref = adapter.SetMasterAuth(cluster_ref, options)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif (args.generate_password or args.set_password
              or args.password is not None):
            if args.generate_password:
                password = ''
                options = api_adapter.SetMasterAuthOptions(
                    action=api_adapter.SetMasterAuthOptions.GENERATE_PASSWORD,
                    password=password)
            else:
                password = args.password
                if args.password is None:
                    password = raw_input('Please enter the new password:'******'Enabling/Disabling Network Policy causes a rolling '
                'update of all cluster nodes, similar to performing a cluster '
                'upgrade.  This operation is long-running and will block other '
                'operations on the cluster (including delete) until it has run '
                'to completion.',
                cancel_on_no=True)
            options = api_adapter.SetNetworkPolicyOptions(
                enabled=args.enable_network_policy)
            try:
                op_ref = adapter.SetNetworkPolicy(cluster_ref, options)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.start_ip_rotation:
            console_io.PromptContinue(
                message=
                'This will start an IP Rotation on cluster [{name}]. The '
                'master will be updated to serve on a new IP address in addition to '
                'the current IP address. Kubernetes Engine will then recreate all '
                'nodes ({num_nodes} nodes) to point to the new IP address. This '
                'operation is long-running and will block other operations on the '
                'cluster (including delete) until it has run to completion.'.
                format(name=cluster.name, num_nodes=cluster.currentNodeCount),
                cancel_on_no=True)
            try:
                op_ref = adapter.StartIpRotation(cluster_ref)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.complete_ip_rotation:
            console_io.PromptContinue(
                message=
                'This will complete the in-progress IP Rotation on cluster '
                '[{name}]. The master will be updated to stop serving on the old IP '
                'address and only serve on the new IP address. Make sure all API '
                'clients have been updated to communicate with the new IP address '
                '(e.g. by running `gcloud container clusters get-credentials '
                '--project {project} --zone {zone} {name}`). This operation is long-'
                'running and will block other operations on the cluster (including '
                'delete) until it has run to completion.'.format(
                    name=cluster.name,
                    project=cluster_ref.projectId,
                    zone=cluster.zone),
                cancel_on_no=True)
            try:
                op_ref = adapter.CompleteIpRotation(cluster_ref)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.update_labels is not None:
            try:
                op_ref = adapter.UpdateLabels(cluster_ref, args.update_labels)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.remove_labels is not None:
            try:
                op_ref = adapter.RemoveLabels(cluster_ref, args.remove_labels)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.logging_service is not None:
            try:
                op_ref = adapter.SetLoggingService(cluster_ref,
                                                   args.logging_service)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.maintenance_window is not None:
            try:
                op_ref = adapter.SetMaintenanceWindow(cluster_ref,
                                                      args.maintenance_window)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        else:
            if args.enable_legacy_authorization is not None:
                op_ref = adapter.SetLegacyAuthorization(
                    cluster_ref, args.enable_legacy_authorization)
            else:
                options = self.ParseUpdateOptions(args, locations)
                op_ref = adapter.UpdateCluster(cluster_ref, options)

        if not args. async:
            adapter.WaitForOperation(
                op_ref, 'Updating {0}'.format(cluster_ref.clusterId))

            log.UpdatedResource(cluster_ref)
            cluster_url = util.GenerateClusterUrl(cluster_ref)
            log.status.Print(
                'To inspect the contents of your cluster, go to: ' +
                cluster_url)

            if args.start_ip_rotation or args.complete_ip_rotation:
                cluster = adapter.GetCluster(cluster_ref)
                try:
                    util.ClusterConfig.Persist(cluster, cluster_ref.projectId)
                except kconfig.MissingEnvVarError as error:
                    log.warning(error.message)
Пример #22
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']
    location_get = self.context['location_get']
    location = location_get(args)
    cluster_refs = []
    for name in args.names:
      cluster_refs.append(adapter.ParseCluster(name, location))
    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,
        cancel_on_no=True)

    operations = []
    errors = []
    # Issue all deletes first
    for cluster_ref in cluster_refs:
      try:
        op_ref = adapter.DeleteCluster(cluster_ref)
        operations.append((op_ref, cluster_ref))
      except apitools_exceptions.HttpError as error:
        errors.append(
            six.text_type(
                exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)))
      except util.Error as error:
        errors.append(error)
    if not args.async:
      # 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
          try:
            util.ClusterConfig.Purge(cluster_ref.clusterId,
                                     adapter.Zone(cluster_ref),
                                     cluster_ref.projectId)
          except kconfig.MissingEnvVarError as error:
            log.warning(error)

          if properties.VALUES.container.cluster.Get() == cluster_ref.clusterId:
            properties.PersistProperty(properties.VALUES.container.cluster,
                                       None)
          log.DeletedResource(cluster_ref)
        except apitools_exceptions.HttpError as error:
          errors.append(exceptions.HttpException(error, util.HTTP_ERROR_FORMAT))
        except util.Error as error:
          errors.append(error)

    if errors:
      raise util.Error(
          util.ConstructList('Some requests did not succeed:', errors))
Пример #23
0
    def Run(self, args):
        if not os.path.isfile(args.records_file):
            raise exceptions.ToolException('no such file [{0}]'.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.HttpError as error:
            raise exceptions.HttpException(util.GetErrorMessage(error))

        # Get the current record-sets.
        current = {}
        for record in apitools.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 = (
                'unable to read record-sets from specified records-file [{0}] '
                '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)
        if not change:
            msg = '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 = '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
Пример #24
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']
    location_get = self.context['location_get']
    location = location_get(args)
    cluster_ref = adapter.ParseCluster(args.name, location)
    project_id = properties.VALUES.core.project.Get(required=True)
    concurrent_node_count = getattr(args, 'concurrent_node_count', None)

    try:
      cluster = adapter.GetCluster(cluster_ref)
    except (exceptions.HttpException,
            apitools_exceptions.HttpForbiddenError,
            util.Error) as error:
      log.warning(('Problem loading details of cluster to upgrade:\n\n{}\n\n'
                   'You can still attempt to upgrade the cluster.\n')
                  .format(console_attr.SafeText(error)))
      cluster = None

    try:
      server_conf = adapter.GetServerConfig(project_id, location)
    except (exceptions.HttpException,
            apitools_exceptions.HttpForbiddenError,
            util.Error) as error:
      log.warning(('Problem loading server config:\n\n{}\n\n'
                   'You can still attempt to upgrade the cluster.\n')
                  .format(console_attr.SafeText(error)))
      server_conf = None

    upgrade_message = container_command_util.ClusterUpgradeMessage(
        name=args.name,
        server_conf=server_conf,
        cluster=cluster,
        master=args.master,
        node_pool_name=args.node_pool,
        new_version=args.cluster_version,
        concurrent_node_count=concurrent_node_count)

    console_io.PromptContinue(
        message=upgrade_message,
        throw_if_unattended=True,
        cancel_on_no=True)

    options = self.ParseUpgradeOptions(args)

    try:
      op_ref = adapter.UpdateCluster(cluster_ref, options)
    except apitools_exceptions.HttpError as error:
      raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

    if not args.async:
      adapter.WaitForOperation(
          op_ref, 'Upgrading {0}'.format(cluster_ref.clusterId),
          timeout_s=args.timeout)

      log.UpdatedResource(cluster_ref)
Пример #25
0
    def Run(self, args):
        """Run 'deployments cancel'.

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

    Returns:
      If --async=true, returns Operation to poll.
      Else, returns boolean indicating whether cancel operation succeeded.

    Raises:
      HttpException: An http error response was received while executing api
          request.
      ToolException: The cancel operation encountered an error.
    """
        client = self.context['deploymentmanager-v2beta2']
        messages = self.context['deploymentmanager-v2beta2-messages']
        project = properties.VALUES.core.project.Get(required=True)

        deployment = messages.Deployment(
            name=args.deployment_name,
            intent='CANCEL',
        )

        # Get the fingerprint from the deployment to update.
        try:
            current_deployment = client.deployments.Get(
                messages.DeploymentmanagerDeploymentsGetRequest(
                    project=project, deployment=args.deployment_name))
            # If no fingerprint is present, default to an empty fingerprint.
            # This empty default can be removed once the fingerprint change is
            # fully implemented and all deployments have fingerprints.
            deployment.fingerprint = current_deployment.fingerprint or ''
        except apitools_base.HttpError as error:
            raise exceptions.HttpException(dm_v2_util.GetError(error))

        try:
            operation = client.deployments.Update(
                messages.DeploymentmanagerDeploymentsUpdateRequest(
                    deploymentResource=deployment,
                    project=project,
                    deployment=args.deployment_name,
                ))
        except apitools_base.HttpError as error:
            raise exceptions.HttpException(dm_v2_util.GetError(error))
        if args. async:
            return operation
        else:
            op_name = operation.name
            try:
                dm_v2_util.WaitForOperation(op_name, project, self.context,
                                            'cancel', OPERATION_TIMEOUT)
                log.status.Print('Cancel operation ' + op_name +
                                 ' completed successfully.')
            except exceptions.ToolException:
                # Operation timed out or had errors. Print this warning, then still
                # show whatever operation can be gotten.
                log.error('Cancel operation ' + op_name +
                          ' has errors or failed to complete within ' +
                          str(OPERATION_TIMEOUT) + ' seconds.')
            except apitools_base.HttpError as error:
                raise exceptions.HttpException(dm_v2_util.GetError(error))
            try:
                # Fetch a list of the canceled resources.
                response = client.resources.List(
                    messages.DeploymentmanagerResourcesListRequest(
                        project=project,
                        deployment=args.deployment_name,
                    ))
                # TODO(user): Pagination
                return response.resources if response.resources else []
            except apitools_base.HttpError as error:
                raise exceptions.HttpException(dm_v2_util.GetError(error))
Пример #26
0
class Create(base.CreateCommand):
    """Create a cluster for running containers."""
    @staticmethod
    def Args(parser):
        _Args(parser)
        flags.AddClusterAutoscalingFlags(parser, suppressed=True)
        flags.AddLocalSSDFlag(parser, suppressed=True)
        flags.AddEnableKubernetesAlphaFlag(parser, suppressed=True)
        flags.AddClusterVersionFlag(parser, 'master and nodes', True)
        flags.AddPreemptibleFlag(parser, suppressed=True)
        flags.AddEnableAutoRepairFlag(parser, suppressed=True)
        flags.AddEnableAutoUpgradeFlag(parser, suppressed=True)

    def ParseCreateOptions(self, args):
        if not args.scopes:
            args.scopes = []
        cluster_ipv4_cidr = args.cluster_ipv4_cidr
        return api_adapter.CreateClusterOptions(
            node_machine_type=args.machine_type,
            scopes=args.scopes,
            enable_cloud_endpoints=args.enable_cloud_endpoints,
            num_nodes=args.num_nodes,
            additional_zones=args.additional_zones,
            user=args.username,
            password=args.password,
            cluster_version=args.cluster_version,
            network=args.network,
            subnetwork=args.subnetwork,
            cluster_ipv4_cidr=cluster_ipv4_cidr,
            node_disk_size_gb=args.disk_size,
            enable_cloud_logging=args.enable_cloud_logging,
            enable_cloud_monitoring=args.enable_cloud_monitoring,
            enable_kubernetes_alpha=args.enable_kubernetes_alpha,
            disable_addons=args.disable_addons,
            local_ssd_count=args.local_ssd_count,
            tags=args.tags,
            node_labels=args.node_labels,
            enable_autoscaling=args.enable_autoscaling,
            max_nodes=args.max_nodes,
            min_nodes=args.min_nodes,
            image_type=args.image_type,
            max_nodes_per_pool=args.max_nodes_per_pool,
            preemptible=args.preemptible,
            enable_autorepair=args.enable_autorepair,
            enable_autoupgrade=args.enable_autoupgrade)

    def Collection(self):
        return 'container.projects.zones.clusters'

    def Format(self, args):
        return self.ListFormat(args)

    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:
      Cluster message for the successfully created cluster.

    Raises:
      util.Error, if creation failed.
    """
        util.CheckKubectlInstalled()

        adapter = self.context['api_adapter']

        if not args.scopes:
            args.scopes = []
        cluster_ref = adapter.ParseCluster(args.name)
        options = self.ParseCreateOptions(args)

        if options.enable_kubernetes_alpha:
            console_io.PromptContinue(
                message=constants.KUBERNETES_ALPHA_PROMPT,
                throw_if_unattended=True,
                cancel_on_no=True)

        if options.enable_autorepair is not None:
            log.status.Print(
                messages.AutoUpdateUpgradeRepairMessage(
                    options.enable_autorepair, 'autorepair'))

        if options.enable_autoupgrade is not None:
            log.status.Print(
                messages.AutoUpdateUpgradeRepairMessage(
                    options.enable_autoupgrade, 'autoupgrade'))

        operation = None
        try:
            operation_ref = adapter.CreateCluster(cluster_ref, options)
            if flags.GetAsyncValueFromAsyncAndWaitFlags(
                    args. async, args.wait):
                return adapter.GetCluster(cluster_ref)

            operation = adapter.WaitForOperation(operation_ref,
                                                 'Creating cluster {0}'.format(
                                                     cluster_ref.clusterId),
                                                 timeout_s=args.timeout)
            cluster = adapter.GetCluster(cluster_ref)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
Пример #27
0
class Create(base.CreateCommand):
    """Create a cluster for running containers."""
    @staticmethod
    def Args(parser):
        _Args(parser)
        _AddAdditionalZonesFlag(parser, deprecated=True)
        flags.AddNodeLocationsFlag(parser)
        flags.AddAddonsFlags(parser)
        flags.AddClusterAutoscalingFlags(parser)
        flags.AddEnableAutoRepairFlag(parser, for_create=True)
        flags.AddEnableKubernetesAlphaFlag(parser)
        flags.AddEnableLegacyAuthorizationFlag(parser)
        flags.AddIPAliasFlags(parser)
        flags.AddLabelsFlag(parser)
        flags.AddLocalSSDFlag(parser)
        flags.AddMaintenanceWindowFlag(parser)
        flags.AddMasterAuthorizedNetworksFlags(parser)
        flags.AddMinCpuPlatformFlag(parser)
        flags.AddNetworkPolicyFlags(parser)
        flags.AddNodeTaintsFlag(parser)
        flags.AddPreemptibleFlag(parser)
        flags.AddDeprecatedClusterNodeIdentityFlags(parser)
        flags.AddPrivateClusterFlags(parser, with_deprecated=False)

    def ParseCreateOptions(self, args):
        return ParseCreateOptionsBase(args)

    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:
      Cluster message for the successfully created cluster.

    Raises:
      util.Error, if creation failed.
    """
        if args. async and not args.IsSpecified('format'):
            args.format = util.OPERATIONS_FORMAT

        util.CheckKubectlInstalled()

        adapter = self.context['api_adapter']
        location_get = self.context['location_get']
        location = location_get(args)

        cluster_ref = adapter.ParseCluster(args.name, location)
        options = self.ParseCreateOptions(args)

        if options.private_cluster and not (
                options.enable_master_authorized_networks
                or options.master_authorized_networks):
            log.warning(
                '`--private-cluster` makes the master inaccessible from '
                'cluster-external IP addresses, by design. To allow limited '
                'access to the master, see the `--master-authorized-networks` flags '
                'and our documentation on setting up private clusters: '
                'https://cloud.google.com'
                '/kubernetes-engine/docs/how-to/private-clusters')

        if not (options.metadata
                and 'disable-legacy-endpoints' in options.metadata):
            log.warning(
                'Starting in 1.12, default node pools in new clusters '
                'will have their legacy Compute Engine instance metadata '
                'endpoints disabled by default. To create a cluster with '
                'legacy instance metadata endpoints disabled in the default '
                'node pool, run `clusters create` with the flag '
                '`--metadata disable-legacy-endpoints=true`.')

        if options.enable_kubernetes_alpha:
            console_io.PromptContinue(
                message=constants.KUBERNETES_ALPHA_PROMPT,
                throw_if_unattended=True,
                cancel_on_no=True)

        if options.enable_autorepair is not None:
            log.status.Print(
                messages.AutoUpdateUpgradeRepairMessage(
                    options.enable_autorepair, 'autorepair'))

        if options.enable_autoupgrade is not None:
            log.status.Print(
                messages.AutoUpdateUpgradeRepairMessage(
                    options.enable_autoupgrade, 'autoupgrade'))

        if options.accelerators is not None:
            log.status.Print(constants.KUBERNETES_GPU_LIMITATION_MSG)

        operation = None
        try:
            operation_ref = adapter.CreateCluster(cluster_ref, options)
            if args. async:
                return adapter.GetCluster(cluster_ref)

            operation = adapter.WaitForOperation(
                operation_ref,
                'Creating cluster {0} in {1}'.format(cluster_ref.clusterId,
                                                     cluster_ref.zone),
                timeout_s=args.timeout)
            cluster = adapter.GetCluster(cluster_ref)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

        log.CreatedResource(cluster_ref)
        cluster_url = util.GenerateClusterUrl(cluster_ref)
        log.status.Print('To inspect the contents of your cluster, go to: ' +
                         cluster_url)
        if operation.detail:
            # Non-empty detail on a DONE create operation should be surfaced as
            # a warning to end user.
            log.warning(operation.detail)

        try:
            util.ClusterConfig.Persist(cluster, cluster_ref.projectId)
        except kconfig.MissingEnvVarError as error:
            log.warning(error)

        return [cluster]
Пример #28
0
    def Run(self, args):
        """Run 'deployments create'.

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

    Returns:
      If --async=true, returns Operation to poll.
      Else, returns a struct containing the list of resources and list of
        outputs in the deployment.

    Raises:
      HttpException: An http error response was received while executing api
          request.
      ConfigError: Config file could not be read or parsed, or the
          deployment creation operation encountered an error.
    """
        deployment = dm_base.GetMessages().Deployment(
            name=args.deployment_name,
            target=importer.BuildTargetConfig(dm_base.GetMessages(),
                                              args.config, args.properties),
        )
        if self.ReleaseTrack() in [base.ReleaseTrack.ALPHA]:
            label_dict = labels_util.GetUpdateLabelsDictFromArgs(args)
            label_entry = []
            if label_dict:
                label_entry = [
                    dm_base.GetMessages().DeploymentLabelEntry(key=k, value=v)
                    for k, v in sorted(label_dict.iteritems())
                ]
                deployment.labels = label_entry

        if args.description:
            deployment.description = args.description

        try:
            operation = dm_base.GetClient().deployments.Insert(
                dm_base.GetMessages(
                ).DeploymentmanagerDeploymentsInsertRequest(
                    project=dm_base.GetProject(),
                    deployment=deployment,
                    preview=args.preview,
                ))
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(error, dm_v2_util.HTTP_ERROR_FORMAT)
        if args. async:
            return operation
        else:
            op_name = operation.name
            try:
                dm_write.WaitForOperation(op_name,
                                          operation_description='create',
                                          project=dm_base.GetProject(),
                                          timeout=OPERATION_TIMEOUT)
                log.status.Print('Create operation ' + op_name +
                                 ' completed successfully.')
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error,
                                               dm_v2_util.HTTP_ERROR_FORMAT)

            return dm_v2_util.FetchResourcesAndOutputs(dm_base.GetClient(),
                                                       dm_base.GetMessages(),
                                                       dm_base.GetProject(),
                                                       args.deployment_name)
Пример #29
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']
        location_get = self.context['location_get']
        location = location_get(args)
        cluster_ref = adapter.ParseCluster(args.name, location)
        cluster_name = args.name
        cluster_node_count = None
        cluster_zone = cluster_ref.zone
        cluster_is_required = self.IsClusterRequired(args)
        try:
            # Attempt to get cluster for better prompts and to validate args.
            # Error is a warning but not fatal. Should only exit with a failure on
            # the actual update API calls below.
            cluster = adapter.GetCluster(cluster_ref)
            cluster_name = cluster.name
            cluster_node_count = cluster.currentNodeCount
            cluster_zone = cluster.zone
        except (exceptions.HttpException,
                apitools_exceptions.HttpForbiddenError, util.Error) as error:
            if cluster_is_required:
                raise
            log.warning(
                ('Problem loading details of cluster to update:\n\n{}\n\n'
                 'You can still attempt updates to the cluster.\n').format(
                     console_attr.SafeText(error)))

        # locations will be None if additional-zones was specified, an empty list
        # if it was specified with no argument, or a populated list if zones were
        # provided. We want to distinguish between the case where it isn't
        # specified (and thus shouldn't be passed on to the API) and the case where
        # it's specified as wanting no additional zones, in which case we must pass
        # the cluster's primary zone to the API.
        # TODO(b/29578401): Remove the hasattr once the flag is GA.
        locations = None
        if hasattr(args,
                   'additional_zones') and args.additional_zones is not None:
            locations = sorted([cluster_ref.zone] + args.additional_zones)
        if hasattr(args, 'node_locations') and args.node_locations is not None:
            locations = sorted(args.node_locations)

        if args.IsSpecified('username') or args.IsSpecified(
                'enable_basic_auth'):
            flags.MungeBasicAuthFlags(args)
            options = api_adapter.SetMasterAuthOptions(
                action=api_adapter.SetMasterAuthOptions.SET_USERNAME,
                username=args.username,
                password=args.password)

            try:
                op_ref = adapter.SetMasterAuth(cluster_ref, options)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif (args.generate_password or args.set_password
              or args.IsSpecified('password')):
            if args.generate_password:
                password = ''
                options = api_adapter.SetMasterAuthOptions(
                    action=api_adapter.SetMasterAuthOptions.GENERATE_PASSWORD,
                    password=password)
            else:
                password = args.password
                if not args.IsSpecified('password'):
                    password = input('Please enter the new password:'******'Enabling/Disabling Network Policy causes a rolling '
                'update of all cluster nodes, similar to performing a cluster '
                'upgrade.  This operation is long-running and will block other '
                'operations on the cluster (including delete) until it has run '
                'to completion.',
                cancel_on_no=True)
            options = api_adapter.SetNetworkPolicyOptions(
                enabled=args.enable_network_policy)
            try:
                op_ref = adapter.SetNetworkPolicy(cluster_ref, options)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.start_ip_rotation or args.start_credential_rotation:
            if args.start_ip_rotation:
                msg_tmpl = """This will start an IP Rotation on cluster [{name}]. The \
master will be updated to serve on a new IP address in addition to the current \
IP address. Kubernetes Engine will then recreate all nodes ({num_nodes} nodes) \
to point to the new IP address. This operation is long-running and will block \
other operations on the cluster (including delete) until it has run to \
completion."""
                rotate_credentials = False
            elif args.start_credential_rotation:
                msg_tmpl = """This will start an IP and Credentials Rotation on cluster\
 [{name}]. The master will be updated to serve on a new IP address in addition \
to the current IP address, and cluster credentials will be rotated. Kubernetes \
Engine will then recreate all nodes ({num_nodes} nodes) to point to the new IP \
address. This operation is long-running and will block other operations on the \
cluster (including delete) until it has run to completion."""
                rotate_credentials = True
            console_io.PromptContinue(message=msg_tmpl.format(
                name=cluster_name,
                num_nodes=cluster_node_count if cluster_node_count else '?'),
                                      cancel_on_no=True)
            try:
                op_ref = adapter.StartIpRotation(
                    cluster_ref, rotate_credentials=rotate_credentials)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.complete_ip_rotation or args.complete_credential_rotation:
            if args.complete_ip_rotation:
                msg_tmpl = """This will complete the in-progress IP Rotation on \
cluster [{name}]. The master will be updated to stop serving on the old IP \
address and only serve on the new IP address. Make sure all API clients have \
been updated to communicate with the new IP address (e.g. by running `gcloud \
container clusters get-credentials --project {project} --zone {zone} {name}`). \
This operation is long-running and will block other operations on the cluster \
(including delete) until it has run to completion."""
            elif args.complete_credential_rotation:
                msg_tmpl = """This will complete the in-progress Credential Rotation on\
 cluster [{name}]. The master will be updated to stop serving on the old IP \
address and only serve on the new IP address. Old cluster credentials will be \
invalidated. Make sure all API clients have been updated to communicate with \
the new IP address (e.g. by running `gcloud container clusters get-credentials \
--project {project} --zone {zone} {name}`). This operation is long-running and \
will block other operations on the cluster (including delete) until it has run \
to completion."""
            console_io.PromptContinue(message=msg_tmpl.format(
                name=cluster_name,
                project=cluster_ref.projectId,
                zone=cluster_zone),
                                      cancel_on_no=True)
            try:
                op_ref = adapter.CompleteIpRotation(cluster_ref)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.update_labels is not None:
            try:
                op_ref = adapter.UpdateLabels(cluster_ref, args.update_labels)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.remove_labels is not None:
            try:
                op_ref = adapter.RemoveLabels(cluster_ref, args.remove_labels)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.logging_service is not None and args.monitoring_service is None:
            try:
                op_ref = adapter.SetLoggingService(cluster_ref,
                                                   args.logging_service)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif args.maintenance_window is not None:
            try:
                op_ref = adapter.SetDailyMaintenanceWindow(
                    cluster_ref, cluster.maintenancePolicy,
                    args.maintenance_window)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif getattr(args, 'maintenance_window_start', None) is not None:
            try:
                op_ref = adapter.SetRecurringMaintenanceWindow(
                    cluster_ref, cluster.maintenancePolicy,
                    args.maintenance_window_start, args.maintenance_window_end,
                    args.maintenance_window_recurrence)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif getattr(args, 'clear_maintenance_window', None):
            try:
                op_ref = adapter.RemoveMaintenanceWindow(
                    cluster_ref, cluster.maintenancePolicy)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif getattr(args, 'add_maintenance_exclusion_end', None) is not None:
            try:
                op_ref = adapter.AddMaintenanceExclusion(
                    cluster_ref, cluster.maintenancePolicy,
                    args.add_maintenance_exclusion_name,
                    args.add_maintenance_exclusion_start,
                    args.add_maintenance_exclusion_end)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        elif getattr(args, 'remove_maintenance_exclusion', None) is not None:
            try:
                op_ref = adapter.RemoveMaintenanceExclusion(
                    cluster_ref, cluster.maintenancePolicy,
                    args.remove_maintenance_exclusion)
            except apitools_exceptions.HttpError as error:
                raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
        else:
            if args.enable_legacy_authorization is not None:
                op_ref = adapter.SetLegacyAuthorization(
                    cluster_ref, args.enable_legacy_authorization)
            else:
                options = self.ParseUpdateOptions(args, locations)
                op_ref = adapter.UpdateCluster(cluster_ref, options)

        if not args.async_:
            adapter.WaitForOperation(op_ref,
                                     'Updating {0}'.format(
                                         cluster_ref.clusterId),
                                     timeout_s=3600)

            log.UpdatedResource(cluster_ref)
            cluster_url = util.GenerateClusterUrl(cluster_ref)
            log.status.Print(
                'To inspect the contents of your cluster, go to: ' +
                cluster_url)

            if (args.start_ip_rotation or args.complete_ip_rotation
                    or args.start_credential_rotation
                    or args.complete_credential_rotation):
                cluster = adapter.GetCluster(cluster_ref)
                try:
                    util.ClusterConfig.Persist(cluster, cluster_ref.projectId)
                except kconfig.MissingEnvVarError as error:
                    log.warning(error)
Пример #30
0
def _GetCloudDnsDetails(domains_messages, cloud_dns_zone, domain,
                        enable_dnssec):
    """Fetches list of name servers from provided Cloud DNS Managed Zone.

  Args:
    domains_messages: Cloud Domains messages module.
    cloud_dns_zone: Cloud DNS Zone resource reference.
    domain: Domain name.
    enable_dnssec: If true, try to read DNSSEC information from the Zone.

  Returns:
    A pair: List of name servers and a list of Ds records (or [] if e.g. the
    Zone is not signed).
  """
    # Get the managed-zone.
    dns_api_version = 'v1'
    dns = apis.GetClientInstance('dns', dns_api_version)
    dns_messages = dns.MESSAGES_MODULE
    zone_ref = dns_api_util.GetRegistry(dns_api_version).Parse(
        cloud_dns_zone,
        params={
            'project': properties.VALUES.core.project.GetOrFail,
        },
        collection='dns.managedZones')

    try:
        zone = dns.managedZones.Get(
            dns_messages.DnsManagedZonesGetRequest(
                project=zone_ref.project, managedZone=zone_ref.managedZone))
    except apitools_exceptions.HttpError as error:
        raise calliope_exceptions.HttpException(error)
    domain_with_dot = domain + '.'
    if zone.dnsName != domain_with_dot:
        raise exceptions.Error(
            'The dnsName \'{}\' of specified Cloud DNS zone \'{}\' does not match the '
            'registration domain \'{}\''.format(zone.dnsName, cloud_dns_zone,
                                                domain_with_dot))
    if zone.visibility != dns_messages.ManagedZone.VisibilityValueValuesEnum.public:
        raise exceptions.Error(
            'Cloud DNS Zone \'{}\' is not public.'.format(cloud_dns_zone))

    if not enable_dnssec:
        return zone.nameServers, []

    signed = dns_messages.ManagedZoneDnsSecConfig.StateValueValuesEnum.on
    if not zone.dnssecConfig or zone.dnssecConfig.state != signed:
        log.status.Print(
            'Cloud DNS Zone \'{}\' is not signed. DNSSEC won\'t be enabled.'.
            format(cloud_dns_zone))
        return zone.nameServers, []
    try:
        dns_keys = []
        req = dns_messages.DnsDnsKeysListRequest(
            project=zone_ref.project,
            managedZone=zone_ref.managedZone,
            maxResults=1)
        while True:
            resp = dns.dnsKeys.List(
                dns_messages.DnsDnsKeysListRequest(
                    project=zone_ref.project,
                    managedZone=zone_ref.managedZone))
            dns_keys += resp.dnsKeys
            req.pageToken = resp.nextPageToken
            if not resp.nextPageToken:
                break
    except apitools_exceptions.HttpError as error:
        log.status.Print(
            'Cannot read DS records from Cloud DNS Zone \'{}\': {}. '
            'DNSSEC won\'t be enabled.'.format(cloud_dns_zone, error))
    ds_records = _ConvertDnsKeys(domains_messages, dns_messages, dns_keys)
    if not ds_records:
        log.status.Print(
            'No supported DS records found in Cloud DNS Zone \'{}\'. '
            'DNSSEC won\'t be enabled.'.format(cloud_dns_zone))
        return zone.nameServers, []
    return zone.nameServers, ds_records