From 625b7d863527f6f497e3c3a505e084dc1bd17e7b Mon Sep 17 00:00:00 2001 From: nicmorales9 <153320946+nicmorales9@users.noreply.github.com> Date: Tue, 20 Feb 2024 14:57:51 +0000 Subject: [PATCH] add podName selection functions (#1944) * add podName selection functions --------- Co-authored-by: Nicole Morales --- kubectl-fdb/cmd/analyze_test.go | 50 ++-- kubectl-fdb/cmd/buggify_crash_loop_test.go | 18 +- kubectl-fdb/cmd/buggify_no_schedule_test.go | 18 +- kubectl-fdb/cmd/cordon_test.go | 40 +-- kubectl-fdb/cmd/exec_test.go | 6 +- kubectl-fdb/cmd/fix_coordinator_ips_test.go | 6 +- kubectl-fdb/cmd/k8s_client.go | 103 +++++++ kubectl-fdb/cmd/k8s_client_test.go | 289 ++++++++++++++++--- kubectl-fdb/cmd/remove_process_group_test.go | 50 ++-- kubectl-fdb/cmd/restart.go | 15 +- kubectl-fdb/cmd/suite_test.go | 6 +- 11 files changed, 453 insertions(+), 148 deletions(-) diff --git a/kubectl-fdb/cmd/analyze_test.go b/kubectl-fdb/cmd/analyze_test.go index b09c2b745..ada7f3476 100644 --- a/kubectl-fdb/cmd/analyze_test.go +++ b/kubectl-fdb/cmd/analyze_test.go @@ -66,12 +66,12 @@ func getPodList(clusterName string, namespace string, status corev1.PodStatus, d Items: []corev1.Pod{ { ObjectMeta: metav1.ObjectMeta{ - Name: "instance-1", + Name: "storage-1", Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStorage), fdbv1beta2.FDBClusterLabel: clusterName, - fdbv1beta2.FDBProcessGroupIDLabel: "instance-1", + fdbv1beta2.FDBProcessGroupIDLabel: "storage-1", }, DeletionTimestamp: deletionTimestamp, }, @@ -119,7 +119,7 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Cluster is fine", testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, @@ -138,7 +138,7 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Cluster is unavailable", testCase{ cluster: getCluster(clusterName, namespace, false, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, @@ -156,7 +156,7 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Cluster is unhealthy", testCase{ cluster: getCluster(clusterName, namespace, true, false, true, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, @@ -175,7 +175,7 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Cluster is not fully replicated", testCase{ cluster: getCluster(clusterName, namespace, true, true, false, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, @@ -193,7 +193,7 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Cluster is not reconciled", testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 0, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, @@ -212,7 +212,7 @@ var _ = Describe("[plugin] analyze cluster", func() { testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ { - ProcessGroupID: "instance-1", + ProcessGroupID: "storage-1", ProcessGroupConditions: []*fdbv1beta2.ProcessGroupCondition{ fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.MissingProcesses), }, @@ -221,7 +221,7 @@ var _ = Describe("[plugin] analyze cluster", func() { podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, }, nil), - ExpectedErrMsg: fmt.Sprintf("✖ ProcessGroup: instance-1 has the following condition: MissingProcesses since %s", time.Unix(time.Now().Unix(), 0).String()), + ExpectedErrMsg: fmt.Sprintf("✖ ProcessGroup: storage-1 has the following condition: MissingProcesses since %s", time.Unix(time.Now().Unix(), 0).String()), ExpectedStdoutMsg: `Checking cluster: test/test ✔ Cluster is available ✔ Cluster is fully replicated @@ -235,7 +235,7 @@ var _ = Describe("[plugin] analyze cluster", func() { testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ { - ProcessGroupID: "instance-1", + ProcessGroupID: "storage-1", ProcessGroupConditions: []*fdbv1beta2.ProcessGroupCondition{ fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.MissingProcesses), }, @@ -245,7 +245,7 @@ var _ = Describe("[plugin] analyze cluster", func() { podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, }, nil), - ExpectedErrMsg: "⚠ ProcessGroup: instance-1 is marked for removal, excluded state: false", + ExpectedErrMsg: "⚠ ProcessGroup: storage-1 is marked for removal, excluded state: false", ExpectedStdoutMsg: `Checking cluster: test/test ✔ Cluster is available ✔ Cluster is fully replicated @@ -259,12 +259,12 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Pod is in Pending phase", testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodPending, }, nil), - ExpectedErrMsg: "✖ Pod test/instance-1 has unexpected Phase Pending with Reason:", + ExpectedErrMsg: "✖ Pod test/storage-1 has unexpected Phase Pending with Reason:", ExpectedStdoutMsg: `Checking cluster: test/test ✔ Cluster is available ✔ Cluster is fully replicated @@ -277,7 +277,7 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Container is in terminated state", testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, @@ -294,7 +294,7 @@ var _ = Describe("[plugin] analyze cluster", func() { }, }, }, nil), - ExpectedErrMsg: "✖ Pod test/instance-1 has an unready container: foundationdb", + ExpectedErrMsg: "✖ Pod test/storage-1 has an unready container: foundationdb", ExpectedStdoutMsg: `Checking cluster: test/test ✔ Cluster is available ✔ Cluster is fully replicated @@ -307,7 +307,7 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Container is in ready state", testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, @@ -332,13 +332,13 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Pod is stuck in terminating", testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, ContainerStatuses: []corev1.ContainerStatus{}, }, &metav1.Time{Time: time.Now().Add(-1 * time.Hour)}), - ExpectedErrMsg: fmt.Sprintf("✖ Pod test/instance-1 has been stuck in terminating since %s", time.Unix(time.Now().Add(-1*time.Hour).Unix(), 0).String()), + ExpectedErrMsg: fmt.Sprintf("✖ Pod test/storage-1 has been stuck in terminating since %s", time.Unix(time.Now().Add(-1*time.Hour).Unix(), 0).String()), ExpectedStdoutMsg: `Checking cluster: test/test ✔ Cluster is available ✔ Cluster is fully replicated @@ -352,7 +352,7 @@ var _ = Describe("[plugin] analyze cluster", func() { testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ { - ProcessGroupID: "instance-1", + ProcessGroupID: "storage-1", RemovalTimestamp: &metav1.Time{Time: time.Now()}, ExclusionTimestamp: &metav1.Time{Time: time.Now()}, }, @@ -372,7 +372,7 @@ var _ = Describe("[plugin] analyze cluster", func() { }, }, }, &metav1.Time{Time: time.Now().Add(-1 * time.Hour)}), - ExpectedErrMsg: "⚠ ProcessGroup: instance-1 is marked for removal, excluded state: true", + ExpectedErrMsg: "⚠ ProcessGroup: storage-1 is marked for removal, excluded state: true", ExpectedStdoutMsg: `Checking cluster: test/test ✔ Cluster is available ✔ Cluster is fully replicated @@ -387,7 +387,7 @@ var _ = Describe("[plugin] analyze cluster", func() { testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ { - ProcessGroupID: "instance-1", + ProcessGroupID: "storage-1", RemovalTimestamp: &metav1.Time{Time: time.Now()}, ExclusionTimestamp: &metav1.Time{Time: time.Now()}, }, @@ -421,7 +421,7 @@ var _ = Describe("[plugin] analyze cluster", func() { Entry("Missing Pods", testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ - {ProcessGroupID: "instance-1"}, + {ProcessGroupID: "storage-1"}, }), podList: &corev1.PodList{}, ExpectedErrMsg: "✖ Found no Pods for this cluster", @@ -441,7 +441,7 @@ var _ = Describe("[plugin] analyze cluster", func() { podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, }, nil), - ExpectedErrMsg: "✖ Pod test/instance-1 with the ID instance-1 is not part of the cluster spec status", + ExpectedErrMsg: "✖ Pod test/storage-1 with the ID storage-1 is not part of the cluster spec status", ExpectedStdoutMsg: `Checking cluster: test/test ✔ Cluster is available ✔ Cluster is fully replicated @@ -455,7 +455,7 @@ var _ = Describe("[plugin] analyze cluster", func() { testCase{ cluster: getCluster(clusterName, namespace, true, true, true, 1, []*fdbv1beta2.ProcessGroupStatus{ { - ProcessGroupID: "instance-1", + ProcessGroupID: "storage-1", ProcessGroupConditions: []*fdbv1beta2.ProcessGroupCondition{ fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.MissingProcesses), fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.IncorrectPodSpec), @@ -465,7 +465,7 @@ var _ = Describe("[plugin] analyze cluster", func() { podList: getPodList(clusterName, namespace, corev1.PodStatus{ Phase: corev1.PodRunning, }, nil), - ExpectedErrMsg: fmt.Sprintf("✖ ProcessGroup: instance-1 has the following condition: MissingProcesses since %s\n⚠ Ignored 1 conditions", time.Unix(time.Now().Unix(), 0).String()), + ExpectedErrMsg: fmt.Sprintf("✖ ProcessGroup: storage-1 has the following condition: MissingProcesses since %s\n⚠ Ignored 1 conditions", time.Unix(time.Now().Unix(), 0).String()), ExpectedStdoutMsg: `Checking cluster: test/test ✔ Cluster is available ✔ Cluster is fully replicated diff --git a/kubectl-fdb/cmd/buggify_crash_loop_test.go b/kubectl-fdb/cmd/buggify_crash_loop_test.go index c24426bcd..7e92955dd 100644 --- a/kubectl-fdb/cmd/buggify_crash_loop_test.go +++ b/kubectl-fdb/cmd/buggify_crash_loop_test.go @@ -108,19 +108,19 @@ var _ = Describe("[plugin] buggify crash-loop process groups command", func() { ProcessGroupOpts: processGroupSelectionOptions{ ids: []string{ // the helper function to create pods for the k8s client uses "instance" not "storage" processGroup names - fmt.Sprintf("%s-instance-1", clusterName), - fmt.Sprintf("%s-instance-2", clusterName), - fmt.Sprintf("%s-instance-2", secondClusterName), + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage), }, clusterLabel: fdbv1beta2.FDBClusterLabel, }, ExpectedProcessGroupsInCrashLoop: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, secondClusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", secondClusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage)), }, }, }), @@ -133,8 +133,8 @@ var _ = Describe("[plugin] buggify crash-loop process groups command", func() { ExpectedProcessGroupsInCrashLoop: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { // the helper function to create pods for the k8s client uses "instance" not "storage" processGroup names - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }), @@ -147,7 +147,7 @@ var _ = Describe("[plugin] buggify crash-loop process groups command", func() { ExpectedProcessGroupsInCrashLoop: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { // the helper function to create pods for the k8s client uses "instance" not "storage" processGroup names - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }), diff --git a/kubectl-fdb/cmd/buggify_no_schedule_test.go b/kubectl-fdb/cmd/buggify_no_schedule_test.go index 70ebe8edd..a03efa54e 100644 --- a/kubectl-fdb/cmd/buggify_no_schedule_test.go +++ b/kubectl-fdb/cmd/buggify_no_schedule_test.go @@ -91,19 +91,19 @@ var _ = Describe("[plugin] buggify no-schedule instances command", func() { ProcessGroupOpts: processGroupSelectionOptions{ ids: []string{ // the helper function to create pods for the k8s client uses "instance" not "storage" processGroup names - fmt.Sprintf("%s-instance-1", clusterName), - fmt.Sprintf("%s-instance-2", clusterName), - fmt.Sprintf("%s-instance-2", secondClusterName), + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage), }, clusterLabel: fdbv1beta2.FDBClusterLabel, }, ExpectedProcessGroupsInNoSchedule: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, secondClusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", secondClusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage)), }, }, }), @@ -116,8 +116,8 @@ var _ = Describe("[plugin] buggify no-schedule instances command", func() { ExpectedProcessGroupsInNoSchedule: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { // the helper function to create pods for the k8s client uses "instance" not "storage" processGroup names - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }), @@ -130,7 +130,7 @@ var _ = Describe("[plugin] buggify no-schedule instances command", func() { ExpectedProcessGroupsInNoSchedule: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { // the helper function to create pods for the k8s client uses "instance" not "storage" processGroup names - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }), diff --git a/kubectl-fdb/cmd/cordon_test.go b/kubectl-fdb/cmd/cordon_test.go index d06c85a43..d167f54b7 100644 --- a/kubectl-fdb/cmd/cordon_test.go +++ b/kubectl-fdb/cmd/cordon_test.go @@ -87,7 +87,7 @@ var _ = Describe("[plugin] cordon command", func() { testCase{ nodes: []string{"node-1"}, WithExclusion: true, - ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName))}, + ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage))}, ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{}, clusterName: clusterName, clusterLabel: "", @@ -97,7 +97,7 @@ var _ = Describe("[plugin] cordon command", func() { nodes: []string{"node-1"}, WithExclusion: false, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{}, - ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName))}, + ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage))}, clusterName: clusterName, clusterLabel: "", }), @@ -126,8 +126,8 @@ var _ = Describe("[plugin] cordon command", func() { nodes: []string{"node-1", "node-2"}, WithExclusion: true, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{}, clusterName: clusterName, @@ -139,8 +139,8 @@ var _ = Describe("[plugin] cordon command", func() { WithExclusion: false, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{}, ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, clusterName: clusterName, clusterLabel: "", @@ -149,7 +149,7 @@ var _ = Describe("[plugin] cordon command", func() { testCase{ nodes: []string{"node-1"}, WithExclusion: true, - ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", secondClusterName))}, + ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage))}, ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{}, clusterName: secondClusterName, clusterLabel: "", @@ -158,7 +158,7 @@ var _ = Describe("[plugin] cordon command", func() { testCase{ nodes: []string{"node-1"}, WithExclusion: true, - ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", secondClusterName))}, + ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage))}, ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{}, clusterName: secondClusterName, clusterLabel: fdbv1beta2.FDBClusterLabel, @@ -168,8 +168,8 @@ var _ = Describe("[plugin] cordon command", func() { nodes: []string{"node-1"}, WithExclusion: true, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", secondClusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{}, clusterName: "", @@ -181,10 +181,10 @@ var _ = Describe("[plugin] cordon command", func() { WithExclusion: false, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{}, ExpectedInstancesToRemoveWithoutExclusion: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", secondClusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", secondClusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage)), }, clusterName: "", clusterLabel: fdbv1beta2.FDBClusterLabel, @@ -207,12 +207,12 @@ func createPods(clusterName string, namespace string) error { pods := []corev1.Pod{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-instance-1", clusterName), + Name: fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStorage), fdbv1beta2.FDBClusterLabel: clusterName, - fdbv1beta2.FDBProcessGroupIDLabel: fmt.Sprintf("%s-instance-1", clusterName), + fdbv1beta2.FDBProcessGroupIDLabel: fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), }, }, Spec: corev1.PodSpec{ @@ -221,12 +221,12 @@ func createPods(clusterName string, namespace string) error { }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-instance-2", clusterName), + Name: fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStorage), fdbv1beta2.FDBClusterLabel: clusterName, - fdbv1beta2.FDBProcessGroupIDLabel: fmt.Sprintf("%s-instance-2", clusterName), + fdbv1beta2.FDBProcessGroupIDLabel: fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), }, }, Spec: corev1.PodSpec{ @@ -235,12 +235,12 @@ func createPods(clusterName string, namespace string) error { }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-instance-3", clusterName), + Name: fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless), Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStateless), fdbv1beta2.FDBClusterLabel: clusterName, - fdbv1beta2.FDBProcessGroupIDLabel: fmt.Sprintf("%s-instance-3", clusterName), + fdbv1beta2.FDBProcessGroupIDLabel: fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless), }, }, Spec: corev1.PodSpec{ diff --git a/kubectl-fdb/cmd/exec_test.go b/kubectl-fdb/cmd/exec_test.go index 4a81adf7a..f4c2da687 100644 --- a/kubectl-fdb/cmd/exec_test.go +++ b/kubectl-fdb/cmd/exec_test.go @@ -43,7 +43,7 @@ var _ = Describe("[plugin] exec command", func() { BeforeEach(func() { Expect(k8sClient.Create(context.TODO(), &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "instance-1", + Name: "storage-1", Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStorage), @@ -70,12 +70,12 @@ var _ = Describe("[plugin] exec command", func() { }, Entry("Exec into instance with valid pod", testCase{ - ExpectedArgs: []string{"--namespace", "test", "exec", "-it", "instance-1", "--", "bash"}, + ExpectedArgs: []string{"--namespace", "test", "exec", "-it", "storage-1", "--", "bash"}, }), Entry("Exec into instance with explicit context", testCase{ Context: "remote-kc", - ExpectedArgs: []string{"--context", "remote-kc", "--namespace", "test", "exec", "-it", "instance-1", "--", "bash"}, + ExpectedArgs: []string{"--context", "remote-kc", "--namespace", "test", "exec", "-it", "storage-1", "--", "bash"}, }), ) }) diff --git a/kubectl-fdb/cmd/fix_coordinator_ips_test.go b/kubectl-fdb/cmd/fix_coordinator_ips_test.go index 59f6c418c..2d580965e 100644 --- a/kubectl-fdb/cmd/fix_coordinator_ips_test.go +++ b/kubectl-fdb/cmd/fix_coordinator_ips_test.go @@ -41,7 +41,7 @@ var _ = Describe("[plugin] fix-coordinator-ips command", func() { BeforeEach(func() { Expect(k8sClient.Create(context.TODO(), &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "instance-1", + Name: "storage-1", Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStorage), @@ -78,7 +78,7 @@ var _ = Describe("[plugin] fix-coordinator-ips command", func() { "-it", "-c", fdbv1beta2.MainContainerName, - "instance-1", + "storage-1", "--", "bash", "-c", @@ -100,7 +100,7 @@ var _ = Describe("[plugin] fix-coordinator-ips command", func() { "-it", "-c", fdbv1beta2.MainContainerName, - "instance-1", + "storage-1", "--", "bash", "-c", diff --git a/kubectl-fdb/cmd/k8s_client.go b/kubectl-fdb/cmd/k8s_client.go index f59619208..8bc6a7f8f 100644 --- a/kubectl-fdb/cmd/k8s_client.go +++ b/kubectl-fdb/cmd/k8s_client.go @@ -310,6 +310,19 @@ func getProcessGroupIdsWithClass(cluster *fdbv1beta2.FoundationDBCluster, proces return matchingProcessGroupIDs } +// getPodsWithProcessClass returns a list of ProcessGroupIDs in the given cluster which are of the given processClass +func getPodsWithProcessClass(cluster *fdbv1beta2.FoundationDBCluster, processClass string) []string { + matchingPodNames := []string{} + for _, processGroupStatus := range cluster.Status.ProcessGroups { + if processGroupStatus.ProcessClass != fdbv1beta2.ProcessClass(processClass) { + continue + } + // GetPodName can out-of-bounds index if the podName does not contain the processClass as expected. + matchingPodNames = append(matchingPodNames, processGroupStatus.GetPodName(cluster)) + } + return matchingPodNames +} + // fetchProcessGroupsCrossCluster fetches the list of process groups matching the given podNames and returns the // processGroupIDs mapped by clusterName matching the given clusterLabel. func fetchProcessGroupsCrossCluster(kubeClient client.Client, namespace string, clusterLabel string, podNames ...string) (map[*fdbv1beta2.FoundationDBCluster][]fdbv1beta2.ProcessGroupID, error) { @@ -346,6 +359,38 @@ func fetchProcessGroupsCrossCluster(kubeClient client.Client, namespace string, return processGroupsByCluster, nil } +// fetchPodNamesCrossCluster fetches the given podNames and returns them mapped by clusterName from the given clusterLabel. +func fetchPodNamesCrossCluster(kubeClient client.Client, namespace string, clusterLabel string, podNames ...string) (map[*fdbv1beta2.FoundationDBCluster][]string, error) { + var pod corev1.Pod + podsByClusterName := map[string][]string{} // start with grouping by cluster-label values and load clusters later + for _, podName := range podNames { + err := kubeClient.Get(context.Background(), client.ObjectKey{Name: podName, Namespace: namespace}, &pod) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil, fmt.Errorf("could not get pod: %s/%s", namespace, podName) + } + return nil, err + } + clusterName, ok := pod.Labels[clusterLabel] + if !ok { + return nil, fmt.Errorf("no cluster-label '%s' found for pod '%s'", clusterLabel, podName) + } + podsByClusterName[clusterName] = append(podsByClusterName[clusterName], podName) + } + podsByCluster := map[*fdbv1beta2.FoundationDBCluster][]string{} + for clusterName, pods := range podsByClusterName { + cluster, err := loadCluster(kubeClient, namespace, clusterName) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil, fmt.Errorf("could not get cluster: %s/%s", namespace, clusterName) + } + return nil, err + } + podsByCluster[cluster] = append(podsByCluster[cluster], pods...) + } + return podsByCluster, nil +} + func chooseRandomPod(pods *corev1.PodList) (*corev1.Pod, error) { items := pods.Items if len(items) == 0 { @@ -393,6 +438,64 @@ func fetchPodsOnNode(kubeClient client.Client, clusterName string, namespace str return pods, nil } +// getPodNamesByCluster returns a map of pod names (strings) by FDB cluster that match the criteria in the provided +// processSelectionOptions. +func getPodNamesByCluster(cmd *cobra.Command, kubeClient client.Client, opts processGroupSelectionOptions) (map[*fdbv1beta2.FoundationDBCluster][]string, error) { + if opts.useProcessGroupID { + return nil, errors.New("useProcessGroupID is not supported by getPodNamesByCluster") + } + // option compatibility checks + if opts.clusterName == "" && opts.clusterLabel == "" { + return nil, errors.New("podNames will not be selected without cluster specification") + } + if opts.clusterName == "" { // cli has a default for clusterLabel + if opts.useProcessGroupID || opts.processClass != "" || len(opts.conditions) > 0 { + return nil, errors.New("selection of pods / process groups by cluster-label (cross-cluster selection) is " + + "incompatible with use-process-group-id, process-class, and process-condition options") + } + } + if len(opts.conditions) > 0 && opts.processClass != "" { + return nil, errors.New("selection of pods / processGroups by both processClass and conditions is not supported at this time") + } + if len(opts.ids) != 0 && (opts.processClass != "" || len(opts.conditions) > 0) { + return nil, fmt.Errorf("process identifiers were provided along with a processClass (or processConditions) and would be ignored, please only provide one or the other") + } + + // cross-cluster logic: given a list of Pod names, we can look up the FDB clusters by pod label, and work across clusters + if !opts.useProcessGroupID && opts.clusterName == "" { + return fetchPodNamesCrossCluster(kubeClient, opts.namespace, opts.clusterLabel, opts.ids...) + } + + // single-cluster logic + cluster, err := loadCluster(kubeClient, opts.namespace, opts.clusterName) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil, fmt.Errorf("could not get cluster: %s/%s", opts.namespace, opts.clusterName) + } + return nil, err + } + // find the desired process groups in the single cluster + var podNames []string + if opts.processClass != "" { // match against a whole process class, ignore provided ids + podNames = getPodsWithProcessClass(cluster, opts.processClass) + } else if len(opts.conditions) > 0 { + podNames, err = getAllPodsFromClusterWithCondition(cmd.ErrOrStderr(), kubeClient, opts.clusterName, opts.namespace, opts.conditions) + if err != nil { + return nil, err + } + } else { + podNames = opts.ids + } + + if len(podNames) == 0 { + return nil, errors.New("found no pods meeting the selection criteria") + } + + return map[*fdbv1beta2.FoundationDBCluster][]string{ + cluster: podNames, + }, nil +} + // getProcessGroupsByCluster returns a map of processGroupIDs by FDB cluster that match the criteria in the provided // processSelectionOptions. func getProcessGroupsByCluster(cmd *cobra.Command, kubeClient client.Client, opts processGroupSelectionOptions) (map[*fdbv1beta2.FoundationDBCluster][]fdbv1beta2.ProcessGroupID, error) { diff --git a/kubectl-fdb/cmd/k8s_client_test.go b/kubectl-fdb/cmd/k8s_client_test.go index de7f4d33a..36407c965 100644 --- a/kubectl-fdb/cmd/k8s_client_test.go +++ b/kubectl-fdb/cmd/k8s_client_test.go @@ -52,21 +52,21 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { Status: fdbv1beta2.FoundationDBClusterStatus{ ProcessGroups: []*fdbv1beta2.ProcessGroupStatus{ { - ProcessGroupID: "instance-1", + ProcessGroupID: "storage-1", Addresses: []string{"1.2.3.4"}, ProcessGroupConditions: []*fdbv1beta2.ProcessGroupCondition{ fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.MissingProcesses), }, }, { - ProcessGroupID: "instance-2", + ProcessGroupID: "storage-2", Addresses: []string{"1.2.3.5"}, ProcessGroupConditions: []*fdbv1beta2.ProcessGroupCondition{ fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.IncorrectCommandLine), }, }, { - ProcessGroupID: "instance-3", + ProcessGroupID: "stateless-3", Addresses: []string{"1.2.3.6"}, ProcessGroupConditions: []*fdbv1beta2.ProcessGroupCondition{ fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.MissingProcesses), @@ -94,12 +94,12 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { pods := []corev1.Pod{ { ObjectMeta: metav1.ObjectMeta{ - Name: "instance-1", + Name: "storage-1", Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStorage), fdbv1beta2.FDBClusterLabel: clusterName, - fdbv1beta2.FDBProcessGroupIDLabel: "instance-1", + fdbv1beta2.FDBProcessGroupIDLabel: "storage-1", }, }, Status: corev1.PodStatus{ @@ -108,12 +108,12 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { }, { ObjectMeta: metav1.ObjectMeta{ - Name: "instance-2", + Name: "storage-2", Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStorage), fdbv1beta2.FDBClusterLabel: clusterName, - fdbv1beta2.FDBProcessGroupIDLabel: "instance-2", + fdbv1beta2.FDBProcessGroupIDLabel: "storage-2", }, }, Status: corev1.PodStatus{ @@ -122,12 +122,12 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { }, { ObjectMeta: metav1.ObjectMeta{ - Name: "instance-3", + Name: "stateless-3", Namespace: namespace, Labels: map[string]string{ fdbv1beta2.FDBProcessClassLabel: string(fdbv1beta2.ProcessClassStorage), fdbv1beta2.FDBClusterLabel: clusterName, - fdbv1beta2.FDBProcessGroupIDLabel: "instance-3", + fdbv1beta2.FDBProcessGroupIDLabel: "stateless-3", }, }, Status: corev1.PodStatus{ @@ -183,14 +183,14 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { Entry("Single condition", testCase{ conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.MissingProcesses}, - expected: []string{"instance-1"}, - expectedOutputBuffer: "Skipping Process Group: instance-3, Pod is not running, current phase: Failed\n", + expected: []string{"storage-1"}, + expectedOutputBuffer: "Skipping Process Group: stateless-3, Pod is not running, current phase: Failed\n", }), Entry("Multiple conditions", testCase{ conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.MissingProcesses, fdbv1beta2.IncorrectCommandLine}, - expected: append(expectedPodNamesMultipleConditions, "instance-1", "instance-2"), - expectedOutputBuffer: "Skipping Process Group: instance-3, Pod is not running, current phase: Failed\n", + expected: append(expectedPodNamesMultipleConditions, "storage-1", "storage-2"), + expectedOutputBuffer: "Skipping Process Group: stateless-3, Pod is not running, current phase: Failed\n", }), Entry("Single condition and missing pod", testCase{ @@ -201,8 +201,8 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { Entry("Multiple conditions and missing pod", testCase{ conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.MissingProcesses, fdbv1beta2.SidecarUnreachable}, - expected: append(expectedPodNamesMultipleConditionsMissingPods, "instance-1"), - expectedOutputBuffer: "Skipping Process Group: instance-5, because it does not have a corresponding Pod.\nSkipping Process Group: instance-3, Pod is not running, current phase: Failed\n", + expected: append(expectedPodNamesMultipleConditionsMissingPods, "storage-1"), + expectedOutputBuffer: "Skipping Process Group: instance-5, because it does not have a corresponding Pod.\nSkipping Process Group: stateless-3, Pod is not running, current phase: Failed\n", }), ) }) @@ -323,7 +323,7 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { Entry("errors when ids are passed along with processClass selector", testCase{ opts: processGroupSelectionOptions{ - ids: []string{fmt.Sprintf("%s-instance-1", clusterName)}, + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)}, processClass: string(fdbv1beta2.ProcessClassStateless), clusterName: clusterName, }, @@ -352,7 +352,7 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { Entry("does not find processGroups from clusterLabel when useProcessGroupID is set", testCase{ opts: processGroupSelectionOptions{ - ids: []string{fmt.Sprintf("%s-instance-1", clusterName)}, + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)}, clusterLabel: fdbv1beta2.FDBClusterLabel, useProcessGroupID: true, }, @@ -364,12 +364,12 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { testCase{ opts: processGroupSelectionOptions{ clusterLabel: fdbv1beta2.FDBClusterLabel, - ids: []string{fmt.Sprintf("%s-instance-1", clusterName), fmt.Sprintf("%s-instance-3", clusterName)}, + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless)}, }, wantResult: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-3", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless)), }, }, }, @@ -379,18 +379,18 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { opts: processGroupSelectionOptions{ clusterLabel: fdbv1beta2.FDBClusterLabel, ids: []string{ - fmt.Sprintf("%s-instance-1", clusterName), - fmt.Sprintf("%s-instance-1", secondClusterName), - fmt.Sprintf("%s-instance-2", secondClusterName), + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage), }, }, wantResult: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), }, secondClusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", secondClusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", secondClusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage)), }, }, }, @@ -398,13 +398,13 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { Entry("gets processGroups from podNames and cluster name", testCase{ opts: processGroupSelectionOptions{ - ids: []string{fmt.Sprintf("%s-instance-1", clusterName), fmt.Sprintf("%s-instance-2", clusterName)}, + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)}, clusterName: clusterName, }, wantResult: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }, @@ -414,12 +414,12 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { opts: processGroupSelectionOptions{ clusterName: clusterName, useProcessGroupID: true, - ids: []string{fmt.Sprintf("%s-instance-1", clusterName), fmt.Sprintf("%s-instance-2", clusterName)}, + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)}, }, wantResult: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }, @@ -432,8 +432,8 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { }, wantResult: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }, @@ -446,7 +446,7 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { }, wantResult: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-3", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless)), }, }, }, @@ -459,8 +459,8 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { }, wantResult: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }, @@ -473,7 +473,7 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { }, wantResult: map[string][]fdbv1beta2.ProcessGroupID{ clusterName: { - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, }, @@ -490,4 +490,217 @@ var _ = Describe("[plugin] using the Kubernetes client", func() { ), ) }) + When("calling getPodNamesByCluster", func() { + BeforeEach(func() { + // creating Pods for first cluster. + cluster = generateClusterStruct(clusterName, namespace) // the status is overwritten by prior tests + Expect(createPods(clusterName, namespace)).NotTo(HaveOccurred()) + + // creating a second cluster + secondCluster = generateClusterStruct(secondClusterName, namespace) + Expect(k8sClient.Create(context.TODO(), secondCluster)).NotTo(HaveOccurred()) + Expect(createPods(secondClusterName, namespace)).NotTo(HaveOccurred()) + }) + type testCase struct { + opts processGroupSelectionOptions + wantResult map[string][]string // cluster-name to pod names in the cluster + wantErrContains string + } + DescribeTable("correctly follow various options", + func(tc testCase) { + tc.opts.namespace = namespace + cmd := newRemoveProcessGroupCmd(genericclioptions.IOStreams{}) + result, err := getPodNamesByCluster(cmd, k8sClient, tc.opts) + if tc.wantErrContains == "" { + Expect(err).To(BeNil()) + } else { + Expect(err).NotTo(BeNil()) + Expect(err.Error()).To(ContainSubstring(tc.wantErrContains)) + } + // ensure that the maps are equivalent, unfortunately involved due to passing cluster by-pointer + Expect(len(tc.wantResult)).To(Equal(len(result))) + for wantClusterName, wantProcessGroups := range tc.wantResult { + foundInResult := false + for cluster, processGroups := range result { + if cluster.Name != wantClusterName { + continue + } + foundInResult = true + Expect(processGroups).To(ContainElements(wantProcessGroups)) + Expect(wantProcessGroups).To(ContainElements(processGroups)) + } + Expect(foundInResult).To(BeTrue()) + } + }, + Entry("errors when neither clusterName nor clusterLabel are passed", + testCase{ + opts: processGroupSelectionOptions{ids: []string{"something"}}, + wantErrContains: "podNames will not be selected without cluster specification", + }, + ), + Entry("errors when ids are passed along with processClass selector", + testCase{ + opts: processGroupSelectionOptions{ + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)}, + processClass: string(fdbv1beta2.ProcessClassStateless), + clusterName: clusterName, + }, + wantErrContains: "process identifiers were provided along with a processClass (or processConditions) and would be ignored, please only provide one or the other", + }, + ), + Entry("errors when conditions are passed along with processClass selector", + testCase{ + opts: processGroupSelectionOptions{ + conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.PodFailing}, + processClass: string(fdbv1beta2.ProcessClassStateless), + clusterName: clusterName, + }, + wantErrContains: "by both processClass and conditions is not supported at this time", + }, + ), + Entry("errors when no pods are found with the given processClass", + testCase{ + opts: processGroupSelectionOptions{ + clusterName: clusterName, + processClass: string(fdbv1beta2.ProcessClassProxy), + }, + wantErrContains: "found no pods meeting the selection criteria", + }, + ), + Entry("does not find pods from clusterLabel when useProcessGroupID is set", + testCase{ + opts: processGroupSelectionOptions{ + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)}, + clusterLabel: fdbv1beta2.FDBClusterLabel, + useProcessGroupID: true, + }, + wantResult: nil, + wantErrContains: "useProcessGroupID is not supported", + }, + ), + Entry("gets pods from podNames and clusterLabel", + testCase{ + opts: processGroupSelectionOptions{ + clusterLabel: fdbv1beta2.FDBClusterLabel, + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless)}, + }, + wantResult: map[string][]string{ + clusterName: { + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless), + }, + }, + }, + ), + Entry("gets pods across clusters from podNames and clusterLabel", + testCase{ + opts: processGroupSelectionOptions{ + clusterLabel: fdbv1beta2.FDBClusterLabel, + ids: []string{ + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage), + }, + }, + wantResult: map[string][]string{ + clusterName: { + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + }, + secondClusterName: { + fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage), + }, + }, + }, + ), + Entry("gets pods from podNames and cluster name", + testCase{ + opts: processGroupSelectionOptions{ + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)}, + clusterName: clusterName, + }, + wantResult: map[string][]string{ + clusterName: { + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), + }, + }, + }, + ), + Entry("errors when useProcessGroupID is set", + testCase{ + opts: processGroupSelectionOptions{ + clusterName: clusterName, + useProcessGroupID: true, + ids: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)}, + }, + wantErrContains: "useProcessGroupID is not supported", + }, + ), + Entry("gets pods matching processClassStorage", + testCase{ + opts: processGroupSelectionOptions{ + clusterName: clusterName, + processClass: string(fdbv1beta2.ProcessClassStorage), + }, + wantResult: map[string][]string{ + clusterName: { + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), + }, + }, + }, + ), + Entry("gets pods matching processClassStateless", + testCase{ + opts: processGroupSelectionOptions{ + clusterName: clusterName, + processClass: string(fdbv1beta2.ProcessClassStateless), + }, + wantResult: map[string][]string{ + clusterName: { + fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless), + }, + }, + }, + ), + Entry("gets 2 pods matching PodFailing condition", + testCase{ + opts: processGroupSelectionOptions{ + clusterName: clusterName, + conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.PodFailing}, + }, + wantResult: map[string][]string{ + clusterName: { + fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), + }, + }, + }, + ), + Entry("gets 1 pods matching MissingProcesses condition", + testCase{ + opts: processGroupSelectionOptions{ + clusterName: clusterName, + conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.MissingProcesses}, + }, + wantResult: map[string][]string{ + clusterName: { + fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), + }, + }, + }, + ), + Entry("gets 0 pods matching IncorrectPodSpec condition", + testCase{ + opts: processGroupSelectionOptions{ + clusterName: clusterName, + conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.IncorrectPodSpec}, + }, + wantResult: nil, + wantErrContains: "found no pods meeting the selection criteria", + }, + ), + ) + }) }) diff --git a/kubectl-fdb/cmd/remove_process_group_test.go b/kubectl-fdb/cmd/remove_process_group_test.go index 86604a7b2..769ed3d36 100644 --- a/kubectl-fdb/cmd/remove_process_group_test.go +++ b/kubectl-fdb/cmd/remove_process_group_test.go @@ -264,9 +264,9 @@ var _ = Describe("[plugin] remove process groups command", func() { }, Entry("errors when process group IDs are provided instead of pod names", testCase{ - podNames: []string{"instance-1"}, + podNames: []string{"storage-1"}, clusterLabel: fdbv1beta2.FDBClusterLabel, - wantErrorContains: "could not get pod: test/instance-1", + wantErrorContains: "could not get pod: test/storage-1", clusterDataMap: map[string]clusterData{ clusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{}, @@ -279,9 +279,9 @@ var _ = Describe("[plugin] remove process groups command", func() { ), Entry("errors when no cluster found with given label", testCase{ - podNames: []string{fmt.Sprintf("%s-instance-1", clusterName)}, + podNames: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)}, clusterLabel: "invalid-cluster-label", - wantErrorContains: fmt.Sprintf("no cluster-label 'invalid-cluster-label' found for pod '%s-instance-1'", clusterName), + wantErrorContains: fmt.Sprintf("no cluster-label 'invalid-cluster-label' found for pod '%s-storage-1'", clusterName), clusterDataMap: map[string]clusterData{ clusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{}, @@ -294,12 +294,12 @@ var _ = Describe("[plugin] remove process groups command", func() { ), Entry("removes valid 1 process group referred to by pod name and cluster-label", testCase{ - podNames: []string{fmt.Sprintf("%s-instance-1", clusterName)}, + podNames: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)}, clusterLabel: fdbv1beta2.FDBClusterLabel, clusterDataMap: map[string]clusterData{ clusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedProcessCounts: fdbv1beta2.ProcessCounts{ Storage: 1, @@ -316,12 +316,12 @@ var _ = Describe("[plugin] remove process groups command", func() { ), Entry("removes two process groups, each on a different cluster", testCase{ - podNames: []string{fmt.Sprintf("%s-instance-1", clusterName), fmt.Sprintf("%s-instance-1", secondClusterName)}, + podNames: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage)}, clusterLabel: fdbv1beta2.FDBClusterLabel, clusterDataMap: map[string]clusterData{ clusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedProcessCounts: fdbv1beta2.ProcessCounts{ Storage: 1, @@ -329,7 +329,7 @@ var _ = Describe("[plugin] remove process groups command", func() { }, secondClusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", secondClusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedProcessCounts: fdbv1beta2.ProcessCounts{ Storage: 1, @@ -340,12 +340,12 @@ var _ = Describe("[plugin] remove process groups command", func() { ), Entry("removes 3 process groups, on 2 different clusters", testCase{ - podNames: []string{fmt.Sprintf("%s-instance-1", clusterName), fmt.Sprintf("%s-instance-1", secondClusterName), fmt.Sprintf("%s-instance-2", secondClusterName)}, + podNames: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage)}, clusterLabel: fdbv1beta2.FDBClusterLabel, clusterDataMap: map[string]clusterData{ clusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedProcessCounts: fdbv1beta2.ProcessCounts{ Storage: 1, @@ -353,8 +353,8 @@ var _ = Describe("[plugin] remove process groups command", func() { }, secondClusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", secondClusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", secondClusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedProcessCounts: fdbv1beta2.ProcessCounts{ Storage: 1, @@ -365,14 +365,14 @@ var _ = Describe("[plugin] remove process groups command", func() { ), Entry("removes 4 process groups, on 2 different clusters", testCase{ - podNames: []string{fmt.Sprintf("%s-instance-1", clusterName), fmt.Sprintf("%s-instance-2", clusterName), - fmt.Sprintf("%s-instance-1", secondClusterName), fmt.Sprintf("%s-instance-2", secondClusterName)}, + podNames: []string{fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage), + fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage), fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage)}, clusterLabel: fdbv1beta2.FDBClusterLabel, clusterDataMap: map[string]clusterData{ clusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedProcessCounts: fdbv1beta2.ProcessCounts{ Storage: 1, @@ -380,8 +380,8 @@ var _ = Describe("[plugin] remove process groups command", func() { }, secondClusterName: { ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", secondClusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", secondClusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", secondClusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", secondClusterName, fdbv1beta2.ProcessClassStorage)), }, ExpectedProcessCounts: fdbv1beta2.ProcessCounts{ Storage: 1, @@ -462,7 +462,7 @@ var _ = Describe("[plugin] remove process groups command", func() { processClass: string(fdbv1beta2.ProcessClassStateless), clusterName: clusterName, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-3", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-3", clusterName, fdbv1beta2.ProcessClassStateless)), }, }, ), @@ -471,8 +471,8 @@ var _ = Describe("[plugin] remove process groups command", func() { processClass: string(fdbv1beta2.ProcessClassStorage), clusterName: clusterName, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, ), @@ -489,8 +489,8 @@ var _ = Describe("[plugin] remove process groups command", func() { conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.PodFailing}, clusterName: clusterName, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-1", clusterName)), - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-1", clusterName, fdbv1beta2.ProcessClassStorage)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, ), @@ -499,7 +499,7 @@ var _ = Describe("[plugin] remove process groups command", func() { conditions: []fdbv1beta2.ProcessGroupConditionType{fdbv1beta2.MissingProcesses}, clusterName: clusterName, ExpectedInstancesToRemove: []fdbv1beta2.ProcessGroupID{ - fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-instance-2", clusterName)), + fdbv1beta2.ProcessGroupID(fmt.Sprintf("%s-%s-2", clusterName, fdbv1beta2.ProcessClassStorage)), }, }, ), diff --git a/kubectl-fdb/cmd/restart.go b/kubectl-fdb/cmd/restart.go index 96119e0f6..3e20f01d5 100644 --- a/kubectl-fdb/cmd/restart.go +++ b/kubectl-fdb/cmd/restart.go @@ -75,22 +75,11 @@ func newRestartCmd(streams genericclioptions.IOStreams) *cobra.Command { return err } - processGroupsByCluster, err := getProcessGroupsByCluster(cmd, kubeClient, processGroupSelectionOpts) + podsByCluster, err := getPodNamesByCluster(cmd, kubeClient, processGroupSelectionOpts) if err != nil { return err } - for cluster, processGroupIDs := range processGroupsByCluster { - // TODO remove this once we've removed support for processGroupID (instead of pod) lookup and - // can more nicely convert getProcessGroupsByCluster to return podNames (possible now, but less clean) - var podNames []string - for _, processGroupStatus := range cluster.Status.ProcessGroups { - for _, processGroupID := range processGroupIDs { - if processGroupStatus.ProcessGroupID != processGroupID { - continue - } - podNames = append(podNames, processGroupStatus.GetPodName(cluster)) - } - } + for cluster, podNames := range podsByCluster { err := restartProcesses(cmd, config, clientSet, podNames, processGroupSelectionOpts.namespace, cluster.Name, wait, sleep) if err != nil { return err diff --git a/kubectl-fdb/cmd/suite_test.go b/kubectl-fdb/cmd/suite_test.go index 6aa971102..fcbd8848e 100644 --- a/kubectl-fdb/cmd/suite_test.go +++ b/kubectl-fdb/cmd/suite_test.go @@ -75,14 +75,14 @@ func generateClusterStruct(name string, namespace string) *fdbv1beta2.Foundation Status: fdbv1beta2.FoundationDBClusterStatus{ ProcessGroups: []*fdbv1beta2.ProcessGroupStatus{ { - ProcessGroupID: fdbv1beta2.ProcessGroupID(name + "-instance-1"), + ProcessGroupID: fdbv1beta2.ProcessGroupID(name + "-" + string(fdbv1beta2.ProcessClassStorage) + "-1"), ProcessClass: fdbv1beta2.ProcessClassStorage, ProcessGroupConditions: []*fdbv1beta2.ProcessGroupCondition{ fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.PodFailing), }, }, { - ProcessGroupID: fdbv1beta2.ProcessGroupID(name + "-instance-2"), + ProcessGroupID: fdbv1beta2.ProcessGroupID(name + "-" + string(fdbv1beta2.ProcessClassStorage) + "-2"), ProcessClass: fdbv1beta2.ProcessClassStorage, ProcessGroupConditions: []*fdbv1beta2.ProcessGroupCondition{ fdbv1beta2.NewProcessGroupCondition(fdbv1beta2.PodFailing), @@ -90,7 +90,7 @@ func generateClusterStruct(name string, namespace string) *fdbv1beta2.Foundation }, }, { - ProcessGroupID: fdbv1beta2.ProcessGroupID(name + "-instance-3"), + ProcessGroupID: fdbv1beta2.ProcessGroupID(name + "-" + string(fdbv1beta2.ProcessClassStateless) + "-3"), ProcessClass: fdbv1beta2.ProcessClassStateless, }, },