Skip to content

Commit bfab8ae

Browse files
authored
Merge branch 'search/public-preview' into lsierant/search-snippets-update
2 parents dbe30cb + 6e11713 commit bfab8ae

File tree

5 files changed

+178
-30
lines changed

5 files changed

+178
-30
lines changed

api/v1/search/mongodbsearch_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
const (
1919
MongotDefaultPort = 27027
2020
MongotDefaultMetricsPort = 9946
21+
MongotDefautHealthCheckPort = 8080
2122
MongotDefaultSyncSourceUsername = "search-sync-source"
2223
)
2324

@@ -189,3 +190,7 @@ func (s *MongoDBSearch) TLSSecretNamespacedName() types.NamespacedName {
189190
func (s *MongoDBSearch) TLSOperatorSecretNamespacedName() types.NamespacedName {
190191
return types.NamespacedName{Name: s.Name + "-search-certificate-key", Namespace: s.Namespace}
191192
}
193+
194+
func (s *MongoDBSearch) GetMongotHealthCheckPort() int32 {
195+
return MongotDefautHealthCheckPort
196+
}

controllers/operator/mongodbsearch_controller_test.go

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/mongodb/mongodb-kubernetes/controllers/operator/workflow"
2828
"github.com/mongodb/mongodb-kubernetes/controllers/search_controller"
2929
mdbcv1 "github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/api/v1"
30+
"github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/api/v1/common"
3031
"github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/pkg/mongot"
3132
)
3233

@@ -36,7 +37,7 @@ func newMongoDBCommunity(name, namespace string) *mdbcv1.MongoDBCommunity {
3637
Spec: mdbcv1.MongoDBCommunitySpec{
3738
Type: mdbcv1.ReplicaSet,
3839
Members: 1,
39-
Version: "8.0",
40+
Version: "8.0.10",
4041
},
4142
}
4243
}
@@ -52,8 +53,9 @@ func newMongoDBSearch(name, namespace, mdbcName string) *searchv1.MongoDBSearch
5253
}
5354
}
5455

