diff --git a/cmd/cli/util.go b/cmd/cli/util.go index ffd9df814e..e562846be5 100644 --- a/cmd/cli/util.go +++ b/cmd/cli/util.go @@ -12,7 +12,8 @@ import ( mapset "github.com/deckarep/golang-set" "github.com/pkg/errors" - v1 "k8s.io/api/apps/v1" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" @@ -113,25 +114,18 @@ func getMeshInfoList(restConfig *rest.Config, clientSet kubernetes.Interface) ([ return meshInfoList, nil } -// getNamespacePods returns a map of controller pods -func getNamespacePods(clientSet kubernetes.Interface, m string, ns string) map[string][]string { - x := make(map[string][]string) - +// GetOSMControllerPods returns a list of osm-controller pods in the namespace +func GetOSMControllerPods(clientSet kubernetes.Interface, ns string) *corev1.PodList { labelSelector := metav1.LabelSelector{MatchLabels: map[string]string{"app": constants.OSMControllerName}} listOptions := metav1.ListOptions{ LabelSelector: labels.Set(labelSelector.MatchLabels).String(), } - pods, _ := clientSet.CoreV1().Pods(ns).List(context.TODO(), listOptions) - - for pno := 0; pno < len(pods.Items); pno++ { - x["Pods"] = append(x["Pods"], pods.Items[pno].GetName()) - } - - return x + podList, _ := clientSet.CoreV1().Pods(ns).List(context.TODO(), listOptions) + return podList } // getControllerDeployments returns a list of Deployments corresponding to osm-controller -func getControllerDeployments(clientSet kubernetes.Interface) (*v1.DeploymentList, error) { +func getControllerDeployments(clientSet kubernetes.Interface) (*appsv1.DeploymentList, error) { deploymentsClient := clientSet.AppsV1().Deployments("") // Get deployments from all namespaces labelSelector := metav1.LabelSelector{MatchLabels: map[string]string{"app": constants.OSMControllerName}} listOptions := metav1.ListOptions{ @@ -176,11 +170,13 @@ func getSupportedSmiInfoForMeshList(meshInfoList []meshInfo, clientSet kubernete var meshSmiInfoList []meshSmiInfo for _, mesh := range meshInfoList { - meshControllerPods := getNamespacePods(clientSet, mesh.name, mesh.namespace) + meshControllerPods := GetOSMControllerPods(clientSet, mesh.namespace) meshSmiSupportedVersions := []string{"Unknown"} - if pods, ok := meshControllerPods["Pods"]; ok && len(pods) > 0 { - smiMap, err := getSupportedSmiForControllerPod(meshControllerPods["Pods"][0], mesh.namespace, config, clientSet, localPort) + if len(meshControllerPods.Items) > 0 { + // for listing mesh information, checking info using the first osm-controller pod should suffice + controllerPod := meshControllerPods.Items[0] + smiMap, err := getSupportedSmiForControllerPod(controllerPod.Name, mesh.namespace, config, clientSet, localPort) if err == nil { meshSmiSupportedVersions = []string{} for smi, version := range smiMap { diff --git a/cmd/cli/util_test.go b/cmd/cli/util_test.go index 0ba977fc02..2bc7802c4c 100644 --- a/cmd/cli/util_test.go +++ b/cmd/cli/util_test.go @@ -9,8 +9,11 @@ import ( . "github.com/onsi/gomega" tassert "github.com/stretchr/testify/assert" v1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" "github.com/openservicemesh/osm/pkg/constants" ) @@ -157,6 +160,95 @@ var _ = Describe("Test getting pretty printed output of smi info of a list of me }) }) +func TestGetNamespaceOsmControllerPods(t *testing.T) { + testNamespace := "osm-namespace" + + tests := []struct { + testName string + pods []*corev1.Pod + expectedPodNames []string + }{ + { + testName: "multiple pods (osm-controller pods and other pods) in multiple namespaces", + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "osm-controller-pod-1", + Namespace: testNamespace, + Labels: map[string]string{ + "app": constants.OSMControllerName, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "osm-controller-pod-2", + Namespace: testNamespace, + Labels: map[string]string{ + "app": constants.OSMControllerName, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "some-other-osm-controller-pod", + Namespace: "some-other-namespace", + Labels: map[string]string{ + "app": constants.OSMControllerName, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "application-pod-1", + Namespace: testNamespace, + Labels: map[string]string{ + "app": "myapp", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "application-pod-2", + Namespace: "some-other-namespace", + Labels: map[string]string{ + "app": "myapp", + }, + }, + }, + }, + expectedPodNames: []string{ + "osm-controller-pod-1", + "osm-controller-pod-2", + }, + }, + { + testName: "no pods", + pods: []*corev1.Pod{}, + expectedPodNames: []string{}, + }, + } + + for _, test := range tests { + t.Run(test.testName, func(t *testing.T) { + assert := tassert.New(t) + + objs := make([]runtime.Object, len(test.pods)) + for i := range test.pods { + objs[i] = test.pods[i] + } + + fakeClientSet := fake.NewSimpleClientset(objs...) + podList := GetOSMControllerPods(fakeClientSet, testNamespace) + actualPodNames := make([]string, len(podList.Items)) + for i, pod := range podList.Items { + actualPodNames[i] = pod.Name + } + assert.ElementsMatch(test.expectedPodNames, actualPodNames) + }) + } +} + // helper function for tests that adds deployment to the clientset func addDeployment(fakeClientSet kubernetes.Interface, depName string, meshName string, namespace string, osmVersion string, isMesh bool) (*v1.Deployment, error) { dep := createDeployment(depName, meshName, osmVersion, isMesh)