From e4c354985c9900abac4aa0ebd0248fe25d5be721 Mon Sep 17 00:00:00 2001 From: Tarun Pothulapati Date: Fri, 13 Nov 2020 00:49:46 +0530 Subject: [PATCH] cli: Remove get cmd and relevant tests (#5202) Fixes #5190 `linkerd get` is not used currently and works only for pods. This can be removed instead as per the issue. This branch removes the command and also the associated unit and integration tests. Signed-off-by: Tarun Pothulapati --- cli/cmd/get.go | 102 --------- cli/cmd/get_test.go | 70 ------- cli/cmd/root.go | 1 - test/integration/get/get_test.go | 195 ------------------ .../not_to_be_injected_application.yaml | 47 ----- .../testdata/to_be_injected_application.yaml | 47 ----- 6 files changed, 462 deletions(-) delete mode 100644 cli/cmd/get.go delete mode 100644 cli/cmd/get_test.go delete mode 100644 test/integration/get/get_test.go delete mode 100644 test/integration/get/testdata/not_to_be_injected_application.yaml delete mode 100644 test/integration/get/testdata/to_be_injected_application.yaml diff --git a/cli/cmd/get.go b/cli/cmd/get.go deleted file mode 100644 index 976a3fbf0..000000000 --- a/cli/cmd/get.go +++ /dev/null @@ -1,102 +0,0 @@ -package cmd - -import ( - "context" - "errors" - "fmt" - "os" - - pb "github.com/linkerd/linkerd2/controller/gen/public" - "github.com/linkerd/linkerd2/pkg/k8s" - "github.com/spf13/cobra" -) - -type getOptions struct { - namespace string - allNamespaces bool -} - -func newGetOptions() *getOptions { - return &getOptions{ - namespace: defaultNamespace, - allNamespaces: false, - } -} - -func newCmdGet() *cobra.Command { - options := newGetOptions() - - cmd := &cobra.Command{ - Use: "get [flags] pods", - Short: "Display one or many mesh resources", - Long: `Display one or many mesh resources. - -Only pod resources (aka pods, po) are supported.`, - Example: ` # get all pods - linkerd get pods - - # get pods from namespace linkerd - linkerd get pods --namespace linkerd`, - Args: cobra.ExactArgs(1), - ValidArgs: []string{k8s.Pod}, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 { - return errors.New("please specify a resource type") - } - - if len(args) > 1 { - return errors.New("please specify only one resource type") - } - - friendlyName := args[0] - resourceType, err := k8s.CanonicalResourceNameFromFriendlyName(friendlyName) - - if err != nil || resourceType != k8s.Pod { - return fmt.Errorf("invalid resource type %s, valid types: %s", friendlyName, k8s.Pod) - } - - podNames, err := getPods(checkPublicAPIClientOrExit(), options) - if err != nil { - return err - } - - if len(podNames) == 0 { - fmt.Fprintln(os.Stderr, "No resources found.") - os.Exit(0) - } - - for _, podName := range podNames { - fmt.Println(podName) - } - - return nil - }, - } - - cmd.PersistentFlags().StringVarP(&options.namespace, "namespace", "n", options.namespace, "Namespace of pods") - cmd.PersistentFlags().BoolVarP(&options.allNamespaces, "all-namespaces", "A", options.allNamespaces, "If present, returns pods across all namespaces, ignoring the \"--namespace\" flag") - return cmd -} - -func getPods(apiClient pb.ApiClient, options *getOptions) ([]string, error) { - req := &pb.ListPodsRequest{} - if !options.allNamespaces { - req.Selector = &pb.ResourceSelection{ - Resource: &pb.Resource{ - Namespace: options.namespace, - }, - } - } - - resp, err := apiClient.ListPods(context.Background(), req) - if err != nil { - return nil, err - } - - names := make([]string, 0) - for _, pod := range resp.GetPods() { - names = append(names, pod.Name) - } - - return names, nil -} diff --git a/cli/cmd/get_test.go b/cli/cmd/get_test.go deleted file mode 100644 index 46b401ded..000000000 --- a/cli/cmd/get_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package cmd - -import ( - "errors" - "testing" - - "github.com/linkerd/linkerd2/controller/api/public" - pb "github.com/linkerd/linkerd2/controller/gen/public" -) - -func TestGetPods(t *testing.T) { - t.Run("Returns names of existing pods if everything went ok", func(t *testing.T) { - mockClient := &public.MockAPIClient{} - - pods := []*pb.Pod{ - {Name: "pod-a"}, - {Name: "pod-b"}, - {Name: "pod-c"}, - } - - expectedPodNames := []string{ - "pod-a", - "pod-b", - "pod-c", - } - response := &pb.ListPodsResponse{ - Pods: pods, - } - - mockClient.ListPodsResponseToReturn = response - actualPodNames, err := getPods(mockClient, newGetOptions()) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - for i, actualName := range actualPodNames { - expectedName := expectedPodNames[i] - if expectedName != actualName { - t.Fatalf("Expected %dth element on %v to be [%s], but was [%s]", i, actualPodNames, expectedName, actualName) - } - } - }) - - t.Run("Returns empty list if no pods found", func(t *testing.T) { - mockClient := &public.MockAPIClient{} - - mockClient.ListPodsResponseToReturn = &pb.ListPodsResponse{ - Pods: []*pb.Pod{}, - } - - actualPodNames, err := getPods(mockClient, newGetOptions()) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - if len(actualPodNames) != 0 { - t.Fatalf("Expecting no pod names, got %v", actualPodNames) - } - }) - - t.Run("Returns error if can't find pods in API", func(t *testing.T) { - mockClient := &public.MockAPIClient{} - mockClient.ErrorToReturn = errors.New("expected") - - _, err := getPods(mockClient, newGetOptions()) - if err == nil { - t.Fatalf("Expecting error, got noting") - } - }) -} diff --git a/cli/cmd/root.go b/cli/cmd/root.go index b401b3364..9dcb84bed 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -113,7 +113,6 @@ func init() { RootCmd.AddCommand(newCmdDoc()) RootCmd.AddCommand(newCmdEdges()) RootCmd.AddCommand(newCmdEndpoints()) - RootCmd.AddCommand(newCmdGet()) RootCmd.AddCommand(newCmdInject()) RootCmd.AddCommand(newCmdInstall()) RootCmd.AddCommand(newCmdInstallCNIPlugin()) diff --git a/test/integration/get/get_test.go b/test/integration/get/get_test.go deleted file mode 100644 index aa2a04f88..000000000 --- a/test/integration/get/get_test.go +++ /dev/null @@ -1,195 +0,0 @@ -package get - -import ( - "context" - "fmt" - "io/ioutil" - "os" - "reflect" - "regexp" - "sort" - "strings" - "testing" - - "github.com/linkerd/linkerd2/testutil" -) - -////////////////////// -/// TEST SETUP /// -////////////////////// - -var TestHelper *testutil.TestHelper - -func TestMain(m *testing.M) { - TestHelper = testutil.NewTestHelper() - os.Exit(testutil.Run(m, TestHelper)) -} - -var ( - deployReplicas = map[string]int{ - "cli-get-test-d1": 2, - "cli-get-test-d2": 1, - "cli-get-test-not-injected-d1": 2, - "cli-get-test-not-injected-d2": 1, - } - - linkerdPods = map[string]int{ - "linkerd-controller": 1, - "linkerd-destination": 1, - "linkerd-grafana": 1, - "linkerd-identity": 1, - "linkerd-prometheus": 1, - "linkerd-proxy-injector": 1, - "linkerd-sp-validator": 1, - "linkerd-tap": 1, - "linkerd-web": 1, - } -) - -////////////////////// -/// TEST EXECUTION /// -////////////////////// - -func TestCliGet(t *testing.T) { - out, err := TestHelper.LinkerdRun("inject", "testdata/to_be_injected_application.yaml") - if err != nil { - testutil.AnnotatedFatal(t, "unexpected error", err) - } - - ctx := context.Background() - TestHelper.WithDataPlaneNamespace(ctx, "get-test", map[string]string{}, t, func(t *testing.T, prefixedNs string) { - - out, err = TestHelper.KubectlApply(out, prefixedNs) - if err != nil { - testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v output:\n%s", err, out) - } - - bytes, err := ioutil.ReadFile("testdata/not_to_be_injected_application.yaml") - if err != nil { - testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v", err) - } - - out, err = TestHelper.KubectlApply(string(bytes), prefixedNs) - if err != nil { - testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v output:\n%s", err, out) - } - - // wait for pods to start - for deploy, replicas := range deployReplicas { - if err := TestHelper.CheckPods(ctx, prefixedNs, deploy, replicas); err != nil { - if rce, ok := err.(*testutil.RestartCountError); ok { - testutil.AnnotatedWarn(t, "CheckPods timed-out", rce) - } else { - testutil.AnnotatedError(t, "CheckPods timed-out", err) - } - } - } - - t.Run("get pods from --all-namespaces", func(t *testing.T) { - out, err = TestHelper.LinkerdRun("get", "pods", "--all-namespaces") - if err != nil { - testutil.AnnotatedFatal(t, "unexpected error", err) - } - - err := checkPodOutput(out, deployReplicas, "", prefixedNs) - if err != nil { - testutil.AnnotatedFatalf(t, "pod output check failed", "pod output check failed:\n%s\nCommand output:\n%s", err, out) - } - }) - - t.Run("get pods from the linkerd namespace", func(t *testing.T) { - out, err = TestHelper.LinkerdRun("get", "pods", "-n", TestHelper.GetLinkerdNamespace()) - if err != nil { - testutil.AnnotatedFatal(t, "unexpected error", err) - } - - err := checkPodOutput(out, linkerdPods, "linkerd-heartbeat", TestHelper.GetLinkerdNamespace()) - if err != nil { - testutil.AnnotatedFatalf(t, "pod output check failed", "pod output check failed:\n%s\nCommand output:\n%s", err, out) - } - }) - - t.Run("get pods from the default namespace of current context", func(t *testing.T) { - out, err := TestHelper.Kubectl("", "config", "set-context", "--namespace="+TestHelper.GetLinkerdNamespace(), "--current") - if err != nil { - testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v output:\n%s", err, out) - } - - out, err = TestHelper.LinkerdRun("get", "pods") - if err != nil { - testutil.AnnotatedFatal(t, "unexpected error", err) - } - - err = checkPodOutput(out, linkerdPods, "linkerd-heartbeat", TestHelper.GetLinkerdNamespace()) - if err != nil { - testutil.AnnotatedFatalf(t, "pod output check failed", "pod output check failed:\n%s\nCommand output:\n%s", err, out) - } - - out, err = TestHelper.Kubectl("", "config", "set-context", "--namespace=default", "--current") - if err != nil { - testutil.AnnotatedFatalf(t, "unexpected error", "unexpected error: %v output:\n%s", err, out) - } - }) - }) -} - -func checkPodOutput(cmdOutput string, expectedPodCounts map[string]int, optionalPod string, namespace string) error { - expectedPods := []string{} - for podName, replicas := range expectedPodCounts { - for i := 0; i < replicas; i++ { - expectedPods = append(expectedPods, podName) - } - } - - lines := strings.Split(cmdOutput, "\n") - if len(lines) == 0 { - return fmt.Errorf("Expecting linkerd get pods to return something, got nothing") - } - - var actualPods []string - for _, line := range lines { - sanitizedLine := strings.TrimSpace(line) - if sanitizedLine == "" { - continue - } - - ns, pod, err := TestHelper.ParseNamespacedResource(sanitizedLine) - if err != nil { - return fmt.Errorf("Unexpected error: %v", err) - } - - if ns == namespace { - podPrefix, err := parsePodPrefix(pod) - - if err != nil { - return fmt.Errorf("Unexpected error: %v", err) - } - actualPods = append(actualPods, podPrefix) - } - } - - sort.Strings(expectedPods) - sort.Strings(actualPods) - if !reflect.DeepEqual(expectedPods, actualPods) { - if optionalPod == "" { - return fmt.Errorf("Expected linkerd get to return:\n%v\nBut got:\n%v", expectedPods, actualPods) - } - - expectedPlusOptionalPods := append(expectedPods, optionalPod) - sort.Strings(expectedPlusOptionalPods) - if !reflect.DeepEqual(expectedPlusOptionalPods, actualPods) { - return fmt.Errorf("Expected linkerd get to return:\n%v\nor:\n%v\nBut got:\n%v", expectedPods, expectedPlusOptionalPods, actualPods) - } - } - - return nil -} - -func parsePodPrefix(pod string) (string, error) { - r := regexp.MustCompile("^(.+)-.+-.+$") - matches := r.FindAllStringSubmatch(pod, 1) - if len(matches) == 0 { - return "", fmt.Errorf("string [%s] didn't contain expected format for pod name, extracted: %v", pod, matches) - } - return matches[0][1], nil -} diff --git a/test/integration/get/testdata/not_to_be_injected_application.yaml b/test/integration/get/testdata/not_to_be_injected_application.yaml deleted file mode 100644 index c63482630..000000000 --- a/test/integration/get/testdata/not_to_be_injected_application.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cli-get-test-not-injected-d1 -spec: - replicas: 2 - selector: - matchLabels: - app: cli-get-test-not-injected-d1 - template: - metadata: - labels: - app: cli-get-test-not-injected-d1 - spec: - containers: - - name: http-to-grpc - image: buoyantio/bb:v0.0.6 - args: ["terminus", "--grpc-server-port", "9090", "--response-text", "BANANA"] - ports: - - containerPort: 9090 - - name: http-to-grpc-2 - image: buoyantio/bb:v0.0.6 - args: ["terminus", "--grpc-server-port", "90", "--response-text", "BANANA"] - ports: - - containerPort: 90 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cli-get-test-not-injected-d2 -spec: - replicas: 1 - selector: - matchLabels: - app: cli-get-test-not-injected-d2 - template: - metadata: - labels: - app: cli-get-test-not-injected-d2 - spec: - containers: - - name: http-to-grpc - image: buoyantio/bb:v0.0.6 - args: ["terminus", "--grpc-server-port", "90", "--response-text", "BANANA"] - ports: - - containerPort: 90 diff --git a/test/integration/get/testdata/to_be_injected_application.yaml b/test/integration/get/testdata/to_be_injected_application.yaml deleted file mode 100644 index 79fcde82e..000000000 --- a/test/integration/get/testdata/to_be_injected_application.yaml +++ /dev/null @@ -1,47 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cli-get-test-d1 -spec: - replicas: 2 - selector: - matchLabels: - app: cli-get-test-d1 - template: - metadata: - labels: - app: cli-get-test-d1 - spec: - containers: - - name: http-to-grpc - image: buoyantio/bb:v0.0.6 - args: ["terminus", "--grpc-server-port", "9090", "--response-text", "BANANA"] - ports: - - containerPort: 9090 - - name: http-to-grpc-2 - image: buoyantio/bb:v0.0.6 - args: ["terminus", "--grpc-server-port", "90", "--response-text", "BANANA"] - ports: - - containerPort: 90 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cli-get-test-d2 -spec: - replicas: 1 - selector: - matchLabels: - app: cli-get-test-d2 - template: - metadata: - labels: - app: cli-get-test-d2 - spec: - containers: - - name: http-to-grpc - image: buoyantio/bb:v0.0.6 - args: ["terminus", "--grpc-server-port", "90", "--response-text", "BANANA"] - ports: - - containerPort: 90