...

Source file src/github.com/linkerd/linkerd2/cli/cmd/uninstall.go

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

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  
     8  	pkgCmd "github.com/linkerd/linkerd2/pkg/cmd"
     9  	"github.com/linkerd/linkerd2/pkg/k8s"
    10  	"github.com/spf13/cobra"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  )
    13  
    14  const (
    15  	yamlSep = "---\n"
    16  )
    17  
    18  func newCmdUninstall() *cobra.Command {
    19  	var force bool
    20  	cmd := &cobra.Command{
    21  		Use:   "uninstall",
    22  		Args:  cobra.NoArgs,
    23  		Short: "Output Kubernetes resources to uninstall Linkerd control plane",
    24  		Long: `Output Kubernetes resources to uninstall Linkerd control plane.
    25  
    26  This command provides all Kubernetes namespace-scoped and cluster-scoped resources (e.g services, deployments, RBACs, etc.) necessary to uninstall Linkerd control plane.`,
    27  		Example: ` linkerd uninstall | kubectl delete -f -`,
    28  		RunE: func(cmd *cobra.Command, args []string) error {
    29  
    30  			k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
    31  			if err != nil {
    32  				return err
    33  			}
    34  
    35  			if !force {
    36  
    37  				var fail bool
    38  				// Retrieve any installed extensions
    39  				extensionNamespaces, err := k8sAPI.GetAllNamespacesWithExtensionLabel(cmd.Context())
    40  				if err != nil {
    41  					return err
    42  				}
    43  
    44  				// map of the namespace and the extension name
    45  				// Namespace is used as key so as to support custom namespace installs
    46  				extensions := make(map[string]string)
    47  				if len(extensionNamespaces) > 0 {
    48  					for _, extension := range extensionNamespaces {
    49  						extensions[extension.Name] = extension.Labels[k8s.LinkerdExtensionLabel]
    50  					}
    51  
    52  					// Retrieve all the extension names
    53  					extensionNames := make([]string, 0, len(extensions))
    54  					for _, v := range extensions {
    55  						extensionNames = append(extensionNames, fmt.Sprintf("* %s", v))
    56  					}
    57  
    58  					fmt.Fprintf(os.Stderr, "Please uninstall the following extensions before uninstalling the control-plane:\n\t%s\n", strings.Join(extensionNames, "\n\t"))
    59  					fail = true
    60  				}
    61  
    62  				podList, err := k8sAPI.CoreV1().Pods("").List(cmd.Context(), metav1.ListOptions{LabelSelector: k8s.ControllerNSLabel})
    63  				if err != nil {
    64  					return err
    65  				}
    66  
    67  				var injectedPods []string
    68  				for _, pod := range podList.Items {
    69  					// skip core control-plane namespace, and extension namespaces
    70  					if pod.Namespace != controlPlaneNamespace && extensions[pod.Namespace] == "" {
    71  						injectedPods = append(injectedPods, fmt.Sprintf("* %s", pod.Name))
    72  					}
    73  				}
    74  
    75  				if len(injectedPods) > 0 {
    76  					fmt.Fprintf(os.Stderr, "Please uninject the following pods before uninstalling the control-plane:\n\t%s\n", strings.Join(injectedPods, "\n\t"))
    77  					fail = true
    78  				}
    79  
    80  				if fail {
    81  					os.Exit(1)
    82  				}
    83  			}
    84  
    85  			selector, err := pkgCmd.GetLabelSelector(k8s.ControllerNSLabel)
    86  			if err != nil {
    87  				return err
    88  			}
    89  
    90  			err = pkgCmd.Uninstall(cmd.Context(), k8sAPI, selector)
    91  			if err != nil {
    92  				fmt.Fprintln(os.Stderr, err)
    93  			}
    94  
    95  			return nil
    96  		},
    97  	}
    98  
    99  	cmd.Flags().BoolVarP(&force, "force", "f", force, "Force uninstall even if there exist non-control-plane injected pods")
   100  	return cmd
   101  }
   102  

View as plain text