diff --git a/controllers/subscriptions.go b/controllers/subscriptions.go index 7d4145a4d..f3a31752c 100644 --- a/controllers/subscriptions.go +++ b/controllers/subscriptions.go @@ -42,16 +42,27 @@ import ( // because fake.Client does not support them. func CheckExistingSubscriptions(cli client.Client, desiredSubscription *operatorv1alpha1.Subscription) (*operatorv1alpha1.Subscription, error) { + odfSub, err := GetOdfSubscription(cli) + if err != nil { + return nil, err + } + + if odfSub.Spec.Config == nil { + odfSub.Spec.Config = &operatorv1alpha1.SubscriptionConfig{} + } + subsList := &operatorv1alpha1.SubscriptionList{} - err := cli.List(context.TODO(), subsList, &client.ListOptions{Namespace: desiredSubscription.Namespace}) + err = cli.List(context.TODO(), subsList, &client.ListOptions{Namespace: desiredSubscription.Namespace}) if err != nil { return nil, err } + var subExsist bool var actualSub *operatorv1alpha1.Subscription pkgName := desiredSubscription.Spec.Package for i, sub := range subsList.Items { if sub.Spec.Package == pkgName { + subExsist = true if actualSub != nil { foundSubs := []string{actualSub.Name, sub.Name} return nil, fmt.Errorf("multiple Subscriptions found for package '%s': %v", pkgName, foundSubs) @@ -59,22 +70,71 @@ func CheckExistingSubscriptions(cli client.Client, desiredSubscription *operator actualSub = &subsList.Items[i] actualSub.Spec.Channel = desiredSubscription.Spec.Channel - // If the config is not set, only then set it to the desired value => allow user to override - if actualSub.Spec.Config == nil { + if actualSub.Spec.Config == nil && desiredSubscription.Spec.Config == nil { + actualSub.Spec.Config = &operatorv1alpha1.SubscriptionConfig{} + actualSub.Spec.Config.Tolerations = odfSub.Spec.Config.Tolerations + } else if actualSub.Spec.Config == nil && desiredSubscription.Spec.Config != nil { actualSub.Spec.Config = desiredSubscription.Spec.Config + actualSub.Spec.Config.Tolerations = getMergedTolerations(odfSub.Spec.Config.Tolerations, desiredSubscription.Spec.Config.Tolerations) + } else if actualSub.Spec.Config != nil && desiredSubscription.Spec.Config == nil { + actualSub.Spec.Config.Tolerations = odfSub.Spec.Config.Tolerations } else if actualSub.Spec.Config != nil && desiredSubscription.Spec.Config != nil { // Combines the environment variables from both subscriptions. - // If actualSub already contains an environment variable, its value will be updated with the value from desiredSubscription. actualSub.Spec.Config.Env = getMergedEnvVars(actualSub.Spec.Config.Env, desiredSubscription.Spec.Config.Env) + // Combines the Tolerations from odf sub and desired sub. + actualSub.Spec.Config.Tolerations = getMergedTolerations(odfSub.Spec.Config.Tolerations, desiredSubscription.Spec.Config.Tolerations) } desiredSubscription = actualSub } } + if !subExsist { + if desiredSubscription.Spec.Config == nil { + desiredSubscription.Spec.Config = &operatorv1alpha1.SubscriptionConfig{ + Tolerations: odfSub.Spec.Config.Tolerations, + } + } else { + desiredSubscription.Spec.Config.Tolerations = getMergedTolerations(odfSub.Spec.Config.Tolerations, desiredSubscription.Spec.Config.Tolerations) + } + } + return desiredSubscription, nil } +func getMergedTolerations(tol1, tol2 []corev1.Toleration) []corev1.Toleration { + + if len(tol1) == 0 { + return append([]corev1.Toleration{}, tol2...) + } else if len(tol2) == 0 { + return append([]corev1.Toleration{}, tol1...) + } + + mergedTolerations := append([]corev1.Toleration{}, tol1...) + + for _, t2 := range tol2 { + found := false + for i, t1 := range tol1 { + if t1.Key == t2.Key && t1.Operator == t2.Operator && t1.Value == t2.Value { + found = true + break + } + // If the toleration with the same key but different values is found, + // update the existing toleration in tol1 with the new toleration from tol2. + if t1.Key == t2.Key && t1.Operator == t2.Operator { + tol1[i] = t2 + found = true + break + } + } + if !found { + mergedTolerations = append(mergedTolerations, t2) + } + } + + return mergedTolerations +} + // getMergedEnvVars updates the value of env variables in the envList1 with that of envList2 and // returns the updated list of env variables. func getMergedEnvVars(envList1, envList2 []corev1.EnvVar) []corev1.EnvVar { diff --git a/controllers/subscriptions_test.go b/controllers/subscriptions_test.go index d2335c591..9a0975323 100644 --- a/controllers/subscriptions_test.go +++ b/controllers/subscriptions_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -72,6 +73,16 @@ func TestEnsureSubscription(t *testing.T) { Spec: &operatorv1alpha1.SubscriptionSpec{ Package: OdfSubscriptionPackage, + Config: &operatorv1alpha1.SubscriptionConfig{ + Tolerations: []corev1.Toleration{ + { + Key: "node.odf.openshift.io/storage", + Operator: "Equal", + Value: "true", + Effect: "NoSchedule", + }, + }, + }, }, } err = fakeReconciler.Client.Create(context.TODO(), odfSub) @@ -81,9 +92,18 @@ func TestEnsureSubscription(t *testing.T) { assert.NoError(t, err) for _, expectedSubscription := range subs { + if expectedSubscription.Spec.Config == nil { + expectedSubscription.Spec.Config = &operatorv1alpha1.SubscriptionConfig{ + Tolerations: odfSub.Spec.Config.Tolerations, + } + } else { + expectedSubscription.Spec.Config.Tolerations = getMergedTolerations(odfSub.Spec.Config.Tolerations, expectedSubscription.Spec.Config.Tolerations) + } + actualSubscription := &operatorv1alpha1.Subscription{} err = fakeReconciler.Client.Get(context.TODO(), types.NamespacedName{Name: expectedSubscription.Name, Namespace: expectedSubscription.Namespace}, actualSubscription) assert.NoError(t, err) + assert.Equal(t, expectedSubscription.Spec, actualSubscription.Spec) } }