예제 #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.

    Raises:
      util.Error: if the cluster is unreachable or not running.
    """
        util.CheckKubectlInstalled()
        adapter = self.context['api_adapter']
        location_get = self.context['location_get']
        location = location_get(args)
        cluster_ref = adapter.ParseCluster(args.name, location)
        if getattr(args, 'region', None):
            message = messages.NonGAFeatureUsingV1APIWarning(
                self._release_track)
            if message:
                console_io.PromptContinue(message=message, cancel_on_no=True)
        log.status.Print('Fetching cluster endpoint and auth data.')
        # Call DescribeCluster to get auth info and cache for next time
        cluster = adapter.GetCluster(cluster_ref)
        auth = cluster.masterAuth
        has_creds = (auth and ((auth.clientCertificate and auth.clientKey) or
                               (auth.username and auth.password)))
        if not has_creds and not util.ClusterConfig.UseGCPAuthProvider(
                cluster):
            raise util.Error(
                'get-credentials requires edit permission on {0}'.format(
                    cluster_ref.projectId))
        if not adapter.IsRunning(cluster):
            log.warn(NOT_RUNNING_MSG.format(cluster_ref.clusterId))
        util.ClusterConfig.Persist(cluster, cluster_ref.projectId)
    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.

    """
        adapter = self.context['api_adapter']
        location_get = self.context['location_get']
        location = location_get(args)
        if getattr(args, 'region', None):
            message = messages.NonGAFeatureUsingV1APIWarning(
                self._release_track)
            if message:
                console_io.PromptContinue(message=message, cancel_on_no=True)

        cluster_ref = adapter.ParseCluster(args.name, location)
        cluster = adapter.GetCluster(cluster_ref)
        pool = adapter.FindNodePool(cluster, args.node_pool)
        console_io.PromptContinue(
            message=('Pool [{pool}] for [{cluster_name}] will be resized to '
                     '{new_size}.').format(pool=pool.name,
                                           cluster_name=cluster.name,
                                           new_size=args.size),
            throw_if_unattended=True,
            cancel_on_no=True)
        op_ref = adapter.ResizeNodePool(cluster_ref, pool.name, args.size)

        if not args. async:
            adapter.WaitForOperation(
                op_ref, 'Resizing {0}'.format(cluster_ref.clusterId))
        log.UpdatedResource(cluster_ref)
예제 #3
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)
    if getattr(args, 'region', None):
      message = messages.NonGAFeatureUsingV1APIWarning(self._release_track)
      if message:
        console_io.PromptContinue(message=message, cancel_on_no=True)
    cluster_ref = adapter.ParseCluster(args.name, location)

    # Make sure it exists (will raise appropriate error if not)
    cluster = adapter.GetCluster(cluster_ref)

    options = api_adapter.UpdateClusterOptions(
        version=args.cluster_version,
        update_master=args.master,
        update_nodes=(not args.master),
        node_pool=args.node_pool,
        image_type=args.image_type)

    upgrade_message = container_command_util.ClusterUpgradeMessage(
        cluster,
        master=args.master,
        node_pool=args.node_pool,
        new_version=options.version)

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

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

      log.UpdatedResource(cluster_ref)
예제 #4
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)

        if getattr(args, 'region', None):
            message = messages.NonGAFeatureUsingV1APIWarning(
                self._release_track)
            if message:
                console_io.PromptContinue(message=message, cancel_on_no=True)

        self._upgrade_hint = None
        vv = VersionVerifier()
        c = adapter.GetCluster(adapter.ParseCluster(args.name, location))
        ver_status = vv.Compare(c.currentMasterVersion, c.currentNodeVersion)

        if ver_status == VersionVerifier.UPGRADE_AVAILABLE:
            self._upgrade_hint = UpgradeHelpText.UPGRADE_AVAILABLE
        elif ver_status == VersionVerifier.SUPPORT_ENDING:
            self._upgrade_hint = UpgradeHelpText.SUPPORT_ENDING
        elif ver_status == VersionVerifier.UNSUPPORTED:
            self._upgrade_hint = UpgradeHelpText.UNSUPPORTED

        if ver_status != VersionVerifier.UP_TO_DATE:
            self._upgrade_hint += UpgradeHelpText.UPGRADE_COMMAND.format(
                name=c.name)

        return c
