...

Source file src/github.com/linkerd/linkerd2/multicluster/cmd/unlink.go

Documentation: github.com/linkerd/linkerd2/multicluster/cmd

     1  package cmd
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	pkgcmd "github.com/linkerd/linkerd2/pkg/cmd"
    10  	"github.com/linkerd/linkerd2/pkg/k8s"
    11  	"github.com/linkerd/linkerd2/pkg/k8s/resource"
    12  	mc "github.com/linkerd/linkerd2/pkg/multicluster"
    13  	log "github.com/sirupsen/logrus"
    14  	"github.com/spf13/cobra"
    15  	appsv1 "k8s.io/api/apps/v1"
    16  	coordinationv1 "k8s.io/api/coordination/v1"
    17  	corev1 "k8s.io/api/core/v1"
    18  	rbac "k8s.io/api/rbac/v1"
    19  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    20  	"k8s.io/client-go/tools/clientcmd"
    21  )
    22  
    23  func newUnlinkCommand() *cobra.Command {
    24  	opts, err := newLinkOptionsWithDefault()
    25  	if err != nil {
    26  		fmt.Fprintln(os.Stderr, err)
    27  		os.Exit(1)
    28  	}
    29  
    30  	cmd := &cobra.Command{
    31  		Use:   "unlink",
    32  		Short: "Outputs link resources for deletion",
    33  		Args:  cobra.NoArgs,
    34  		RunE: func(cmd *cobra.Command, args []string) error {
    35  
    36  			if opts.clusterName == "" {
    37  				return errors.New("You need to specify cluster name")
    38  			}
    39  
    40  			rules := clientcmd.NewDefaultClientConfigLoadingRules()
    41  			rules.ExplicitPath = kubeconfigPath
    42  			loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, &clientcmd.ConfigOverrides{})
    43  			config, err := loader.RawConfig()
    44  			if err != nil {
    45  				return err
    46  			}
    47  
    48  			if kubeContext != "" {
    49  				config.CurrentContext = kubeContext
    50  			}
    51  
    52  			k, err := k8s.NewAPI(kubeconfigPath, config.CurrentContext, impersonate, impersonateGroup, 0)
    53  			if err != nil {
    54  				return err
    55  			}
    56  
    57  			l, err := mc.GetLink(cmd.Context(), k.DynamicClient, opts.namespace, opts.clusterName)
    58  			if err != nil {
    59  				return err
    60  			}
    61  
    62  			secret := resource.NewNamespaced(corev1.SchemeGroupVersion.String(), "Secret", fmt.Sprintf("cluster-credentials-%s", opts.clusterName), opts.namespace)
    63  			link := resource.NewNamespaced(k8s.LinkAPIGroupVersion, "Link", opts.clusterName, opts.namespace)
    64  			clusterRole := resource.New(rbac.SchemeGroupVersion.String(), "ClusterRole", fmt.Sprintf("linkerd-service-mirror-access-local-resources-%s", opts.clusterName))
    65  			clusterRoleBinding := resource.New(rbac.SchemeGroupVersion.String(), "ClusterRoleBinding", fmt.Sprintf("linkerd-service-mirror-access-local-resources-%s", opts.clusterName))
    66  			role := resource.NewNamespaced(rbac.SchemeGroupVersion.String(), "Role", fmt.Sprintf("linkerd-service-mirror-read-remote-creds-%s", opts.clusterName), opts.namespace)
    67  			roleBinding := resource.NewNamespaced(rbac.SchemeGroupVersion.String(), "RoleBinding", fmt.Sprintf("linkerd-service-mirror-read-remote-creds-%s", opts.clusterName), opts.namespace)
    68  			serviceAccount := resource.NewNamespaced(corev1.SchemeGroupVersion.String(), "ServiceAccount", fmt.Sprintf("linkerd-service-mirror-%s", opts.clusterName), opts.namespace)
    69  			serviceMirror := resource.NewNamespaced(appsv1.SchemeGroupVersion.String(), "Deployment", fmt.Sprintf("linkerd-service-mirror-%s", opts.clusterName), opts.namespace)
    70  			lease := resource.NewNamespaced(coordinationv1.SchemeGroupVersion.String(), "Lease", fmt.Sprintf("service-mirror-write-%s", opts.clusterName), opts.namespace)
    71  
    72  			resources := []resource.Kubernetes{
    73  				secret, link, clusterRole, clusterRoleBinding,
    74  				role, roleBinding, serviceAccount, serviceMirror, lease,
    75  			}
    76  
    77  			if l.ProbeSpec.Path != "" {
    78  				gatewayMirror := resource.NewNamespaced(corev1.SchemeGroupVersion.String(), "Service", fmt.Sprintf("probe-gateway-%s", opts.clusterName), opts.namespace)
    79  				resources = append(resources, gatewayMirror)
    80  			}
    81  
    82  			selector := fmt.Sprintf("%s=%s,%s=%s",
    83  				k8s.MirroredResourceLabel, "true",
    84  				k8s.RemoteClusterNameLabel, opts.clusterName,
    85  			)
    86  			svcList, err := k.CoreV1().Services(metav1.NamespaceAll).List(cmd.Context(), metav1.ListOptions{LabelSelector: selector})
    87  			if err != nil {
    88  				return err
    89  			}
    90  			for _, svc := range svcList.Items {
    91  				resources = append(resources,
    92  					resource.NewNamespaced(corev1.SchemeGroupVersion.String(), "Service", svc.Name, svc.Namespace),
    93  				)
    94  			}
    95  
    96  			selector = fmt.Sprintf("%s=%s", clusterNameLabel, opts.clusterName)
    97  			destinationCredentials, err := k.CoreV1().Secrets(controlPlaneNamespace).List(cmd.Context(), metav1.ListOptions{LabelSelector: selector})
    98  			if err != nil {
    99  				return err
   100  			}
   101  			for _, secret := range destinationCredentials.Items {
   102  				resources = append(resources,
   103  					resource.NewNamespaced(corev1.SchemeGroupVersion.String(), "Secret", secret.Name, secret.Namespace),
   104  				)
   105  			}
   106  
   107  			for _, r := range resources {
   108  				if err := r.RenderResource(stdout); err != nil {
   109  					log.Errorf("failed to render resource %s: %s", r.Name, err)
   110  				}
   111  			}
   112  
   113  			return nil
   114  		},
   115  	}
   116  
   117  	cmd.Flags().StringVar(&opts.namespace, "namespace", defaultMulticlusterNamespace, "The namespace for the service account")
   118  	cmd.Flags().StringVar(&opts.clusterName, "cluster-name", "", "Cluster name")
   119  
   120  	pkgcmd.ConfigureNamespaceFlagCompletion(
   121  		cmd, []string{"namespace"},
   122  		kubeconfigPath, impersonate, impersonateGroup, kubeContext)
   123  
   124  	configureClusterNameFlagCompletion(cmd)
   125  	return cmd
   126  }
   127  
   128  func configureClusterNameFlagCompletion(cmd *cobra.Command) {
   129  	cmd.RegisterFlagCompletionFunc("cluster-name",
   130  		func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
   131  			k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
   132  			if err != nil {
   133  				return nil, cobra.ShellCompDirectiveError
   134  			}
   135  
   136  			cc := k8s.NewCommandCompletion(k8sAPI, corev1.NamespaceAll)
   137  			results, err := cc.Complete([]string{strings.ToLower(k8s.LinkKind)}, toComplete)
   138  			if err != nil {
   139  				return nil, cobra.ShellCompDirectiveError
   140  			}
   141  
   142  			return results, cobra.ShellCompDirectiveDefault
   143  		})
   144  }
   145  

View as plain text