cli: make `linkerd uninstall` fail when injected pods are present (#5642)

* cli: make `linkerd uninstall` fail when injected pods are present

Fixes #5622

This PR updates the `linkerd uninstall` cmd to check if there
are any injected pods and fails if there are any. This also
provides `--force` flag to skip this check.

pods from namespaces with prefix `linkerd` are skipped
so as to not error out for control-plane and extension
pods.

Signed-off-by: Tarun Pothulapati <tarunpothulapati@outlook.com>
This commit is contained in:
Tarun Pothulapati 2021-02-03 12:31:30 +05:30 committed by GitHub
parent 10411d02bb
commit b521091ca7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 16 deletions

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"os"
"strings"
"github.com/linkerd/linkerd2/pkg/k8s"
"github.com/linkerd/linkerd2/pkg/k8s/resource"
@ -16,6 +17,7 @@ const (
)
func newCmdUninstall() *cobra.Command {
var force bool
cmd := &cobra.Command{
Use: "uninstall",
Args: cobra.NoArgs,
@ -25,18 +27,41 @@ func newCmdUninstall() *cobra.Command {
This command provides all Kubernetes namespace-scoped and cluster-scoped resources (e.g services, deployments, RBACs, etc.) necessary to uninstall Linkerd control plane.`,
Example: ` linkerd uninstall | kubectl delete -f -`,
RunE: func(cmd *cobra.Command, args []string) error {
return uninstallRunE(cmd.Context())
k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
if err != nil {
return err
}
if !force {
podList, err := k8sAPI.CoreV1().Pods("").List(cmd.Context(), metav1.ListOptions{LabelSelector: k8s.ControllerNSLabel})
if err != nil {
return err
}
var injectedPods []string
for _, pod := range podList.Items {
// skip core control-plane namespace
if pod.Namespace != controlPlaneNamespace {
injectedPods = append(injectedPods, fmt.Sprintf("* %s", pod.Name))
}
}
if len(injectedPods) > 0 {
fmt.Fprintln(os.Stderr, fmt.Sprintf("Please uninject the following pods before uninstalling the control-plane:\n\t%s", strings.Join(injectedPods, "\n\t")))
os.Exit(1)
}
}
return uninstallRunE(cmd.Context(), k8sAPI)
},
}
cmd.Flags().BoolVarP(&force, "force", "f", force, "Force uninstall even if there exist non-control-plane injected pods")
return cmd
}
func uninstallRunE(ctx context.Context) error {
k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
if err != nil {
return err
}
func uninstallRunE(ctx context.Context, k8sAPI *k8s.KubernetesAPI) error {
resources, err := resource.FetchKubernetesResources(ctx, k8sAPI,
metav1.ListOptions{LabelSelector: k8s.ControllerNSLabel},

View File

@ -91,8 +91,25 @@ func TestResourcesPostInstall(t *testing.T) {
}
func TestUninstall(t *testing.T) {
args := []string{"uninstall"}
out, err := TestHelper.LinkerdRun(args...)
var (
vizCmd = []string{"viz", "uninstall"}
)
// Uninstall Linkerd Viz Extension
out, err := TestHelper.LinkerdRun(vizCmd...)
if err != nil {
testutil.AnnotatedFatal(t, "'linkerd viz uninstall' command failed", err)
}
args := []string{"delete", "-f", "-"}
out, err = TestHelper.Kubectl(out, args...)
if err != nil {
testutil.AnnotatedFatalf(t, "'kubectl delete' command failed",
"'kubectl delete' command failed\n%s", out)
}
args = []string{"uninstall"}
out, err = TestHelper.LinkerdRun(args...)
if err != nil {
testutil.AnnotatedFatal(t, "'linkerd install' command failed", err)
}
@ -100,8 +117,8 @@ func TestUninstall(t *testing.T) {
args = []string{"delete", "-f", "-"}
out, err = TestHelper.Kubectl(out, args...)
if err != nil {
testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
"'kubectl apply' command failed\n%s", out)
testutil.AnnotatedFatalf(t, "'kubectl delete' command failed",
"'kubectl delete' command failed\n%s", out)
}
}

View File

@ -34,13 +34,8 @@ func uninstallRunE(ctx context.Context) error {
return err
}
vizNs, err := k8sAPI.GetNamespaceWithExtensionLabel(ctx, ExtensionName)
if err != nil {
return err
}
resources, err := resource.FetchKubernetesResources(ctx, k8sAPI,
metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", k8s.LinkerdExtensionLabel, vizNs.Name)},
metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", k8s.LinkerdExtensionLabel, ExtensionName)},
)
if err != nil {
return err