55-
func newSearchReconciler(
56+
func newSearchReconcilerWithOperatorConfig(
5657
mdbc *mdbcv1.MongoDBCommunity,
58+
operatorConfig search_controller.OperatorSearchConfig,
5759
searches ...*searchv1.MongoDBSearch,
5860
) (*MongoDBSearchReconciler, client.Client) {
5961
builder := mock.NewEmptyFakeClientBuilder()
@@ -70,7 +72,15 @@ func newSearchReconciler(
7072
}
7173

7274
fakeClient := builder.Build()
73-
return newMongoDBSearchReconciler(fakeClient, search_controller.OperatorSearchConfig{}), fakeClient
75+
76+
return newMongoDBSearchReconciler(fakeClient, operatorConfig), fakeClient
77+
}
78+
79+
func newSearchReconciler(
80+
mdbc *mdbcv1.MongoDBCommunity,
81+
searches ...*searchv1.MongoDBSearch,
82+
) (*MongoDBSearchReconciler, client.Client) {
83+
return newSearchReconcilerWithOperatorConfig(mdbc, search_controller.OperatorSearchConfig{}, searches...)
7484
}
7585

7686
func buildExpectedMongotConfig(search *searchv1.MongoDBSearch, mdbc *mdbcv1.MongoDBCommunity) mongot.Config {
@@ -99,15 +109,15 @@ func buildExpectedMongotConfig(search *searchv1.MongoDBSearch, mdbc *mdbcv1.Mong
99109
Mode: "keyfile",
100110
KeyFile: "/tmp/keyfile",
101111
},
102-
TLS: mongot.ConfigTLS{Mode: "disabled"},
112+
TLS: mongot.ConfigTLS{Mode: mongot.ConfigTLSModeDisabled},
103113
},
104114
},
105115
Metrics: mongot.ConfigMetrics{
106116
Enabled: true,
107-
Address: fmt.Sprintf("localhost:%d", searchv1.MongotDefaultMetricsPort),
117+
Address: fmt.Sprintf("0.0.0.0:%d", search.GetMongotMetricsPort()),
108118
},
109119
HealthCheck: mongot.ConfigHealthCheck{
110-
Address: "0.0.0.0:8080",
120+
Address: fmt.Sprintf("0.0.0.0:%d", search.GetMongotHealthCheckPort()),
111121
},
112122
Logging: mongot.ConfigLogging{
113123
Verbosity: "TRACE",
@@ -210,16 +220,6 @@ func TestMongoDBSearchReconcile_InvalidVersion(t *testing.T) {
210220
checkSearchReconcileFailed(ctx, t, reconciler, c, search, "MongoDB version")
211221
}
212222

213-
func TestMongoDBSearchReconcile_TLSNotSupported(t *testing.T) {
214-
ctx := context.Background()
215-
search := newMongoDBSearch("search", mock.TestNamespace, "mdb")
216-
mdbc := newMongoDBCommunity("mdb", mock.TestNamespace)
217-
mdbc.Spec.Security.TLS.Enabled = true
218-
reconciler, c := newSearchReconciler(mdbc, search)
219-
220-
checkSearchReconcileFailed(ctx, t, reconciler, c, search, "TLS-enabled")
221-
}
222-
223223
func TestMongoDBSearchReconcile_MultipleSearchResources(t *testing.T) {
224224
ctx := context.Background()
225225
search1 := newMongoDBSearch("search1", mock.TestNamespace, "mdb")
@@ -229,3 +229,60 @@ func TestMongoDBSearchReconcile_MultipleSearchResources(t *testing.T) {
229229

230230
checkSearchReconcileFailed(ctx, t, reconciler, c, search1, "multiple MongoDBSearch")
231231
}
232+
233+
func TestMongoDBSearchReconcile_InvalidSearchImageVersion(t *testing.T) {
234+
ctx := context.Background()
235+
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."
236+
237+
tests := []struct {
238+
name string
239+
specVersion string
240+
operatorVersion string
241+
statefulSetConfig *common.StatefulSetConfiguration
242+
}{
243+
{
244+
name: "unsupported version in Spec.Version",
245+
specVersion: "1.47.0",
246+
},
247+
{
248+
name: "unsupported version in operator config",
249+
operatorVersion: "1.47.0",
250+
},
251+
{
252+
name: "unsupported version in StatefulSetConfiguration",
253+
statefulSetConfig: &common.StatefulSetConfiguration{
254+
SpecWrapper: common.StatefulSetSpecWrapper{
255+
Spec: appsv1.StatefulSetSpec{
256+
Template: corev1.PodTemplateSpec{
257+
Spec: corev1.PodSpec{
258+
Containers: []corev1.Container{
259+
{
260+
Name: search_controller.MongotContainerName,
261+
Image: "testrepo/mongot:1.47.0",
262+
},
263+
},
264+
},
265+
},
266+
},
267+
},
268+
},
269+
},
270+
}
271+
272+
for _, tc := range tests {
273+
t.Run(tc.name, func(t *testing.T) {
274+
search := newMongoDBSearch("search", mock.TestNamespace, "mdb")
275+
mdbc := newMongoDBCommunity("mdb", mock.TestNamespace)
276+
277+
search.Spec.Version = tc.specVersion
278+
search.Spec.StatefulSetConfiguration = tc.statefulSetConfig
279+
280+
operatorConfig := search_controller.OperatorSearchConfig{
281+
SearchVersion: tc.operatorVersion,
282+
}
283+
reconciler, _ := newSearchReconcilerWithOperatorConfig(mdbc, operatorConfig, search)
284+
285+
checkSearchReconcileFailed(ctx, t, reconciler, reconciler.kubeClient, search, expectedMsg)
286+
})
287+
}
288+
}

controllers/search_controller/mongodbsearch_reconcile_helper.go

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ import (
3535
)
3636

3737
const (
38-
MongoDBSearchIndexFieldName = "mdbsearch-for-mongodbresourceref-index"
38+
MongoDBSearchIndexFieldName = "mdbsearch-for-mongodbresourceref-index"
39+
unsupportedSearchVersion = "1.47.0"
40+
unsupportedSearchVersionErrorFmt = "MongoDBSearch version %s is not supported because of breaking changes. " +
41+
"The operator will ignore this resource: it will not reconcile or reconfigure the workload. " +
42+
"Existing deployments will continue to run, but cannot be managed by the operator. " +
43+
"To regain operator management, you must delete and recreate the MongoDBSearch resource."
3944
)
4045

4146
type OperatorSearchConfig struct {
@@ -81,6 +86,10 @@ func (r *MongoDBSearchReconcileHelper) reconcile(ctx context.Context, log *zap.S
8186
return workflow.Failed(err)
8287
}
8388

89+
if err := r.ValidateSearchImageVersion(); err != nil {
90+
return workflow.Failed(err)
91+
}
92+
8493
if err := r.ValidateSingleMongoDBSearchForSearchSource(ctx); err != nil {
8594
return workflow.Failed(err)
8695
}
@@ -313,6 +322,13 @@ func buildSearchHeadlessService(search *searchv1.MongoDBSearch) corev1.Service {
313322
TargetPort: intstr.FromInt32(search.GetMongotMetricsPort()),
314323
})
315324

325+
serviceBuilder.AddPort(&corev1.ServicePort{
326+
Name: "healthcheck",
327+
Protocol: corev1.ProtocolTCP,
328+
Port: search.GetMongotHealthCheckPort(),
329+
TargetPort: intstr.FromInt32(search.GetMongotHealthCheckPort()),
330+
})
331+
316332
return serviceBuilder.Build()
317333
}
318334

@@ -347,10 +363,10 @@ func createMongotConfig(search *searchv1.MongoDBSearch, db SearchSourceDBResourc
347363
}
348364
config.Metrics = mongot.ConfigMetrics{
349365
Enabled: true,
350-
Address: fmt.Sprintf("localhost:%d", search.GetMongotMetricsPort()),
366+
Address: fmt.Sprintf("0.0.0.0:%d", search.GetMongotMetricsPort()),
351367
}
352368
config.HealthCheck = mongot.ConfigHealthCheck{
353-
Address: "0.0.0.0:8080",
369+
Address: fmt.Sprintf("0.0.0.0:%d", search.GetMongotHealthCheckPort()),
354370
}
355371
config.Logging = mongot.ConfigLogging{
356372
Verbosity: "TRACE",
@@ -403,8 +419,44 @@ func (r *MongoDBSearchReconcileHelper) ValidateSingleMongoDBSearchForSearchSourc
403419
for i, search := range searchList.Items {
404420
resourceNames[i] = search.Name
405421
}
406-
return xerrors.Errorf("Found multiple MongoDBSearch resources for search source '%s': %s", r.db.Name(), strings.Join(resourceNames, ", "))
422+
return xerrors.Errorf(
423+
"Found multiple MongoDBSearch resources for search source '%s': %s", r.db.Name(),
424+
strings.Join(resourceNames, ", "),
425+
)
426+
}
427+
428+
return nil
429+
}
430+
431+
func (r *MongoDBSearchReconcileHelper) ValidateSearchImageVersion() error {
432+
version := r.getMongotImage()
433+
434+
if strings.Contains(version, unsupportedSearchVersion) {
435+
return xerrors.Errorf(unsupportedSearchVersionErrorFmt, unsupportedSearchVersion)
407436
}
408437

409438
return nil
410439
}
440+
441+
func (r *MongoDBSearchReconcileHelper) getMongotImage() string {
442+
version := strings.TrimSpace(r.mdbSearch.Spec.Version)
443+
if version != "" {
444+
return version
445+
}
446+
447+
if r.operatorSearchConfig.SearchVersion != "" {
448+
return r.operatorSearchConfig.SearchVersion
449+
}
450+
451+
if r.mdbSearch.Spec.StatefulSetConfiguration == nil {
452+
return ""
453+
}
454+
455+
for _, container := range r.mdbSearch.Spec.StatefulSetConfiguration.SpecWrapper.Spec.Template.Spec.Containers {
456+
if container.Name == MongotContainerName {
457+
return container.Image
458+
}
459+
}
460+
461+
return ""
462+
}

controllers/search_controller/mongodbsearch_reconcile_helper_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ func TestMongoDBSearchReconcileHelper_ValidateSearchSource(t *testing.T) {
3434
Version: "4.4.0",
3535
},
3636
},
37-
expectedError: "MongoDB version must be 8.0 or higher",
37+
expectedError: "MongoDB version must be 8.0.10 or higher",
3838
},
3939
{
4040
name: "Valid version",
4141
mdbc: mdbcv1.MongoDBCommunity{
4242
ObjectMeta: mdbcMeta,
4343
Spec: mdbcv1.MongoDBCommunitySpec{
44-
Version: "8.0",
44+
Version: "8.0.10",
4545
},
4646
},
4747
},
@@ -50,15 +50,14 @@ func TestMongoDBSearchReconcileHelper_ValidateSearchSource(t *testing.T) {
5050
mdbc: mdbcv1.MongoDBCommunity{
5151
ObjectMeta: mdbcMeta,
5252
Spec: mdbcv1.MongoDBCommunitySpec{
53-
Version: "8.0",
53+
Version: "8.0.10",
5454
Security: mdbcv1.Security{
5555
TLS: mdbcv1.TLS{
5656
Enabled: true,
5757
},
5858
},
5959
},
6060
},
61-
expectedError: "MongoDBSearch does not support TLS-enabled sources",
6261
},
6362
}
6463

controllers/search_controller/search_construction.go

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import (
1919
)
2020

2121
const (
22-
MongotContainerName = "mongot"
22+
MongotContainerName = "mongot"
23+
SearchLivenessProbePath = "/health"
24+
SearchReadinessProbePath = "/health" // Todo: Update this when search GA is available
2325
)
2426

2527
// SearchSourceDBResource is an object wrapping a MongoDBCommunity object
@@ -183,11 +185,8 @@ func mongodbSearchContainer(mdbSearch *searchv1.MongoDBSearch, volumeMounts []co
183185
container.WithName(MongotContainerName),
184186
container.WithImage(searchImage),
185187
container.WithImagePullPolicy(corev1.PullAlways),
186-
container.WithReadinessProbe(probes.Apply(
187-
probes.WithTCPSocket("", intstr.FromInt32(mdbSearch.GetMongotPort())),
188-
probes.WithInitialDelaySeconds(20),
189-
probes.WithPeriodSeconds(10),
190-
)),
188+
container.WithLivenessProbe(mongotLivenessProbe(mdbSearch)),
189+
container.WithReadinessProbe(mongotReadinessProbe(mdbSearch)),
191190
container.WithResourceRequirements(createSearchResourceRequirements(mdbSearch.Spec.ResourceRequirements)),
192191
container.WithVolumeMounts(volumeMounts),
193192
container.WithCommand([]string{"sh"}),
@@ -209,6 +208,42 @@ chmod 0600 /tmp/sourceUserPassword
209208
)
210209
}
211210

211+
func mongotLivenessProbe(search *searchv1.MongoDBSearch) func(*corev1.Probe) {
212+
return probes.Apply(
213+
probes.WithHandler(corev1.ProbeHandler{
214+
HTTPGet: &corev1.HTTPGetAction{
215+
Scheme: corev1.URISchemeHTTP,
216+
Port: intstr.FromInt32(search.GetMongotHealthCheckPort()),
217+
Path: SearchLivenessProbePath,
218+
},
219+
}),
220+
probes.WithInitialDelaySeconds(10),
221+
probes.WithPeriodSeconds(10),
222+
probes.WithTimeoutSeconds(5),
223+
probes.WithSuccessThreshold(1),
224+
probes.WithFailureThreshold(10),
225+
)
226+
}
227+
228+
// mongotReadinessProbe just uses the endpoint intended for liveness checks;
229+
// readiness check endpoint may be available in search GA.
230+
func mongotReadinessProbe(search *searchv1.MongoDBSearch) func(*corev1.Probe) {
231+
return probes.Apply(
232+
probes.WithHandler(corev1.ProbeHandler{
233+
HTTPGet: &corev1.HTTPGetAction{
234+
Scheme: corev1.URISchemeHTTP,
235+
Port: intstr.FromInt32(search.GetMongotHealthCheckPort()),
236+
Path: SearchReadinessProbePath,
237+
},
238+
}),
239+
probes.WithInitialDelaySeconds(20),
240+
probes.WithPeriodSeconds(10),
241+
probes.WithTimeoutSeconds(5),
242+
probes.WithSuccessThreshold(1),
243+
probes.WithFailureThreshold(3),
244+
)
245+
}
246+
212247
func createSearchResourceRequirements(requirements *corev1.ResourceRequirements) corev1.ResourceRequirements {
213248
if requirements != nil {
214249
return *requirements

0 commit comments

Comments
 (0)