Example #1
0
  def GetCluster(self, cluster_ref):
    """Get a running cluster.

    Args:
      cluster_ref: cluster Resource to describe.
    Returns:
      Cluster message.
    Raises:
      Error: if cluster cannot be found.
    """
    try:
      return self.client.projects_zones_clusters.Get(cluster_ref.Request())
    except apitools_exceptions.HttpError as error:
      api_error = util.GetError(error)
      if api_error.code != 404:
        raise api_error

    # Cluster couldn't be found, maybe user got zone wrong?
    try:
      clusters = self.ListClusters(cluster_ref.projectId).clusters
    except apitools_exceptions.HttpError as error:
      raise exceptions.HttpException(util.GetError(error))
    for cluster in clusters:
      if cluster.name == cluster_ref.clusterId:
        # User likely got zone wrong.
        raise util.Error(WRONG_ZONE_ERROR_MSG.format(
            error=api_error,
            name=cluster_ref.clusterId,
            wrong_zone=self.Zone(cluster_ref),
            zone=cluster.zone))
    # Couldn't find a cluster with that name.
    raise util.Error(NO_SUCH_CLUSTER_ERROR_MSG.format(
        error=api_error,
        name=cluster_ref.clusterId,
        project=cluster_ref.projectId))
Example #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']

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

    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 exceptions.HttpError as error:
        errors.append(util.GetError(error))
      except util.Error as error:
        errors.append(error)
    if not flags.GetAsyncValueFromAsyncAndWaitFlags(args.async, args.wait):
      # Poll each operation for completion
      for operation_ref, cluster_ref in operations:
        try:
          adapter.WaitForOperation(
              operation_ref,
              'Deleting cluster {0}'.format(cluster_ref.clusterId),
              timeout_s=args.timeout)
          # Purge cached config files
          util.ClusterConfig.Purge(cluster_ref.clusterId,
                                   adapter.Zone(cluster_ref),
                                   cluster_ref.projectId)
          if properties.VALUES.container.cluster.Get() == cluster_ref.clusterId:
            properties.PersistProperty(
                properties.VALUES.container.cluster, None)
          log.DeletedResource(cluster_ref)
        except exceptions.HttpError as error:
          errors.append(util.GetError(error))
        except util.Error as error:
          errors.append(error)
Example #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']

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

    options = api_adapter.UpdateClusterOptions(
        monitoring_service=args.monitoring_service,
        disable_addons=args.disable_addons)

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

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

      log.UpdatedResource(cluster_ref)
Example #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)
        op_ref = adapter.ParseOperation(args.operation_id, location)
        try:
            op = adapter.GetOperation(op_ref)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(util.GetError(error))

        console_io.PromptContinue(
            message='Are you sure you want to cancel operation {0}?'.format(
                op.name),
            throw_if_unattended=True,
            cancel_on_no=True)

        try:
            adapter.CancelOperation(op_ref)
            log.status.Print(
                CANCEL_OPERATION_MESSAGE.format(args.operation_id,
                                                args.operation_id))
            return adapter.GetOperation(op_ref)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(error)
