Ejemplo n.º 1
0
    def _VerifyClusterExclusivity(self, kube_client, project, context, uuid):
        """Verifies that the cluster can be registered to the project.

    The ensures cluster exclusivity constraints are not violated as well as
    ensuring the user is authorized to register the cluster to the project.

    Args:
      kube_client: A KubernetesClient
      project: A project ID the user is attempting to register the cluster with.
      context: The kubernetes cluster context.
      uuid: The UUID of the kubernetes cluster.

    Raises:
      exceptions.Error: If exclusivity constraints are violated or the user is
        not authorized to register to the cluster.
    """
        authorized_projects = hub_util.UserAccessibleProjectIDSet()
        registered_project = exclusivity_util.GetMembershipCROwnerID(
            kube_client)

        if registered_project:
            if registered_project not in authorized_projects:
                raise exceptions.Error(
                    'The cluster is already registered to [{}], which you are not '
                    'authorized to access.'.format(registered_project))
            elif registered_project != project:
                raise exceptions.Error(
                    'This cluster is already registered to [{}]. '
                    'Please unregister this cluster before continuing:\n\n'
                    '  gcloud {}container hub memberships unregister --project {} --context {}'
                    .format(
                        registered_project,
                        hub_util.ReleaseTrackCommandPrefix(
                            self.ReleaseTrack()), registered_project, context))

        if project not in authorized_projects:
            raise exceptions.Error(
                'The project you are attempting to register with [{}] either '
                'doesn\'t exist or you are not authorized to access it.'.
                format(project))

        try:
            registered_membership_project = api_util.ProjectForClusterUUID(
                uuid, [project, registered_project])
        except apitools_exceptions.HttpNotFoundError as e:
            raise exceptions.Error(
                'Could not access Memberships API. Is your project whitelisted for '
                'API access? Underlying error: {}'.format(e))

        if registered_membership_project and registered_membership_project != project:
            raise exceptions.Error(
                'This cluster is already registered to [{}]. '
                'Please unregister this cluster before continuing:\n\n'
                '  gcloud {}container hub memberships unregister --project {} --context {}'
                .format(
                    registered_membership_project,
                    hub_util.ReleaseTrackCommandPrefix(self.ReleaseTrack()),
                    registered_membership_project, context))
Ejemplo n.º 2
0
    def Run(self, args):
        # TODO(b/145953996): api_utils map release_track to an api_version.
        # All old commands needs to use 'v1beta1' irrespective of the release track,
        # till they are removed (already deprecation policy applied).
        self.release_track = base.ReleaseTrack.BETA
        project = arg_utils.GetFromNamespace(args,
                                             '--project',
                                             use_defaults=True)
        kube_client = kube_util.OldKubernetesClient(args)
        uuid = kube_util.GetClusterUUID(kube_client)

        # Delete membership from GKE Hub API.
        try:
            name = 'projects/{}/locations/global/memberships/{}'.format(
                project, uuid)
            api_util.DeleteMembership(name, self.release_track)
        except apitools_exceptions.HttpUnauthorizedError as e:
            raise exceptions.Error(
                'You are not authorized to unregister clusters from project [{}]. '
                'Underlying error: {}'.format(project, e))
        except apitools_exceptions.HttpNotFoundError as e:
            log.status.Print(
                'Membership for [{}] was not found. It may already have been '
                'deleted, or it may never have existed.'.format(args.context))

        # Get namespace for the connect resource label.
        selector = '{}={}'.format(agent_util.CONNECT_RESOURCE_LABEL, project)
        namespaces = kube_client.NamespacesWithLabelSelector(selector)
        if not namespaces:
            raise exceptions.Error(
                'There\'s no namespace for the label {}. '
                'If gke-connect is labeled with another project,'
                'You\'ll have to manually delete the namespace.'
                'You can find all namespaces by running:\n\n'
                '  `kubectl get ns -l {}`'.format(
                    agent_util.CONNECT_RESOURCE_LABEL,
                    agent_util.CONNECT_RESOURCE_LABEL))

        registered_project = exclusivity_util.GetMembershipCROwnerID(
            kube_client)
        if registered_project:
            if registered_project != project:
                raise exceptions.Error(
                    'This cluster is registered to another project [{}]. '
                    'Please unregister this cluster from the correct project:\n\n'
                    '  gcloud {}container hub unregister-cluster --project {} --context {}'
                    .format(
                        registered_project,
                        hub_util.ReleaseTrackCommandPrefix(
                            self.ReleaseTrack()), registered_project,
                        args.context))

        # Delete membership resources.
        exclusivity_util.DeleteMembershipResources(kube_client)

        # Delete the connect agent.
        agent_util.DeleteConnectNamespace(kube_client, args)
    def Run(self, args):
        project = arg_utils.GetFromNamespace(args,
                                             '--project',
                                             use_defaults=True)
        kube_client = hub_util.KubernetesClient(args)
        uuid = hub_util.GetClusterUUID(kube_client)

        # Delete membership from GKE Hub API.
        try:
            name = 'projects/{}/locations/global/memberships/{}'.format(
                project, uuid)
            hub_util.DeleteMembership(name)
        except apitools_exceptions.HttpUnauthorizedError as e:
            raise exceptions.Error(
                'You are not authorized to unregister clusters from project [{}]. '
                'Underlying error: {}'.format(project, e))
        except apitools_exceptions.HttpNotFoundError as e:
            log.status.Print(
                'Membership for [{}] was not found. It may already have been '
                'deleted, or it may never have existed. You can safely run the '
                '`register-cluster` command again for this cluster.'.format(
                    args.context))

        # Get namespace for the connect resource label.
        selector = '{}={}'.format(hub_util.CONNECT_RESOURCE_LABEL, project)
        namespaces = kube_client.NamespacesWithLabelSelector(selector)
        if not namespaces:
            raise exceptions.Error(
                'There\'s no namespace for the label {}. '
                'If gke-connect is labeled with another project,'
                'You\'ll have to manually delete the namespace.'
                'You can find all namespaces by running:\n\n'
                '  `kubectl get ns -l {}`'.format(
                    hub_util.CONNECT_RESOURCE_LABEL,
                    hub_util.CONNECT_RESOURCE_LABEL))

        registered_project = hub_util.GetMembershipCROwnerID(kube_client)
        if registered_project:
            if registered_project != project:
                raise exceptions.Error(
                    'This cluster is registered to another project [{}]. '
                    'Please unregister this cluster from the correct project:\n\n'
                    '  gcloud {}container hub unregister-cluster --project {} --context {}'
                    .format(
                        registered_project,
                        hub_util.ReleaseTrackCommandPrefix(
                            self.ReleaseTrack()), registered_project,
                        args.context))

        # Delete membership resources.
        hub_util.DeleteMembershipResources(kube_client)

        # Delete the connect agent.
        hub_util.DeleteConnectNamespace(args)
