def testGenerateClusterUrl(self):
     registry = resources.Registry()
     cluster_ref = registry.Parse(
         'some-cluster-name',
         params={
             'projectId': 'some-project-id',
             'zone': 'some-zone',
         },
         collection='container.projects.zones.clusters')
     self.assertEqual(
         'https://console.cloud.google.com/kubernetes/'
         'workload_/gcloud/some-zone/some-cluster-name?'
         'project=some-project-id', c_util.GenerateClusterUrl(cluster_ref))
Exemple #2
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=1800)

            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)
Exemple #3
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.AddMaxPodsPerNodeFlag(parser)
        flags.AddEnableAutoRepairFlag(parser, for_create=True)
        flags.AddEnableKubernetesAlphaFlag(parser)
        flags.AddEnableStackdriverKubernetesFlag(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.AddClusterNodeIdentityFlags(parser)
        flags.AddPrivateClusterFlags(parser,
                                     with_deprecated=False,
                                     with_alpha=False)
        flags.AddClusterVersionFlag(parser)
        flags.AddNodeVersionFlag(parser)
        flags.AddEnableAutoUpgradeFlag(parser)
        flags.AddTpuFlags(parser, hidden=False)
        flags.AddResourceUsageExportFlags(parser)

    def ParseCreateOptions(self, args):
        flags.WarnGAForFutureAutoUpgradeChange()
        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_ip_alias:
            log.warning(
                'The Pod address range limits the maximum size of the cluster. '
                'Please refer to https://cloud.google.com/kubernetes-engine/docs/how-to/flexible-pod-cidr to learn how to optimize IP address allocation.'
            )
        else:
            max_node_number = util.CalculateMaxNodeNumberByPodRange(
                options.cluster_ipv4_cidr)
            if max_node_number > 0:
                log.warning(
                    'Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most %d node(s). '
                    % max_node_number)

        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.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]
Exemple #4
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)
    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.message)

    return [cluster]
Exemple #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.
    """
        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.enable_shielded_nodes:
            log.warning(
                'Starting with version 1.18, clusters will have shielded GKE nodes by default.'
            )

        if options.enable_ip_alias:
            log.warning(
                'The Pod address range limits the maximum size of the cluster. '
                'Please refer to https://cloud.google.com/kubernetes-engine/docs/how-to/flexible-pod-cidr to learn how to optimize IP address allocation.'
            )
        else:
            max_node_number = util.CalculateMaxNodeNumberByPodRange(
                options.cluster_ipv4_cidr)
            if max_node_number > 0:
                log.warning(
                    'Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most %d node(s). '
                    % max_node_number)

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

        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]
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)

    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 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]
Exemple #7
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)