예제 #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:
      Some value that we want to have printed later.
    """
        adapter = self.context['api_adapter']
        location_get = self.context['location_get']
        location = location_get(args)
        if getattr(args, 'region', None):
            message = messages.NonGAFeatureUsingV1APIWarning(
                self._release_track)
            if message:
                console_io.PromptContinue(message=message, cancel_on_no=True)
        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:
                # Make sure it exists (will raise appropriate error if not)
                adapter.GetCluster(cluster_ref)

                op_ref = adapter.DeleteCluster(cluster_ref)
                operations.append((op_ref, cluster_ref))
            except apitools_exceptions.HttpError as error:
                errors.append(
                    str(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
                    util.ClusterConfig.Purge(cluster_ref.clusterId,
                                             adapter.Zone(cluster_ref),
                                             cluster_ref.projectId)
                    if properties.VALUES.container.cluster.Get(
                    ) == cluster_ref.clusterId:
                        properties.PersistProperty(
                            properties.VALUES.container.cluster, None)
                    log.DeletedResource(cluster_ref)
                except apitools_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))
예제 #6
0
class Create(base.CreateCommand):
    """Create a cluster for running containers."""
    @staticmethod
    def Args(parser):
        _Args(parser)
        _AddAdditionalZonesFlag(parser)
        flags.AddAddonsFlags(parser,
                             hide_addons_flag=True,
                             deprecate_disable_addons_flag=False)
        flags.AddClusterAutoscalingFlags(parser)
        flags.AddEnableAutoRepairFlag(parser, suppressed=True)
        flags.AddEnableKubernetesAlphaFlag(parser, suppressed=True)
        flags.AddEnableLegacyAuthorizationFlag(parser, hidden=True)
        flags.AddIPAliasFlags(parser, hidden=True)
        flags.AddLabelsFlag(parser, suppressed=True)
        flags.AddLocalSSDFlag(parser, suppressed=True)
        flags.AddMaintenanceWindowFlag(parser, hidden=True)
        flags.AddMasterAuthorizedNetworksFlags(parser, hidden=True)
        flags.AddNetworkPolicyFlags(parser, hidden=True)
        flags.AddNodeTaintsFlag(parser, hidden=True)
        flags.AddOldClusterNodeIdentityFlags(parser)
        flags.AddPreemptibleFlag(parser, suppressed=True)
        flags.AddNodeVersionFlag(parser, hidden=True)

    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)

        if not args.scopes:
            args.scopes = []
        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):
            message = messages.NonGAFeatureUsingV1APIWarning(
                self._release_track)
            if message:
                console_io.PromptContinue(message=message, cancel_on_no=True)

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

        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]
예제 #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)
        if getattr(args, 'region', None):
            message = messages.NonGAFeatureUsingV1APIWarning(
                self._release_track)
            if message:
                console_io.PromptContinue(message=message, cancel_on_no=True)
        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.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:'******'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. Container 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)

            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)
    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, ignore_property=True, required=False)
        if getattr(args, 'region', None):
            message = messages.NonGAFeatureUsingV1APIWarning(
                self._release_track)
            if message:
                console_io.PromptContinue(message=message, cancel_on_no=True)
        project = properties.VALUES.core.project.Get(required=True)

        def sort_key(cluster):
            return (cluster.zone, cluster.name)

        try:
            clusters = adapter.ListClusters(project, location)
            clusters.clusters = sorted(clusters.clusters, key=sort_key)

            if clusters.missingZones:
                log.warning(
                    'The following zones did not respond: {0}. List results may be '
                    'incomplete.'.format(', '.join(clusters.missingZones)))

            upgrade_available = False
            support_ending = False
            unsupported = False
            expiring = False
            self._upgrade_hint = ''
            self._expire_warning = ''
            vv = VersionVerifier()
            for c in clusters.clusters:
                time_left = transforms.ParseExpireTime(c.expireTime)
                if time_left and time_left.days < constants.EXPIRE_WARNING_DAYS:
                    expiring = True
                if c.enableKubernetesAlpha:
                    # Don't print upgrade hints for alpha clusters, they aren't
                    # upgradeable.
                    continue
                ver_status = vv.Compare(c.currentMasterVersion,
                                        c.currentNodeVersion)
                if ver_status == VersionVerifier.UPGRADE_AVAILABLE:
                    c.currentNodeVersion += ' *'

                    upgrade_available = True
                elif ver_status == VersionVerifier.SUPPORT_ENDING:
                    c.currentNodeVersion += ' **'
                    support_ending = True
                elif ver_status == VersionVerifier.UNSUPPORTED:
                    c.currentNodeVersion += ' ***'
                    unsupported = True

            if upgrade_available:
                self._upgrade_hint += UpgradeHelpText.UPGRADE_AVAILABLE
            if support_ending:
                self._upgrade_hint += UpgradeHelpText.SUPPORT_ENDING
            if unsupported:
                self._upgrade_hint += UpgradeHelpText.UNSUPPORTED
            if self._upgrade_hint:
                self._upgrade_hint += UpgradeHelpText.UPGRADE_COMMAND.format(
                    name='NAME')
            if expiring:
                self._expire_warning = constants.EXPIRE_WARNING

            return clusters.clusters
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)