diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index 5a6620fb..081f60d2 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -26,6 +26,7 @@ import ( "io/fs" "log" "net/http" + "sort" "strings" "time" @@ -627,6 +628,35 @@ type InstallOperatorRequest struct { SubscriptionConfig *olmv1alpha1.SubscriptionConfig } +func mergeNamespacesEnvVar(str1, str2 string) string { + ns1 := strings.Split(str1, ",") + ns2 := strings.Split(str2, ",") + nsMap := map[string]struct{}{} + + for _, ns := range ns1 { + if ns == "" { + continue + } + nsMap[ns] = struct{}{} + } + + for _, ns := range ns2 { + if ns == "" { + continue + } + nsMap[ns] = struct{}{} + } + + namespaces := []string{} + for ns := range nsMap { + namespaces = append(namespaces, ns) + } + + sort.Strings(namespaces) + + return strings.Join(namespaces, ",") +} + func mergeSubscriptionConfig(sub *olmv1alpha1.SubscriptionConfig, cfg *olmv1alpha1.SubscriptionConfig) *olmv1alpha1.SubscriptionConfig { if sub == nil { sub = &olmv1alpha1.SubscriptionConfig{Env: []corev1.EnvVar{}} @@ -648,20 +678,7 @@ func mergeSubscriptionConfig(sub *olmv1alpha1.SubscriptionConfig, cfg *olmv1alph } // Merge the namespaces - subNamespaces := strings.Split(se.Value, ",") - cfgNamespaces := strings.Split(e.Value, ",") - namespacesMap := map[string]struct{}{} - for _, ns := range subNamespaces { - namespacesMap[ns] = struct{}{} - } - for _, ns := range cfgNamespaces { - namespacesMap[ns] = struct{}{} - } - namespaces := []string{} - for ns := range namespacesMap { - namespaces = append(namespaces, ns) - } - sub.Env[i].Value = strings.Join(namespaces, ",") + sub.Env[i].Value = mergeNamespacesEnvVar(se.Value, e.Value) break } diff --git a/pkg/kubernetes/kubernetes_test.go b/pkg/kubernetes/kubernetes_test.go new file mode 100644 index 00000000..7a57f15e --- /dev/null +++ b/pkg/kubernetes/kubernetes_test.go @@ -0,0 +1,104 @@ +// percona-everest-cli +// Copyright (C) 2023 Percona LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package kubernetes provides functionality for kubernetes. +package kubernetes + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMergeNamesspacesEnvVar(t *testing.T) { + t.Parallel() + tests := []struct { + name string + ns1 string + ns2 string + want string + }{ + { + name: "0-0", + ns1: "", + ns2: "", + want: "", + }, + { + name: "1-0", + ns1: "ns1", + ns2: "", + want: "ns1", + }, + { + name: "0-1", + ns1: "", + ns2: "ns2", + want: "ns2", + }, + { + name: "1-1", + ns1: "ns1", + ns2: "ns2", + want: "ns1,ns2", + }, + { + name: "1-2", + ns1: "ns1", + ns2: "ns2,ns3", + want: "ns1,ns2,ns3", + }, + { + name: "1-2 unsorted", + ns1: "ns2", + ns2: "ns3,ns1", + want: "ns1,ns2,ns3", + }, + { + name: "1-2 extra commas", + ns1: ",ns1,", + ns2: ",,ns2,,,,ns3,,,", + want: "ns1,ns2,ns3", + }, + { + name: "2-2", + ns1: "ns4,ns1", + ns2: "ns2,ns3", + want: "ns1,ns2,ns3,ns4", + }, + { + name: "0-2", + ns1: "", + ns2: "ns2,ns3", + want: "ns2,ns3", + }, + { + name: "2-0 unsorted", + ns1: "ns4,ns1", + ns2: "", + want: "ns1,ns4", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + mergedNS := mergeNamespacesEnvVar(tt.ns1, tt.ns2) + assert.Equal(t, tt.want, mergedNS) + }) + } +} diff --git a/pkg/kubernetes/olm_operator_test.go b/pkg/kubernetes/olm_operator_test.go index e82863d4..b4236a5a 100644 --- a/pkg/kubernetes/olm_operator_test.go +++ b/pkg/kubernetes/olm_operator_test.go @@ -27,6 +27,8 @@ import ( "go.uber.org/zap" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "github.com/percona/percona-everest-cli/pkg/kubernetes/client" @@ -83,11 +85,16 @@ func TestInstallOlmOperator(t *testing.T) { }, }, } + groupResource := schema.GroupResource{ + Group: "operators.coreos.com", + Resource: "subscriptions", + } + k8sclient.On("GetSubscription", mock.Anything, subscriptionNamespace, operatorName).Return(&v1alpha1.Subscription{}, apierrors.NewNotFound(groupResource, operatorName)).Once() k8sclient.On( "CreateSubscription", mock.Anything, subscriptionNamespace, mockSubscription, ).Return(mockSubscription, nil) - k8sclient.On("GetSubscription", mock.Anything, subscriptionNamespace, operatorName).Return(mockSubscription, nil) + k8sclient.On("GetSubscription", mock.Anything, subscriptionNamespace, operatorName).Return(mockSubscription, nil).Once() mockInstallPlan := &v1alpha1.InstallPlan{} k8sclient.On( "GetInstallPlan", mock.Anything,