mirror of https://github.com/linkerd/linkerd2.git
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:
parent
10411d02bb
commit
b521091ca7
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/linkerd/linkerd2/pkg/k8s"
|
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||||
"github.com/linkerd/linkerd2/pkg/k8s/resource"
|
"github.com/linkerd/linkerd2/pkg/k8s/resource"
|
||||||
|
@ -16,6 +17,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func newCmdUninstall() *cobra.Command {
|
func newCmdUninstall() *cobra.Command {
|
||||||
|
var force bool
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "uninstall",
|
Use: "uninstall",
|
||||||
Args: cobra.NoArgs,
|
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.`,
|
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 -`,
|
Example: ` linkerd uninstall | kubectl delete -f -`,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
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
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func uninstallRunE(ctx context.Context) error {
|
func uninstallRunE(ctx context.Context, k8sAPI *k8s.KubernetesAPI) error {
|
||||||
k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resources, err := resource.FetchKubernetesResources(ctx, k8sAPI,
|
resources, err := resource.FetchKubernetesResources(ctx, k8sAPI,
|
||||||
metav1.ListOptions{LabelSelector: k8s.ControllerNSLabel},
|
metav1.ListOptions{LabelSelector: k8s.ControllerNSLabel},
|
||||||
|
|
|
@ -91,8 +91,25 @@ func TestResourcesPostInstall(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUninstall(t *testing.T) {
|
func TestUninstall(t *testing.T) {
|
||||||
args := []string{"uninstall"}
|
var (
|
||||||
out, err := TestHelper.LinkerdRun(args...)
|
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 {
|
if err != nil {
|
||||||
testutil.AnnotatedFatal(t, "'linkerd install' command failed", err)
|
testutil.AnnotatedFatal(t, "'linkerd install' command failed", err)
|
||||||
}
|
}
|
||||||
|
@ -100,8 +117,8 @@ func TestUninstall(t *testing.T) {
|
||||||
args = []string{"delete", "-f", "-"}
|
args = []string{"delete", "-f", "-"}
|
||||||
out, err = TestHelper.Kubectl(out, args...)
|
out, err = TestHelper.Kubectl(out, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
|
testutil.AnnotatedFatalf(t, "'kubectl delete' command failed",
|
||||||
"'kubectl apply' command failed\n%s", out)
|
"'kubectl delete' command failed\n%s", out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,13 +34,8 @@ func uninstallRunE(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vizNs, err := k8sAPI.GetNamespaceWithExtensionLabel(ctx, ExtensionName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
resources, err := resource.FetchKubernetesResources(ctx, k8sAPI,
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in New Issue