diff --git a/cli/cmd/get.go b/cli/cmd/get.go deleted file mode 100644 index 976a3fbf07eb9..0000000000000 --- 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 46b401dedb43a..0000000000000 --- 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 b401b33643d18..9dcb84bed94a1 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 aa2a04f884901..0000000000000 --- 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 c63482630b971..0000000000000 --- 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 79fcde82e4b79..0000000000000 --- 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