mirror of https://github.com/linkerd/linkerd2.git
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 <tarunpothulapati@outlook.com>
This commit is contained in:
parent
4ffb41ab44
commit
e4c354985c
102
cli/cmd/get.go
102
cli/cmd/get.go
|
@ -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
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
})
|
||||
}
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue