diff --git a/controllers/operator/mongodbsearch_controller_test.go b/controllers/operator/mongodbsearch_controller_test.go index 93e9f4abf..72590c8d3 100644 --- a/controllers/operator/mongodbsearch_controller_test.go +++ b/controllers/operator/mongodbsearch_controller_test.go @@ -27,6 +27,7 @@ import ( "github.com/mongodb/mongodb-kubernetes/controllers/operator/workflow" "github.com/mongodb/mongodb-kubernetes/controllers/search_controller" mdbcv1 "github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/api/v1" + "github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/api/v1/common" "github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/pkg/mongot" ) @@ -52,8 +53,9 @@ func newMongoDBSearch(name, namespace, mdbcName string) *searchv1.MongoDBSearch } } -func newSearchReconciler( +func newSearchReconcilerWithOperatorConfig( mdbc *mdbcv1.MongoDBCommunity, + operatorConfig search_controller.OperatorSearchConfig, searches ...*searchv1.MongoDBSearch, ) (*MongoDBSearchReconciler, client.Client) { builder := mock.NewEmptyFakeClientBuilder() @@ -70,7 +72,15 @@ func newSearchReconciler( } fakeClient := builder.Build() - return newMongoDBSearchReconciler(fakeClient, search_controller.OperatorSearchConfig{}), fakeClient + + return newMongoDBSearchReconciler(fakeClient, operatorConfig), fakeClient +} + +func newSearchReconciler( + mdbc *mdbcv1.MongoDBCommunity, + searches ...*searchv1.MongoDBSearch, +) (*MongoDBSearchReconciler, client.Client) { + return newSearchReconcilerWithOperatorConfig(mdbc, search_controller.OperatorSearchConfig{}, searches...) } func buildExpectedMongotConfig(search *searchv1.MongoDBSearch, mdbc *mdbcv1.MongoDBCommunity) mongot.Config { @@ -228,3 +238,60 @@ func TestMongoDBSearchReconcile_MultipleSearchResources(t *testing.T) { checkSearchReconcileFailed(ctx, t, reconciler, c, search1, "multiple MongoDBSearch") } + +func TestMongoDBSearchReconcile_InvalidSearchImageVersion(t *testing.T) { + ctx := context.Background() + expectedMsg := "MongoDBSearch version 1.47.0 is not supported because of breaking changes. The operator will ignore this resource: it will not reconcile or reconfigure the workload. Existing deployments will continue to run, but cannot be managed by the operator. To regain operator management, you must delete and recreate the MongoDBSearch resource." + + tests := []struct { + name string + specVersion string + operatorVersion string + statefulSetConfig *common.StatefulSetConfiguration + }{ + { + name: "unsupported version in Spec.Version", + specVersion: "1.47.0", + }, + { + name: "unsupported version in operator config", + operatorVersion: "1.47.0", + }, + { + name: "unsupported version in StatefulSetConfiguration", + statefulSetConfig: &common.StatefulSetConfiguration{ + SpecWrapper: common.StatefulSetSpecWrapper{ + Spec: appsv1.StatefulSetSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: search_controller.MongotContainerName, + Image: "testrepo/mongot:1.47.0", + }, + }, + }, + }, + }, + }, + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + search := newMongoDBSearch("search", mock.TestNamespace, "mdb") + mdbc := newMongoDBCommunity("mdb", mock.TestNamespace) + + search.Spec.Version = tc.specVersion + search.Spec.StatefulSetConfiguration = tc.statefulSetConfig + + operatorConfig := search_controller.OperatorSearchConfig{ + SearchVersion: tc.operatorVersion, + } + reconciler, _ := newSearchReconcilerWithOperatorConfig(mdbc, operatorConfig, search) + + checkSearchReconcileFailed(ctx, t, reconciler, reconciler.kubeClient, search, expectedMsg) + }) + } +} diff --git a/controllers/search_controller/mongodbsearch_reconcile_helper.go b/controllers/search_controller/mongodbsearch_reconcile_helper.go index 6c80806e4..9c0db2849 100644 --- a/controllers/search_controller/mongodbsearch_reconcile_helper.go +++ b/controllers/search_controller/mongodbsearch_reconcile_helper.go @@ -35,7 +35,12 @@ import ( ) const ( - MongoDBSearchIndexFieldName = "mdbsearch-for-mongodbresourceref-index" + MongoDBSearchIndexFieldName = "mdbsearch-for-mongodbresourceref-index" + unsupportedSearchVersion = "1.47.0" + unsupportedSearchVersionErrorFmt = "MongoDBSearch version %s is not supported because of breaking changes. " + + "The operator will ignore this resource: it will not reconcile or reconfigure the workload. " + + "Existing deployments will continue to run, but cannot be managed by the operator. " + + "To regain operator management, you must delete and recreate the MongoDBSearch resource." ) type OperatorSearchConfig struct { @@ -81,6 +86,10 @@ func (r *MongoDBSearchReconcileHelper) reconcile(ctx context.Context, log *zap.S return workflow.Failed(err) } + if err := r.ValidateSearchImageVersion(); err != nil { + return workflow.Failed(err) + } + if err := r.ValidateSingleMongoDBSearchForSearchSource(ctx); err != nil { return workflow.Failed(err) } @@ -402,8 +411,44 @@ func (r *MongoDBSearchReconcileHelper) ValidateSingleMongoDBSearchForSearchSourc for i, search := range searchList.Items { resourceNames[i] = search.Name } - return xerrors.Errorf("Found multiple MongoDBSearch resources for search source '%s': %s", r.db.Name(), strings.Join(resourceNames, ", ")) + return xerrors.Errorf( + "Found multiple MongoDBSearch resources for search source '%s': %s", r.db.Name(), + strings.Join(resourceNames, ", "), + ) + } + + return nil +} + +func (r *MongoDBSearchReconcileHelper) ValidateSearchImageVersion() error { + version := r.getMongotImage() + + if strings.Contains(version, unsupportedSearchVersion) { + return xerrors.Errorf(unsupportedSearchVersionErrorFmt, unsupportedSearchVersion) } return nil } + +func (r *MongoDBSearchReconcileHelper) getMongotImage() string { + version := strings.TrimSpace(r.mdbSearch.Spec.Version) + if version != "" { + return version + } + + if r.operatorSearchConfig.SearchVersion != "" { + return r.operatorSearchConfig.SearchVersion + } + + if r.mdbSearch.Spec.StatefulSetConfiguration == nil { + return "" + } + + for _, container := range r.mdbSearch.Spec.StatefulSetConfiguration.SpecWrapper.Spec.Template.Spec.Containers { + if container.Name == MongotContainerName { + return container.Image + } + } + + return "" +}