Example #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']

        cluster_ref = adapter.ParseCluster(args.name)

        # 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_family=args.image_family)

        if options.version:
            new_version = options.version
        else:
            new_version = 'latest'

        if args.master:
            node_message = 'Master'
            current_version = cluster.currentMasterVersion
        else:
            node_message = 'All {node_count} nodes'.format(
                node_count=cluster.currentNodeCount)
            current_version = cluster.currentNodeVersion

        console_io.PromptContinue(
            message=
            '{node_message} of cluster [{cluster_name}] will be upgraded '
            'from version [{current_version}] to version [{new_version}]. '
            'This operation is long-running and will block other operations '
            'on the cluster (including delete) until it has run to completion.'
            .format(node_message=node_message,
                    cluster_name=cluster.name,
                    current_version=current_version,
                    new_version=new_version),
            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(util.GetError(error))

        if args.wait:
            adapter.WaitForOperation(
                op_ref, 'Upgrading {0}'.format(cluster_ref.clusterId))

            log.UpdatedResource(cluster_ref)
Example #6
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

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

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

        project = properties.VALUES.core.project.Get(required=True)
        zone = None
        if args.zone:
            zone = adapter.registry.Parse(args.zone,
                                          collection='compute.zones').zone

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

        try:
            clusters = adapter.ListClusters(project, zone)
            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
            self._upgrade_hint = ''
            vv = VersionVerifier()
            for c in clusters.clusters:
                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')
            return clusters.clusters
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(util.GetError(error))
Example #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:
      Cluster message for the successfully created node pool.

    Raises:
      util.Error, if creation failed.
    """
        adapter = self.context['api_adapter']

        if not args.scopes:
            args.scopes = []

        try:
            if not args.scopes:
                args.scopes = []
            pool_ref = adapter.ParseNodePool(args.name)
            options = self.ParseCreateNodePoolOptions(args)
            operation_ref = adapter.CreateNodePool(pool_ref, options)

            adapter.WaitForOperation(operation_ref,
                                     'Creating node pool {0}'.format(
                                         pool_ref.nodePoolId),
                                     timeout_s=args.timeout)
            pool = adapter.GetNodePool(pool_ref)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(util.GetError(error))

        log.CreatedResource(pool_ref)
        return pool
Example #8
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)

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

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

        log.CreatedResource(cluster_ref)
        # Persist cluster config
        current_context = kconfig.Kubeconfig.Default().current_context
        c_config = util.ClusterConfig.Persist(cluster, cluster_ref.projectId,
                                              self.cli)
        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
Example #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()
        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)

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

        return cluster
Example #10
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)

        options = api_adapter.UpdateClusterOptions(
            monitoring_service=args.monitoring_service,
            disable_addons=args.disable_addons,
            enable_autoscaling=args.enable_autoscaling,
            min_nodes=args.min_nodes,
            max_nodes=args.max_nodes,
            node_pool=args.node_pool,
            locations=locations)

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

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

            log.UpdatedResource(cluster_ref)
Example #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']

    try:
      return adapter.GetOperation(adapter.ParseOperation(args.operation_id))
    except apitools_base.HttpError as error:
      raise exceptions.HttpException(util.GetError(error))
    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']

        project = properties.VALUES.core.project.Get(required=True)
        cluster = properties.VALUES.container.cluster.Get(required=True)
        zone = properties.VALUES.compute.zone.Get(required=True)

        try:
            return adapter.ListNodePools(project, zone, cluster)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(util.GetError(error))
Example #13
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']

    project = properties.VALUES.core.project.Get(required=True)
    zone = None
    if args.zone:
      zone = adapter.registry.Parse(args.zone, collection='compute.zones').zone

    try:
      return adapter.ListClusters(project, zone)
    except apitools_base.HttpError as error:
      raise exceptions.HttpException(util.GetError(error))
Example #14
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']

        pool_ref = adapter.ParseNodePool(args.name)

        console_io.PromptContinue(message=(
            'The following node pool will be deleted.\n'
            '[{name}] in cluster [{clusterId}] in zone [{zone}]').format(
                name=pool_ref.nodePoolId,
                clusterId=pool_ref.clusterId,
                zone=adapter.Zone(pool_ref)),
                                  throw_if_unattended=True,
                                  cancel_on_no=True)

        try:
            # Make sure it exists (will raise appropriate error if not)
            adapter.GetNodePool(pool_ref)

            op_ref = adapter.DeleteNodePool(pool_ref)
            if args.wait:
                adapter.WaitForOperation(op_ref,
                                         'Deleting node pool {0}'.format(
                                             pool_ref.nodePoolId),
                                         timeout_s=args.timeout)
        except apitools_exceptions.HttpError as error:
            raise exceptions.HttpException(util.GetError(error))

        log.DeletedResource(pool_ref)
        return op_ref
Example #15
0
  def Run(self, args):
    """This is what gets called when the user runs this command.

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

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

    operation_ref = adapter.ParseOperation(args.operation_id)

    try:
      # Try fetching it first to ensure we have permissions and the op exists.
      adapter.GetOperation(operation_ref)

      return adapter.WaitForOperation(
          operation_ref,
          'Waiting for {0} to complete'.format(operation_ref.operationId))
    except apitools_exceptions.HttpError as error:
      raise exceptions.HttpException(util.GetError(error))
Example #16
0
class Create(base.Command):
    """Create a cluster for running containers."""
    @staticmethod
    def Args(parser):
        _Args(parser)
        flags.AddClusterAutoscalingFlags(parser, suppressed=True)
        flags.AddLocalSSDFlag(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,
            disable_addons=args.disable_addons,
            local_ssd_count=args.local_ssd_count,
            tags=args.tags,
            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)

    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()
        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 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(util.GetError(error))