Ejemplo n.º 4
0
    def _CheckMembershipWithUUID(self, resource_name, cluster_name):
        """Checks for an existing Membership with UUID.

    In the past, by default we used Cluster UUID to create a membership. Now
    we use user supplied cluster_name. This check ensures that we don't
    reregister a cluster.

    Args:
      resource_name: The full membership resource name using the cluster uuid.
      cluster_name: User supplied cluster_name.

    Returns:
     The Membership resource or None.

    Raises:
      exceptions.Error: If it fails to getMembership.
    """
        obj = None
        try:
            obj = api_util.GetMembership(resource_name, self.ReleaseTrack())
            if (hasattr(obj, 'description')
                    and obj.description != cluster_name):
                # A membership exists, but does not have the same cluster_name.
                # This is possible if two different users attempt to register the same
                # cluster, or if the user is upgrading and has passed a different
                # cluster_name. Treat this as an error: even in the upgrade case,
                # this is useful to prevent the user from upgrading the wrong cluster.
                raise exceptions.Error(
                    'There is an existing membership, [{}], that conflicts with [{}]. '
                    'Please delete it before continuing:\n\n'
                    '  gcloud {}container hub memberships delete {}'.format(
                        obj.description, cluster_name,
                        hub_util.ReleaseTrackCommandPrefix(
                            self.ReleaseTrack()), resource_name))
        except apitools_exceptions.HttpNotFoundError:
            # We couldn't find a membership with uuid, so it's safe to create a
            # new one.
            pass
        return obj
Ejemplo n.º 5
0
    def Run(self, args):
        project = arg_utils.GetFromNamespace(args,
                                             '--project',
                                             use_defaults=True)
        kube_client = hub_util.KubernetesClient(args)
        registered_project = hub_util.GetMembershipCROwnerID(kube_client)
        authorized_projects = hub_util.UserAccessibleProjectIDSet()
        if registered_project:
            if registered_project not in authorized_projects:
                raise exceptions.Error(
                    'The cluster is already registered to [{}], which you are not '
                    'authorized to access.'.format(registered_project))
            elif registered_project != project:
                raise exceptions.Error(
                    'This cluster is registered to another project [{}]. '
                    'Please unregister this cluster from the correct project:\n\n'
                    '  gcloud {}container hub unregister-cluster --project {} --context {}'
                    .format(
                        registered_project,
                        hub_util.ReleaseTrackCommandPrefix(
                            self.ReleaseTrack()), registered_project,
                        args.context))

        if project not in authorized_projects:
            raise exceptions.Error(
                'The project you are attempting to register with [{}] either '
                'doesn\'t exist or you are not authorized to access it.'.
                format(project))

        uuid = hub_util.GetClusterUUID(kube_client)
        try:
            registered_membership_project = hub_util.ProjectForClusterUUID(
                uuid, [project, registered_project])
        except apitools_exceptions.HttpNotFoundError as e:
            raise exceptions.Error(
                'Could not access Memberships API. Is your project whitelisted for '
                'API access? Underlying error: {}'.format(e))

        if registered_membership_project and project != registered_membership_project:
            raise exceptions.Error(
                'This cluster is registered to another project [{}]. '
                'Please unregister this cluster from the appropriate project:\n\n'
                '  gcloud {}container hub unregister-cluster --project {} --context {}'
                .format(
                    registered_membership_project,
                    hub_util.ReleaseTrackCommandPrefix(self.ReleaseTrack()),
                    registered_membership_project, args.context))

        if not registered_membership_project:
            log.status.Print(
                'Membership for [{}] was not found. It may already have been '
                'deleted, or it may never have existed. You can safely run the '
                '`register-cluster` command again for this cluster.'.format(
                    args.context))
            # There is no Membership for this cluster, but there is a Membership CR.
            # We can safely remove the Membership CR, so users can register to another
            # hub without issue.
            if registered_project:
                hub_util.DeleteMembershipResources(kube_client)
            return
        hub_util.DeleteConnectNamespace(args)

        try:
            name = 'projects/{}/locations/global/memberships/{}'.format(
                project, uuid)
            hub_util.DeleteMembership(name)
            hub_util.DeleteMembershipResources(kube_client)
        except apitools_exceptions.HttpUnauthorizedError as e:
            raise exceptions.Error(
                'You are not authorized to unregister clusters from project [{}]. '
                'Underlying error: {}'.format(project, e))
