From ba14af924919c0be55c769ee385c58ef026b2d40 Mon Sep 17 00:00:00 2001 From: Mikalai Radchuk <509198+m1kola@users.noreply.github.com> Date: Wed, 19 Feb 2025 16:28:08 +0100 Subject: [PATCH] Refactoring: propagate env vars via parameters --- cmd/manager/main.go | 21 +- .../construct/build_statefulset_test.go | 108 +--------- controllers/construct/mongodbstatefulset.go | 58 ++---- controllers/mongodb_cleanup_test.go | 5 +- controllers/mongodb_tls_test.go | 22 +- controllers/replica_set_controller.go | 55 +++-- controllers/replicaset_controller_test.go | 191 +++++++++++------- .../replica_set_enterprise_upgrade.go | 4 +- test/e2e/setup/test_config.go | 2 +- 9 files changed, 222 insertions(+), 244 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index a874faff6..b8dd5d184 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -3,11 +3,13 @@ package main import ( "fmt" "os" + "sigs.k8s.io/controller-runtime/pkg/cache" mdbv1 "github.com/mongodb/mongodb-kubernetes-operator/api/v1" "github.com/mongodb/mongodb-kubernetes-operator/controllers" "github.com/mongodb/mongodb-kubernetes-operator/controllers/construct" + "github.com/mongodb/mongodb-kubernetes-operator/pkg/util/envvar" "go.uber.org/zap" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -56,7 +58,14 @@ func main() { log.Sugar().Fatalf("Failed to configure logger: %v", err) } - if !hasRequiredVariables(log, construct.AgentImageEnv, construct.VersionUpgradeHookImageEnv, construct.ReadinessProbeImageEnv) { + if !hasRequiredVariables( + log, + construct.MongodbRepoUrlEnv, + construct.MongodbImageEnv, + construct.AgentImageEnv, + construct.VersionUpgradeHookImageEnv, + construct.ReadinessProbeImageEnv, + ) { os.Exit(1) } @@ -99,7 +108,15 @@ func main() { } // Setup Controller. - if err = controllers.NewReconciler(mgr).SetupWithManager(mgr); err != nil { + if err = controllers.NewReconciler( + mgr, + os.Getenv(construct.MongodbRepoUrlEnv), + os.Getenv(construct.MongodbImageEnv), + envvar.GetEnvOrDefault(construct.MongoDBImageTypeEnv, construct.DefaultImageType), + os.Getenv(construct.AgentImageEnv), + os.Getenv(construct.VersionUpgradeHookImageEnv), + os.Getenv(construct.ReadinessProbeImageEnv), + ).SetupWithManager(mgr); err != nil { log.Sugar().Fatalf("Unable to create controller: %v", err) } // +kubebuilder:scaffold:builder diff --git a/controllers/construct/build_statefulset_test.go b/controllers/construct/build_statefulset_test.go index 56e3bcaac..e02095c63 100644 --- a/controllers/construct/build_statefulset_test.go +++ b/controllers/construct/build_statefulset_test.go @@ -1,7 +1,6 @@ package construct import ( - "os" "reflect" "testing" @@ -21,10 +20,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func init() { - os.Setenv(VersionUpgradeHookImageEnv, "version-upgrade-hook-image") -} - func newTestReplicaSet() mdbv1.MongoDBCommunity { return mdbv1.MongoDBCommunity{ ObjectMeta: metav1.ObjectMeta{ @@ -40,12 +35,8 @@ func newTestReplicaSet() mdbv1.MongoDBCommunity { } func TestMultipleCalls_DoNotCauseSideEffects(t *testing.T) { - t.Setenv(MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(MongodbImageEnv, "mongodb-community-server") - t.Setenv(AgentImageEnv, "agent-image") - mdb := newTestReplicaSet() - stsFunc := BuildMongoDBReplicaSetStatefulSetModificationFunction(&mdb, &mdb, os.Getenv(AgentImageEnv), true) + stsFunc := BuildMongoDBReplicaSetStatefulSetModificationFunction(&mdb, &mdb, "fake-mongodbImage", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage", true) sts := &appsv1.StatefulSet{} t.Run("1st Call", func(t *testing.T) { @@ -63,13 +54,10 @@ func TestMultipleCalls_DoNotCauseSideEffects(t *testing.T) { } func TestManagedSecurityContext(t *testing.T) { - t.Setenv(MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(MongodbImageEnv, "mongodb-community-server") - t.Setenv(AgentImageEnv, "agent-image") t.Setenv(podtemplatespec.ManagedSecurityContextEnv, "true") mdb := newTestReplicaSet() - stsFunc := BuildMongoDBReplicaSetStatefulSetModificationFunction(&mdb, &mdb, os.Getenv(AgentImageEnv), true) + stsFunc := BuildMongoDBReplicaSetStatefulSetModificationFunction(&mdb, &mdb, "fake-mongodbImage", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage", true) sts := &appsv1.StatefulSet{} stsFunc(sts) @@ -77,89 +65,9 @@ func TestManagedSecurityContext(t *testing.T) { assertStatefulSetIsBuiltCorrectly(t, mdb, sts) } -func TestGetMongoDBImage(t *testing.T) { - type testConfig struct { - setArgs func(t *testing.T) - version string - expectedImage string - } - tests := map[string]testConfig{ - "Default UBI8 Community image": { - setArgs: func(t *testing.T) { - t.Setenv(MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(MongodbImageEnv, "mongodb-community-server") - }, - version: "6.0.5", - expectedImage: "docker.io/mongodb/mongodb-community-server:6.0.5-ubi8", - }, - "Overridden UBI8 Enterprise image": { - setArgs: func(t *testing.T) { - t.Setenv(MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(MongodbImageEnv, "mongodb-enterprise-server") - }, - version: "6.0.5", - expectedImage: "docker.io/mongodb/mongodb-enterprise-server:6.0.5-ubi8", - }, - "Overridden UBI8 Enterprise image from Quay": { - setArgs: func(t *testing.T) { - t.Setenv(MongodbRepoUrl, "quay.io/mongodb") - t.Setenv(MongodbImageEnv, "mongodb-enterprise-server") - }, - version: "6.0.5", - expectedImage: "quay.io/mongodb/mongodb-enterprise-server:6.0.5-ubi8", - }, - "Overridden Ubuntu Community image": { - setArgs: func(t *testing.T) { - t.Setenv(MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(MongodbImageEnv, "mongodb-community-server") - t.Setenv(MongoDBImageType, "ubuntu2204") - }, - version: "6.0.5", - expectedImage: "docker.io/mongodb/mongodb-community-server:6.0.5-ubuntu2204", - }, - "Overridden UBI Community image": { - setArgs: func(t *testing.T) { - t.Setenv(MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(MongodbImageEnv, "mongodb-community-server") - t.Setenv(MongoDBImageType, "ubi8") - }, - version: "6.0.5", - expectedImage: "docker.io/mongodb/mongodb-community-server:6.0.5-ubi8", - }, - "Docker Inc images": { - setArgs: func(t *testing.T) { - t.Setenv(MongodbRepoUrl, "docker.io") - t.Setenv(MongodbImageEnv, "mongo") - }, - version: "6.0.5", - expectedImage: "docker.io/mongo:6.0.5", - }, - "Deprecated AppDB images defined the old way": { - setArgs: func(t *testing.T) { - t.Setenv(MongodbRepoUrl, "quay.io") - t.Setenv(MongodbImageEnv, "mongodb/mongodb-enterprise-appdb-database-ubi") - // In this example, we intentionally don't use the suffix from the env. variable and let users - // define it in the version instead. There are some known customers who do this. - // This is a backwards compatibility case. - t.Setenv(MongoDBImageType, "will-be-ignored") - }, - - version: "5.0.14-ent", - expectedImage: "quay.io/mongodb/mongodb-enterprise-appdb-database-ubi:5.0.14-ent", - }, - } - for testName := range tests { - t.Run(testName, func(t *testing.T) { - testConfig := tests[testName] - testConfig.setArgs(t) - image := getMongoDBImage(testConfig.version) - assert.Equal(t, testConfig.expectedImage, image) - }) - } -} - func TestMongod_Container(t *testing.T) { - c := container.New(mongodbContainer("4.2", []corev1.VolumeMount{}, mdbv1.NewMongodConfiguration())) + const mongodbImageMock = "fake-mongodbImage" + c := container.New(mongodbContainer(mongodbImageMock, []corev1.VolumeMount{}, mdbv1.NewMongodConfiguration())) t.Run("Has correct Env vars", func(t *testing.T) { assert.Len(t, c.Env, 1) @@ -168,7 +76,7 @@ func TestMongod_Container(t *testing.T) { }) t.Run("Image is correct", func(t *testing.T) { - assert.Equal(t, getMongoDBImage("4.2"), c.Image) + assert.Equal(t, mongodbImageMock, c.Image) }) t.Run("Resource requirements are correct", func(t *testing.T) { @@ -210,7 +118,7 @@ func assertStatefulSetIsBuiltCorrectly(t *testing.T, mdb mdbv1.MongoDBCommunity, } agentContainer := sts.Spec.Template.Spec.Containers[0] - assert.Equal(t, "agent-image", agentContainer.Image) + assert.Equal(t, "fake-agentImage", agentContainer.Image) probe := agentContainer.ReadinessProbe assert.True(t, reflect.DeepEqual(probes.New(DefaultReadiness()), *probe)) assert.Equal(t, probes.New(DefaultReadiness()).FailureThreshold, probe.FailureThreshold) @@ -231,7 +139,7 @@ func assertStatefulSetIsBuiltCorrectly(t *testing.T, mdb mdbv1.MongoDBCommunity, assertContainsVolumeMountWithName(t, agentContainer.VolumeMounts, "my-rs-keyfile") mongodContainer := sts.Spec.Template.Spec.Containers[1] - assert.Equal(t, "docker.io/mongodb/mongodb-community-server:6.0.5-ubi8", mongodContainer.Image) + assert.Equal(t, "fake-mongodbImage", mongodContainer.Image) assert.Len(t, mongodContainer.VolumeMounts, 6) if !managedSecurityContext { assert.NotNil(t, sts.Spec.Template.Spec.Containers[1].SecurityContext) @@ -248,7 +156,7 @@ func assertStatefulSetIsBuiltCorrectly(t *testing.T, mdb mdbv1.MongoDBCommunity, initContainer := sts.Spec.Template.Spec.InitContainers[0] assert.Equal(t, versionUpgradeHookName, initContainer.Name) - assert.Equal(t, "version-upgrade-hook-image", initContainer.Image) + assert.Equal(t, "fake-versionUpgradeHookImage", initContainer.Image) assert.Len(t, initContainer.VolumeMounts, 1) if !managedSecurityContext { assert.NotNil(t, sts.Spec.Template.Spec.InitContainers[0].SecurityContext) diff --git a/controllers/construct/mongodbstatefulset.go b/controllers/construct/mongodbstatefulset.go index a6a71ff9b..cec2e5be7 100644 --- a/controllers/construct/mongodbstatefulset.go +++ b/controllers/construct/mongodbstatefulset.go @@ -2,12 +2,10 @@ package construct import ( "fmt" - "github.com/mongodb/mongodb-kubernetes-operator/pkg/readiness/config" "os" "strconv" - "strings" - "github.com/mongodb/mongodb-kubernetes-operator/pkg/util/envvar" + "github.com/mongodb/mongodb-kubernetes-operator/pkg/readiness/config" "github.com/mongodb/mongodb-kubernetes-operator/pkg/automationconfig" "github.com/mongodb/mongodb-kubernetes-operator/pkg/kube/container" @@ -28,6 +26,16 @@ var ( OfficialMongodbRepoUrls = []string{"docker.io/mongodb", "quay.io/mongodb"} ) +// Environment variables used to configure the MongoDB StatefulSet. +const ( + MongodbRepoUrlEnv = "MONGODB_REPO_URL" + MongodbImageEnv = "MONGODB_IMAGE" + MongoDBImageTypeEnv = "MDB_IMAGE_TYPE" + AgentImageEnv = "AGENT_IMAGE" + VersionUpgradeHookImageEnv = "VERSION_UPGRADE_HOOK_IMAGE" + ReadinessProbeImageEnv = "READINESS_PROBE_IMAGE" +) + const ( AgentName = "mongodb-agent" MongodbName = "mongod" @@ -42,18 +50,12 @@ const ( mongodbDatabaseServiceAccountName = "mongodb-database" agentHealthStatusFilePathValue = "/var/log/mongodb-mms-automation/healthstatus/agent-health-status.json" - MongodbRepoUrl = "MONGODB_REPO_URL" OfficialMongodbEnterpriseServerImageName = "mongodb-enterprise-server" headlessAgentEnv = "HEADLESS_AGENT" podNamespaceEnv = "POD_NAMESPACE" automationConfigEnv = "AUTOMATION_CONFIG_MAP" - AgentImageEnv = "AGENT_IMAGE" - MongodbImageEnv = "MONGODB_IMAGE" - MongoDBImageType = "MDB_IMAGE_TYPE" MongoDBAssumeEnterpriseEnv = "MDB_ASSUME_ENTERPRISE" - VersionUpgradeHookImageEnv = "VERSION_UPGRADE_HOOK_IMAGE" - ReadinessProbeImageEnv = "READINESS_PROBE_IMAGE" automationMongodConfFileName = "automation-mongod.conf" keyfileFilePath = "/var/lib/mongodb-mms-automation/authentication/keyfile" @@ -123,7 +125,7 @@ type MongoDBStatefulSetOwner interface { // BuildMongoDBReplicaSetStatefulSetModificationFunction builds the parts of the replica set that are common between every resource that implements // MongoDBStatefulSetOwner. // It doesn't configure TLS or additional containers/env vars that the statefulset might need. -func BuildMongoDBReplicaSetStatefulSetModificationFunction(mdb MongoDBStatefulSetOwner, scaler scale.ReplicaSetScaler, agentImage string, withInitContainers bool) statefulset.Modification { +func BuildMongoDBReplicaSetStatefulSetModificationFunction(mdb MongoDBStatefulSetOwner, scaler scale.ReplicaSetScaler, mongodbImage, agentImage, versionUpgradeHookImage, readinessProbeImage string, withInitContainers bool) statefulset.Modification { labels := map[string]string{ "app": mdb.ServiceName(), } @@ -174,8 +176,8 @@ func BuildMongoDBReplicaSetStatefulSetModificationFunction(mdb MongoDBStatefulSe scriptsVolume = statefulset.CreateVolumeFromEmptyDir("agent-scripts") scriptsVolumeMount := statefulset.CreateVolumeMount(scriptsVolume.Name, "/opt/scripts", statefulset.WithReadOnly(false)) - upgradeInitContainer = podtemplatespec.WithInitContainer(versionUpgradeHookName, versionUpgradeHookInit([]corev1.VolumeMount{hooksVolumeMount})) - readinessInitContainer = podtemplatespec.WithInitContainer(ReadinessProbeContainerName, readinessProbeInit([]corev1.VolumeMount{scriptsVolumeMount})) + upgradeInitContainer = podtemplatespec.WithInitContainer(versionUpgradeHookName, versionUpgradeHookInit([]corev1.VolumeMount{hooksVolumeMount}, versionUpgradeHookImage)) + readinessInitContainer = podtemplatespec.WithInitContainer(ReadinessProbeContainerName, readinessProbeInit([]corev1.VolumeMount{scriptsVolumeMount}, readinessProbeImage)) scriptsVolumeMod = podtemplatespec.WithVolume(scriptsVolume) hooksVolumeMod = podtemplatespec.WithVolume(hooksVolume) @@ -243,7 +245,7 @@ func BuildMongoDBReplicaSetStatefulSetModificationFunction(mdb MongoDBStatefulSe podtemplatespec.WithVolume(keyFileVolume), podtemplatespec.WithServiceAccount(mongodbDatabaseServiceAccountName), podtemplatespec.WithContainer(AgentName, mongodbAgentContainer(mdb.AutomationConfigSecretName(), mongodbAgentVolumeMounts, agentLogLevel, agentLogFile, agentMaxLogFileDurationHours, agentImage)), - podtemplatespec.WithContainer(MongodbName, mongodbContainer(mdb.GetMongoDBVersion(nil), mongodVolumeMounts, mdb.GetMongodConfiguration())), + podtemplatespec.WithContainer(MongodbName, mongodbContainer(mongodbImage, mongodVolumeMounts, mdb.GetMongodConfiguration())), upgradeInitContainer, readinessInitContainer, ), @@ -312,12 +314,12 @@ func mongodbAgentContainer(automationConfigSecretName string, volumeMounts []cor ) } -func versionUpgradeHookInit(volumeMount []corev1.VolumeMount) container.Modification { +func versionUpgradeHookInit(volumeMount []corev1.VolumeMount, versionUpgradeHookImage string) container.Modification { _, containerSecurityContext := podtemplatespec.WithDefaultSecurityContextsModifications() return container.Apply( container.WithName(versionUpgradeHookName), container.WithCommand([]string{"cp", "version-upgrade-hook", "/hooks/version-upgrade"}), - container.WithImage(os.Getenv(VersionUpgradeHookImageEnv)), + container.WithImage(versionUpgradeHookImage), container.WithResourceRequirements(resourcerequirements.Defaults()), container.WithImagePullPolicy(corev1.PullAlways), container.WithVolumeMounts(volumeMount), @@ -351,12 +353,12 @@ func logsPvc(logsVolumeName string) persistentvolumeclaim.Modification { // readinessProbeInit returns a modification function which will add the readiness probe container. // this container will copy the readiness probe binary into the /opt/scripts directory. -func readinessProbeInit(volumeMount []corev1.VolumeMount) container.Modification { +func readinessProbeInit(volumeMount []corev1.VolumeMount, readinessProbeImage string) container.Modification { _, containerSecurityContext := podtemplatespec.WithDefaultSecurityContextsModifications() return container.Apply( container.WithName(ReadinessProbeContainerName), container.WithCommand([]string{"cp", "/probes/readinessprobe", "/opt/scripts/readinessprobe"}), - container.WithImage(os.Getenv(ReadinessProbeImageEnv)), + container.WithImage(readinessProbeImage), container.WithImagePullPolicy(corev1.PullAlways), container.WithVolumeMounts(volumeMount), container.WithResourceRequirements(resourcerequirements.Defaults()), @@ -364,25 +366,7 @@ func readinessProbeInit(volumeMount []corev1.VolumeMount) container.Modification ) } -func getMongoDBImage(version string) string { - repoUrl := os.Getenv(MongodbRepoUrl) - imageType := envvar.GetEnvOrDefault(MongoDBImageType, DefaultImageType) - - if strings.HasSuffix(repoUrl, "/") { - repoUrl = strings.TrimRight(repoUrl, "/") - } - mongoImageName := os.Getenv(MongodbImageEnv) - for _, officialUrl := range OfficialMongodbRepoUrls { - if repoUrl == officialUrl { - return fmt.Sprintf("%s/%s:%s-%s", repoUrl, mongoImageName, version, imageType) - } - } - - // This is the old images backwards compatibility code path. - return fmt.Sprintf("%s/%s:%s", repoUrl, mongoImageName, version) -} - -func mongodbContainer(version string, volumeMounts []corev1.VolumeMount, additionalMongoDBConfig mdbv1.MongodConfiguration) container.Modification { +func mongodbContainer(mongodbImage string, volumeMounts []corev1.VolumeMount, additionalMongoDBConfig mdbv1.MongodConfiguration) container.Modification { filePath := additionalMongoDBConfig.GetDBDataDir() + "/" + automationMongodConfFileName mongoDbCommand := fmt.Sprintf(` if [ -e "/hooks/version-upgrade" ]; then @@ -408,7 +392,7 @@ exec mongod -f %s; return container.Apply( container.WithName(MongodbName), - container.WithImage(getMongoDBImage(version)), + container.WithImage(mongodbImage), container.WithResourceRequirements(resourcerequirements.Defaults()), container.WithCommand(containerCommand), // The official image provides both CMD and ENTRYPOINT. We're reusing the former and need to replace diff --git a/controllers/mongodb_cleanup_test.go b/controllers/mongodb_cleanup_test.go index 249556061..0123f63ee 100644 --- a/controllers/mongodb_cleanup_test.go +++ b/controllers/mongodb_cleanup_test.go @@ -2,12 +2,13 @@ package controllers import ( "context" + "testing" + mdbv1 "github.com/mongodb/mongodb-kubernetes-operator/api/v1" kubeClient "github.com/mongodb/mongodb-kubernetes-operator/pkg/kube/client" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "testing" ) func TestReplicaSetReconcilerCleanupScramSecrets(t *testing.T) { @@ -140,7 +141,7 @@ func TestReplicaSetReconcilerCleanupPemSecret(t *testing.T) { err := createAgentCertPemSecret(ctx, client, mdb, "CERT", "KEY", "") assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") secret, err := r.client.GetSecret(ctx, mdb.AgentCertificatePemSecretNamespacedName()) assert.NoError(t, err) diff --git a/controllers/mongodb_tls_test.go b/controllers/mongodb_tls_test.go index f6c21b6b9..b4e832778 100644 --- a/controllers/mongodb_tls_test.go +++ b/controllers/mongodb_tls_test.go @@ -34,7 +34,7 @@ func TestStatefulSetIsCorrectlyConfiguredWithTLS(t *testing.T) { err = createTLSConfigMap(ctx, client, mdb) assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -61,7 +61,7 @@ func TestStatefulSetIsCorrectlyConfiguredWithTLSAndX509(t *testing.T) { err = createAgentCertSecret(ctx, client, mdb, crt, key, "") assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -230,7 +230,7 @@ func TestStatefulSetIsCorrectlyConfiguredWithPrometheusTLS(t *testing.T) { err = createTLSConfigMap(ctx, cli, mdb) assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -259,7 +259,7 @@ func TestStatefulSetIsCorrectlyConfiguredWithTLSAfterChangingExistingVolumes(t * err = createTLSConfigMap(ctx, cli, mdb) assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -301,7 +301,7 @@ func TestAutomationConfigIsCorrectlyConfiguredWithTLS(t *testing.T) { tlsModification, err := getTLSConfigModification(ctx, client, client, mdb) assert.NoError(t, err) - ac, err := buildAutomationConfig(mdb, automationconfig.Auth{}, automationconfig.AutomationConfig{}, tlsModification) + ac, err := buildAutomationConfig(mdb, false, automationconfig.Auth{}, automationconfig.AutomationConfig{}, tlsModification) assert.NoError(t, err) return ac @@ -383,7 +383,7 @@ func TestTLSOperatorSecret(t *testing.T) { err = createTLSConfigMap(ctx, c, mdb) assert.NoError(t, err) - r := NewReconciler(kubeClient.NewManagerWithClient(c)) + r := NewReconciler(kubeClient.NewManagerWithClient(c), "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") err = r.ensureTLSResources(ctx, mdb) assert.NoError(t, err) @@ -413,7 +413,7 @@ func TestTLSOperatorSecret(t *testing.T) { err = k8sclient.CreateSecret(ctx, s) assert.NoError(t, err) - r := NewReconciler(kubeClient.NewManagerWithClient(k8sclient)) + r := NewReconciler(kubeClient.NewManagerWithClient(k8sclient), "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") err = r.ensureTLSResources(ctx, mdb) assert.NoError(t, err) @@ -456,7 +456,7 @@ func TestPemSupport(t *testing.T) { err = createTLSConfigMap(ctx, c, mdb) assert.NoError(t, err) - r := NewReconciler(kubeClient.NewManagerWithClient(c)) + r := NewReconciler(kubeClient.NewManagerWithClient(c), "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") err = r.ensureTLSResources(ctx, mdb) assert.NoError(t, err) @@ -476,7 +476,7 @@ func TestPemSupport(t *testing.T) { err = createTLSConfigMap(ctx, c, mdb) assert.NoError(t, err) - r := NewReconciler(kubeClient.NewManagerWithClient(c)) + r := NewReconciler(kubeClient.NewManagerWithClient(c), "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") err = r.ensureTLSResources(ctx, mdb) assert.NoError(t, err) @@ -496,7 +496,7 @@ func TestPemSupport(t *testing.T) { err = createTLSConfigMap(ctx, c, mdb) assert.NoError(t, err) - r := NewReconciler(kubeClient.NewManagerWithClient(c)) + r := NewReconciler(kubeClient.NewManagerWithClient(c), "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") err = r.ensureTLSResources(ctx, mdb) assert.Error(t, err) @@ -544,7 +544,7 @@ func TestTLSConfigReferencesToCACertAreValidated(t *testing.T) { assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", "fake-agentImage", "fake-versionUpgradeHookImage", "fake-readinessProbeImage") _, err = r.validateTLSConfig(ctx, mdb) if tc.expectedError != nil { diff --git a/controllers/replica_set_controller.go b/controllers/replica_set_controller.go index 325da36aa..d7f2ee65d 100644 --- a/controllers/replica_set_controller.go +++ b/controllers/replica_set_controller.go @@ -60,7 +60,7 @@ func init() { zap.ReplaceGlobals(logger) } -func NewReconciler(mgr manager.Manager) *ReplicaSetReconciler { +func NewReconciler(mgr manager.Manager, mongodbRepoUrl, mongodbImage, mongodbImageType, agentImage, versionUpgradeHookImage, readinessProbeImage string) *ReplicaSetReconciler { mgrClient := mgr.GetClient() secretWatcher := watch.New() configMapWatcher := watch.New() @@ -70,6 +70,13 @@ func NewReconciler(mgr manager.Manager) *ReplicaSetReconciler { log: zap.S(), secretWatcher: &secretWatcher, configMapWatcher: &configMapWatcher, + + mongodbRepoUrl: mongodbRepoUrl, + mongodbImage: mongodbImage, + mongodbImageType: mongodbImageType, + agentImage: agentImage, + versionUpgradeHookImage: versionUpgradeHookImage, + readinessProbeImage: readinessProbeImage, } } @@ -93,6 +100,13 @@ type ReplicaSetReconciler struct { log *zap.SugaredLogger secretWatcher *watch.ResourceWatcher configMapWatcher *watch.ResourceWatcher + + mongodbRepoUrl string + mongodbImage string + mongodbImageType string + agentImage string + versionUpgradeHookImage string + readinessProbeImage string } // +kubebuilder:rbac:groups=mongodbcommunity.mongodb.com,resources=mongodbcommunity,verbs=get;list;watch;create;update;patch;delete @@ -477,7 +491,8 @@ func (r *ReplicaSetReconciler) createOrUpdateStatefulSet(ctx context.Context, md return fmt.Errorf("error getting StatefulSet: %s", err) } - buildStatefulSetModificationFunction(mdb)(&set) + mongodbImage := getMongoDBImage(r.mongodbRepoUrl, r.mongodbImage, r.mongodbImageType, mdb.GetMongoDBVersion(nil)) + buildStatefulSetModificationFunction(mdb, mongodbImage, r.agentImage, r.versionUpgradeHookImage, r.readinessProbeImage)(&set) if isArbiter { buildArbitersModificationFunction(mdb)(&set) } @@ -499,7 +514,7 @@ func (r ReplicaSetReconciler) ensureAutomationConfig(mdb mdbv1.MongoDBCommunity, return automationconfig.EnsureSecret(ctx, r.client, types.NamespacedName{Name: mdb.AutomationConfigSecretName(), Namespace: mdb.Namespace}, mdb.GetOwnerReferences(), ac) } -func buildAutomationConfig(mdb mdbv1.MongoDBCommunity, auth automationconfig.Auth, currentAc automationconfig.AutomationConfig, modifications ...automationconfig.Modification) (automationconfig.AutomationConfig, error) { +func buildAutomationConfig(mdb mdbv1.MongoDBCommunity, isEnterprise bool, auth automationconfig.Auth, currentAc automationconfig.AutomationConfig, modifications ...automationconfig.Modification) (automationconfig.AutomationConfig, error) { domain := getDomain(mdb.ServiceName(), mdb.Namespace, os.Getenv(clusterDomain)) arbiterDomain := getDomain(mdb.ServiceName(), mdb.Namespace, os.Getenv(clusterDomain)) @@ -517,7 +532,7 @@ func buildAutomationConfig(mdb mdbv1.MongoDBCommunity, auth automationconfig.Aut } return automationconfig.NewBuilder(). - IsEnterprise(guessEnterprise(mdb)). + IsEnterprise(isEnterprise). SetTopology(automationconfig.ReplicaSetTopology). SetName(mdb.Name). SetDomain(domain). @@ -541,7 +556,7 @@ func buildAutomationConfig(mdb mdbv1.MongoDBCommunity, auth automationconfig.Aut Build() } -func guessEnterprise(mdb mdbv1.MongoDBCommunity) bool { +func guessEnterprise(mdb mdbv1.MongoDBCommunity, mongodbImage string) bool { overrideAssumption, err := strconv.ParseBool(os.Getenv(construct.MongoDBAssumeEnterpriseEnv)) if err == nil { return overrideAssumption @@ -561,7 +576,7 @@ func guessEnterprise(mdb mdbv1.MongoDBCommunity) bool { if len(overriddenImage) > 0 { return strings.Contains(overriddenImage, construct.OfficialMongodbEnterpriseServerImageName) } - return os.Getenv(construct.MongodbImageEnv) == construct.OfficialMongodbEnterpriseServerImageName + return mongodbImage == construct.OfficialMongodbEnterpriseServerImageName } // buildService creates a Service that will be used for the Replica Set StatefulSet @@ -671,6 +686,7 @@ func (r ReplicaSetReconciler) buildAutomationConfig(ctx context.Context, mdb mdb automationConfig, err := buildAutomationConfig( mdb, + guessEnterprise(mdb, r.mongodbImage), auth, currentAC, tlsModification, @@ -720,16 +736,10 @@ func getMongodConfigModification(mdb mdbv1.MongoDBCommunity) automationconfig.Mo } } -// buildStatefulSet takes a MongoDB resource and converts it into +// buildStatefulSetModificationFunction takes a MongoDB resource and converts it into // the corresponding stateful set -func buildStatefulSet(mdb mdbv1.MongoDBCommunity) (appsv1.StatefulSet, error) { - sts := appsv1.StatefulSet{} - buildStatefulSetModificationFunction(mdb)(&sts) - return sts, nil -} - -func buildStatefulSetModificationFunction(mdb mdbv1.MongoDBCommunity) statefulset.Modification { - commonModification := construct.BuildMongoDBReplicaSetStatefulSetModificationFunction(&mdb, &mdb, os.Getenv(construct.AgentImageEnv), true) +func buildStatefulSetModificationFunction(mdb mdbv1.MongoDBCommunity, mongodbImage, agentImage, versionUpgradeHookImage, readinessProbeImage string) statefulset.Modification { + commonModification := construct.BuildMongoDBReplicaSetStatefulSetModificationFunction(&mdb, &mdb, mongodbImage, agentImage, versionUpgradeHookImage, readinessProbeImage, true) return statefulset.Apply( commonModification, statefulset.WithOwnerReference(mdb.GetOwnerReferences()), @@ -769,3 +779,18 @@ func getDomain(service, namespace, clusterName string) string { func isPreReadinessInitContainerStatefulSet(sts appsv1.StatefulSet) bool { return container.GetByName(construct.ReadinessProbeContainerName, sts.Spec.Template.Spec.InitContainers) == nil } + +func getMongoDBImage(repoUrl, mongodbImage, mongodbImageType, version string) string { + if strings.HasSuffix(repoUrl, "/") { + repoUrl = strings.TrimRight(repoUrl, "/") + } + mongoImageName := mongodbImage + for _, officialUrl := range construct.OfficialMongodbRepoUrls { + if repoUrl == officialUrl { + return fmt.Sprintf("%s/%s:%s-%s", repoUrl, mongoImageName, version, mongodbImageType) + } + } + + // This is the old images backwards compatibility code path. + return fmt.Sprintf("%s/%s:%s", repoUrl, mongoImageName, version) +} diff --git a/controllers/replicaset_controller_test.go b/controllers/replicaset_controller_test.go index da5780d62..d7f2eb8da 100644 --- a/controllers/replicaset_controller_test.go +++ b/controllers/replicaset_controller_test.go @@ -46,9 +46,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -func init() { - os.Setenv(construct.AgentImageEnv, "agent-image") -} +const ( + AgentImage = "fake-agentImage" +) func newTestReplicaSet() mdbv1.MongoDBCommunity { return mdbv1.MongoDBCommunity{ @@ -162,7 +162,7 @@ func TestKubernetesResources_AreCreated(t *testing.T) { mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -178,12 +178,10 @@ func TestKubernetesResources_AreCreated(t *testing.T) { func TestStatefulSet_IsCorrectlyConfigured(t *testing.T) { ctx := context.Background() - t.Setenv(construct.MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(construct.MongodbImageEnv, "mongodb-community-server") mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "docker.io/mongodb", "mongodb-community-server", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -195,7 +193,7 @@ func TestStatefulSet_IsCorrectlyConfigured(t *testing.T) { agentContainer := sts.Spec.Template.Spec.Containers[1] assert.Equal(t, construct.AgentName, agentContainer.Name) - assert.Equal(t, os.Getenv(construct.AgentImageEnv), agentContainer.Image) + assert.Equal(t, AgentImage, agentContainer.Image) expectedProbe := probes.New(construct.DefaultReadiness()) assert.True(t, reflect.DeepEqual(&expectedProbe, agentContainer.ReadinessProbe)) @@ -215,66 +213,42 @@ func TestGuessEnterprise(t *testing.T) { type testConfig struct { setArgs func(t *testing.T) mdb mdbv1.MongoDBCommunity + mongodbImage string expectedEnterprise bool } tests := map[string]testConfig{ "No override and Community image": { - setArgs: func(t *testing.T) { - t.Setenv(construct.MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(construct.MongodbImageEnv, "mongodb-community-server") - }, + setArgs: func(t *testing.T) {}, mdb: mdbv1.MongoDBCommunity{}, + mongodbImage: "mongodb-community-server", expectedEnterprise: false, }, "No override and Enterprise image": { - setArgs: func(t *testing.T) { - t.Setenv(construct.MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(construct.MongodbImageEnv, "mongodb-enterprise-server") - }, + setArgs: func(t *testing.T) {}, mdb: mdbv1.MongoDBCommunity{}, + mongodbImage: "mongodb-enterprise-server", expectedEnterprise: true, }, "Assuming enterprise manually": { setArgs: func(t *testing.T) { - t.Setenv(construct.MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(construct.MongodbImageEnv, "mongodb-community-server") t.Setenv(construct.MongoDBAssumeEnterpriseEnv, "true") }, mdb: mdbv1.MongoDBCommunity{}, + mongodbImage: "mongodb-community-server", expectedEnterprise: true, }, "Assuming community manually": { setArgs: func(t *testing.T) { - t.Setenv(construct.MongodbRepoUrl, "docker.io/mongodb") - t.Setenv(construct.MongodbImageEnv, "mongodb-enterprise-server") t.Setenv(construct.MongoDBAssumeEnterpriseEnv, "false") }, mdb: mdbv1.MongoDBCommunity{}, - expectedEnterprise: false, - }, - "Enterprise with different repo": { - setArgs: func(t *testing.T) { - t.Setenv(construct.MongodbRepoUrl, "some_other_repo.com/some_other_org") - t.Setenv(construct.MongodbImageEnv, "mongodb-enterprise-server") - }, - mdb: mdbv1.MongoDBCommunity{}, - expectedEnterprise: true, - }, - "Community with different repo": { - setArgs: func(t *testing.T) { - t.Setenv(construct.MongodbRepoUrl, "some_other_repo.com/some_other_org") - t.Setenv(construct.MongodbImageEnv, "mongodb-community-server") - }, - mdb: mdbv1.MongoDBCommunity{}, + mongodbImage: "mongodb-enterprise-server", expectedEnterprise: false, }, // This one is a corner case. We don't expect users to fall here very often as there are // dedicated variables to control this type of behavior. "Enterprise with StatefulSet override": { - setArgs: func(t *testing.T) { - t.Setenv(construct.MongodbRepoUrl, "some_other_repo.com/some_other_org") - t.Setenv(construct.MongodbImageEnv, "mongodb-community-server") - }, + setArgs: func(t *testing.T) {}, mdb: mdbv1.MongoDBCommunity{ Spec: mdbv1.MongoDBCommunitySpec{ StatefulSetConfiguration: mdbv1.StatefulSetConfiguration{ @@ -295,13 +269,11 @@ func TestGuessEnterprise(t *testing.T) { }, }, }, + mongodbImage: "mongodb-community-server", expectedEnterprise: true, }, "Enterprise with StatefulSet override to Community": { - setArgs: func(t *testing.T) { - t.Setenv(construct.MongodbRepoUrl, "some_other_repo.com/some_other_org") - t.Setenv(construct.MongodbImageEnv, "mongodb-enterprise-server") - }, + setArgs: func(t *testing.T) {}, mdb: mdbv1.MongoDBCommunity{ Spec: mdbv1.MongoDBCommunitySpec{ StatefulSetConfiguration: mdbv1.StatefulSetConfiguration{ @@ -322,6 +294,7 @@ func TestGuessEnterprise(t *testing.T) { }, }, }, + mongodbImage: "mongodb-enterprise-server", expectedEnterprise: false, }, } @@ -329,7 +302,7 @@ func TestGuessEnterprise(t *testing.T) { t.Run(testName, func(t *testing.T) { testConfig := tests[testName] testConfig.setArgs(t) - calculatedEnterprise := guessEnterprise(testConfig.mdb) + calculatedEnterprise := guessEnterprise(testConfig.mdb, testConfig.mongodbImage) assert.Equal(t, testConfig.expectedEnterprise, calculatedEnterprise) }) } @@ -349,7 +322,7 @@ func TestChangingVersion_ResultsInRollingUpdateStrategyType(t *testing.T) { mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) mgrClient := mgr.GetClient() - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: mdb.NamespacedName()}) assertReconciliationSuccessful(t, res, err) @@ -390,16 +363,16 @@ func TestBuildStatefulSet_ConfiguresUpdateStrategyCorrectly(t *testing.T) { mdb := newTestReplicaSet() mdb.Spec.Version = "4.0.0" mdb.Annotations[annotations.LastAppliedMongoDBVersion] = "4.0.0" - sts, err := buildStatefulSet(mdb) - assert.NoError(t, err) + sts := appsv1.StatefulSet{} + buildStatefulSetModificationFunction(mdb, "fake-mongodbImage", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage")(&sts) assert.Equal(t, appsv1.RollingUpdateStatefulSetStrategyType, sts.Spec.UpdateStrategy.Type) }) t.Run("On No Version Change, First Version", func(t *testing.T) { mdb := newTestReplicaSet() mdb.Spec.Version = "4.0.0" delete(mdb.Annotations, annotations.LastAppliedMongoDBVersion) - sts, err := buildStatefulSet(mdb) - assert.NoError(t, err) + sts := appsv1.StatefulSet{} + buildStatefulSetModificationFunction(mdb, "fake-mongodbImage", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage")(&sts) assert.Equal(t, appsv1.RollingUpdateStatefulSetStrategyType, sts.Spec.UpdateStrategy.Type) }) t.Run("On Version Change", func(t *testing.T) { @@ -415,9 +388,8 @@ func TestBuildStatefulSet_ConfiguresUpdateStrategyCorrectly(t *testing.T) { assert.NoError(t, err) mdb.Annotations[annotations.LastAppliedMongoDBVersion] = string(bytes) - sts, err := buildStatefulSet(mdb) - - assert.NoError(t, err) + sts := appsv1.StatefulSet{} + buildStatefulSetModificationFunction(mdb, "fake-mongodbImage", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage")(&sts) assert.Equal(t, appsv1.OnDeleteStatefulSetStrategyType, sts.Spec.UpdateStrategy.Type) }) } @@ -427,7 +399,7 @@ func TestService_isCorrectlyCreatedAndUpdated(t *testing.T) { mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -452,7 +424,7 @@ func TestService_usesCustomMongodPortWhenSpecified(t *testing.T) { mdb.Spec.AdditionalMongodConfig.Object = mongodConfig mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -516,7 +488,7 @@ func TestService_changesMongodPortOnRunningClusterWithArbiters(t *testing.T) { mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") t.Run("Prepare cluster with arbiters and change port", func(t *testing.T) { err := createUserPasswordSecret(ctx, mgr.Client, mdb, "password-secret-name", "pass") @@ -745,7 +717,7 @@ func TestService_configuresPrometheusCustomPorts(t *testing.T) { Build()) assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -782,7 +754,7 @@ func TestService_configuresPrometheus(t *testing.T) { Build()) assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -808,7 +780,7 @@ func TestAutomationConfig_versionIsBumpedOnChange(t *testing.T) { mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -833,7 +805,7 @@ func TestAutomationConfig_versionIsNotBumpedWithNoChanges(t *testing.T) { mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -854,7 +826,7 @@ func TestAutomationConfigFCVIsNotIncreasedWhenUpgradingMinorVersion(t *testing.T mdb := newTestReplicaSet() mdb.Spec.Version = "4.2.2" mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -888,7 +860,7 @@ func TestAutomationConfig_CustomMongodConfig(t *testing.T) { mdb.Spec.AdditionalMongodConfig.Object = mongodConfig mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -932,7 +904,7 @@ func TestExistingPasswordAndKeyfile_AreUsedWhenTheSecretExists(t *testing.T) { Build()) assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -963,7 +935,7 @@ func TestReplicaSet_IsScaledDown_OneMember_AtATime_WhenItAlreadyExists(t *testin mdb.Spec.Members = 5 mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -1008,7 +980,7 @@ func TestReplicaSet_IsScaledUp_OneMember_AtATime_WhenItAlreadyExists(t *testing. mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -1078,7 +1050,7 @@ func TestAnnotationsAreAppliedToResource(t *testing.T) { mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -1094,7 +1066,7 @@ func TestAnnotationsAreAppliedToResource(t *testing.T) { // results in the AuthoritativeSet of the created AutomationConfig to have the expectedValue provided. func assertAuthoritativeSet(ctx context.Context, t *testing.T, mdb mdbv1.MongoDBCommunity, expectedValue bool) { mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -1110,7 +1082,7 @@ func assertAuthoritativeSet(ctx context.Context, t *testing.T, mdb mdbv1.MongoDB func assertReplicaSetIsConfiguredWithScram(ctx context.Context, t *testing.T, mdb mdbv1.MongoDBCommunity) { mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -1144,7 +1116,7 @@ func assertReplicaSetIsConfiguredWithScramTLS(ctx context.Context, t *testing.T, assert.NoError(t, err) err = createTLSConfigMap(ctx, newClient, mdb) assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -1184,7 +1156,7 @@ func assertReplicaSetIsConfiguredWithX509(ctx context.Context, t *testing.T, mdb err = createAgentCertSecret(ctx, newClient, mdb, crt, key, "") assert.NoError(t, err) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -1244,7 +1216,7 @@ func TestReplicaSet_IsScaledUpToDesiredMembers_WhenFirstCreated(t *testing.T) { mdb := newTestReplicaSet() mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assertReconciliationSuccessful(t, res, err) @@ -1347,7 +1319,7 @@ func TestInconsistentReplicas(t *testing.T) { mdb.Spec.Members = 4 mgr := client.NewManager(ctx, &mdb) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") _, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Namespace: mdb.Namespace, Name: mdb.Name}}) assert.NoError(t, err) } @@ -1367,7 +1339,7 @@ func performReconciliationAndGetStatefulSet(ctx context.Context, t *testing.T, f assert.NoError(t, err) mgr := client.NewManager(ctx, &mdb) assert.NoError(t, generatePasswordsForAllUsers(ctx, mdb, mgr.Client)) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: mdb.NamespacedName()}) assertReconciliationSuccessful(t, res, err) @@ -1381,7 +1353,7 @@ func performReconciliationAndGetService(ctx context.Context, t *testing.T, fileP assert.NoError(t, err) mgr := client.NewManager(ctx, &mdb) assert.NoError(t, generatePasswordsForAllUsers(ctx, mdb, mgr.Client)) - r := NewReconciler(mgr) + r := NewReconciler(mgr, "fake-mongodbRepoUrl", "fake-mongodbImage", "ubi8", AgentImage, "fake-versionUpgradeHookImage", "fake-readinessProbeImage") res, err := r.Reconcile(ctx, reconcile.Request{NamespacedName: mdb.NamespacedName()}) assertReconciliationSuccessful(t, res, err) svc, err := mgr.Client.GetService(ctx, types.NamespacedName{Name: mdb.ServiceName(), Namespace: mdb.Namespace}) @@ -1468,3 +1440,74 @@ func marshalRuntimeObjectFromYAMLBytes(bytes []byte, obj runtime.Object) error { } return json.Unmarshal(jsonBytes, &obj) } + +func TestGetMongoDBImage(t *testing.T) { + type testConfig struct { + mongodbRepoUrl string + mongodbImage string + mongodbImageType string + version string + expectedImage string + } + tests := map[string]testConfig{ + "Default UBI8 Community image": { + mongodbRepoUrl: "docker.io/mongodb", + mongodbImage: "mongodb-community-server", + mongodbImageType: "ubi8", + version: "6.0.5", + expectedImage: "docker.io/mongodb/mongodb-community-server:6.0.5-ubi8", + }, + "Overridden UBI8 Enterprise image": { + mongodbRepoUrl: "docker.io/mongodb", + mongodbImage: "mongodb-enterprise-server", + mongodbImageType: "ubi8", + version: "6.0.5", + expectedImage: "docker.io/mongodb/mongodb-enterprise-server:6.0.5-ubi8", + }, + "Overridden UBI8 Enterprise image from Quay": { + mongodbRepoUrl: "quay.io/mongodb", + mongodbImage: "mongodb-enterprise-server", + mongodbImageType: "ubi8", + version: "6.0.5", + expectedImage: "quay.io/mongodb/mongodb-enterprise-server:6.0.5-ubi8", + }, + "Overridden Ubuntu Community image": { + mongodbRepoUrl: "docker.io/mongodb", + mongodbImage: "mongodb-community-server", + mongodbImageType: "ubuntu2204", + version: "6.0.5", + expectedImage: "docker.io/mongodb/mongodb-community-server:6.0.5-ubuntu2204", + }, + "Overridden UBI Community image": { + mongodbRepoUrl: "docker.io/mongodb", + mongodbImage: "mongodb-community-server", + mongodbImageType: "ubi8", + version: "6.0.5", + expectedImage: "docker.io/mongodb/mongodb-community-server:6.0.5-ubi8", + }, + "Docker Inc images": { + mongodbRepoUrl: "docker.io", + mongodbImage: "mongo", + mongodbImageType: "ubi8", + version: "6.0.5", + expectedImage: "docker.io/mongo:6.0.5", + }, + "Deprecated AppDB images defined the old way": { + mongodbRepoUrl: "quay.io", + mongodbImage: "mongodb/mongodb-enterprise-appdb-database-ubi", + // In this example, we intentionally don't use the suffix from the env. variable and let users + // define it in the version instead. There are some known customers who do this. + // This is a backwards compatibility case. + mongodbImageType: "will-be-ignored", + version: "5.0.14-ent", + expectedImage: "quay.io/mongodb/mongodb-enterprise-appdb-database-ubi:5.0.14-ent", + }, + } + for testName := range tests { + t.Run(testName, func(t *testing.T) { + testConfig := tests[testName] + image := getMongoDBImage(testConfig.mongodbRepoUrl, testConfig.mongodbImage, testConfig.mongodbImageType, testConfig.version) + assert.Equal(t, testConfig.expectedImage, image) + }) + } +} diff --git a/test/e2e/replica_set_enterprise_upgrade/replica_set_enterprise_upgrade.go b/test/e2e/replica_set_enterprise_upgrade/replica_set_enterprise_upgrade.go index d8c0bfb23..ff6930252 100644 --- a/test/e2e/replica_set_enterprise_upgrade/replica_set_enterprise_upgrade.go +++ b/test/e2e/replica_set_enterprise_upgrade/replica_set_enterprise_upgrade.go @@ -7,14 +7,14 @@ import ( "time" "github.com/mongodb/mongodb-kubernetes-operator/controllers/construct" - "github.com/mongodb/mongodb-kubernetes-operator/test/e2e" + e2eutil "github.com/mongodb/mongodb-kubernetes-operator/test/e2e" "github.com/mongodb/mongodb-kubernetes-operator/test/e2e/mongodbtests" "github.com/mongodb/mongodb-kubernetes-operator/test/e2e/setup" "github.com/mongodb/mongodb-kubernetes-operator/test/e2e/util/mongotester" ) func DeployEnterpriseAndUpgradeTest(ctx context.Context, t *testing.T, versionsToBeTested []string) { - t.Setenv(construct.MongodbRepoUrl, "docker.io/mongodb") + t.Setenv(construct.MongodbRepoUrlEnv, "docker.io/mongodb") t.Setenv(construct.MongodbImageEnv, "mongodb-enterprise-server") testCtx := setup.Setup(ctx, t) defer testCtx.Teardown() diff --git a/test/e2e/setup/test_config.go b/test/e2e/setup/test_config.go index 06f2018fe..d4b2ab8c1 100644 --- a/test/e2e/setup/test_config.go +++ b/test/e2e/setup/test_config.go @@ -39,7 +39,7 @@ func LoadTestConfigFromEnv() TestConfig { CertManagerVersion: envvar.GetEnvOrDefault(testCertManagerVersionEnvName, "v1.5.3"), OperatorImage: envvar.GetEnvOrDefault(operatorImageEnvName, "quay.io/mongodb/community-operator-dev:latest"), MongoDBImage: envvar.GetEnvOrDefault(construct.MongodbImageEnv, "mongodb-community-server"), - MongoDBRepoUrl: envvar.GetEnvOrDefault(construct.MongodbRepoUrl, "quay.io/mongodb"), + MongoDBRepoUrl: envvar.GetEnvOrDefault(construct.MongodbRepoUrlEnv, "quay.io/mongodb"), VersionUpgradeHookImage: envvar.GetEnvOrDefault(construct.VersionUpgradeHookImageEnv, "quay.io/mongodb/mongodb-kubernetes-operator-version-upgrade-post-start-hook:1.0.2"), AgentImage: envvar.GetEnvOrDefault(construct.AgentImageEnv, "quay.io/mongodb/mongodb-agent-ubi:10.29.0.6830-1"), // TODO: better way to decide default agent image. ClusterWide: envvar.ReadBool(clusterWideEnvName),