Ejemplo n.º 6
0
    def Run(self, args):
        project = arg_utils.GetFromNamespace(args,
                                             '--project',
                                             use_defaults=True)

        # This incidentally verifies that the kubeconfig and context args are valid.
        kube_client = hub_util.KubernetesClient(args)
        uuid = hub_util.GetClusterUUID(kube_client)

        self._VerifyClusterExclusivity(kube_client, project, args.context,
                                       uuid)

        # Read the service account files provided in the arguments early, in order
        # to catch invalid files before performing mutating operations.
        try:
            service_account_key_data = hub_util.Base64EncodedFileContents(
                args.service_account_key_file)
        except files.Error as e:
            raise exceptions.Error('Could not process {}: {}'.format(
                SERVICE_ACCOUNT_KEY_FILE_FLAG, e))

        docker_credential_data = None
        if args.docker_credential_file:
            try:
                docker_credential_data = hub_util.Base64EncodedFileContents(
                    args.docker_credential_file)
            except files.Error as e:
                raise exceptions.Error('Could not process {}: {}'.format(
                    DOCKER_CREDENTIAL_FILE_FLAG, e))

        # The full resource name of the membership for this registration flow.
        name = 'projects/{}/locations/global/memberships/{}'.format(
            project, uuid)

        # Attempt to create a membership.
        already_exists = False
        try:
            hub_util.ApplyMembershipResources(kube_client, project)
            obj = hub_util.CreateMembership(project, uuid, args.CLUSTER_NAME)
        except apitools_exceptions.HttpConflictError as e:
            # If the error is not due to the object already existing, re-raise.
            error = core_api_exceptions.HttpErrorPayload(e)
            if error.status_description != 'ALREADY_EXISTS':
                raise

            # The membership already exists. Check to see if it has the same
            # description (i.e., user-visible cluster name).
            obj = hub_util.GetMembership(name)
            if obj.description != args.CLUSTER_NAME:
                # A membership exists, but does not have the same description. This is
                # possible if two different users attempt to register the same
                # cluster, or if the user is upgrading and has passed a different
                # cluster name. Treat this as an error: even in the upgrade case,
                # this is useful to prevent the user from upgrading the wrong cluster.
                raise exceptions.Error(
                    'There is an existing membership, [{}], that conflicts with [{}]. '
                    'Please delete it before continuing:\n\n'
                    '  gcloud {}container memberships delete {}'.format(
                        obj.description, args.CLUSTER_NAME,
                        hub_util.ReleaseTrackCommandPrefix(
                            self.ReleaseTrack()), name))

            # The membership exists and has the same description.
            already_exists = True
            console_io.PromptContinue(
                message='A membership for [{}] already exists. Continuing will '
                'update the Connect agent deployment to use a new image (if one is '
                'available), or install the Connect agent if it is not already '
                'running.'.format(args.CLUSTER_NAME),
                cancel_on_no=True)

        # A membership exists. Attempt to update the existing agent deployment, or
        # install a new agent if necessary.
        if already_exists:
            obj = hub_util.GetMembership(name)
            hub_util.DeployConnectAgent(args,
                                        service_account_key_data,
                                        docker_credential_data,
                                        upgrade=True)
            return obj

        # No membership exists. Attempt to create a new one, and install a new
        # agent.
        try:
            hub_util.DeployConnectAgent(args,
                                        service_account_key_data,
                                        docker_credential_data,
                                        upgrade=False)
        except:
            hub_util.DeleteMembership(name)
            hub_util.DeleteMembershipResources(kube_client)
            raise
        return obj