@@ -24,6 +24,7 @@ import (
24
24
"github.com/mongodb/mongodb-kubernetes-operator/pkg/authentication/scram"
25
25
"github.com/stretchr/objx"
26
26
27
+ "github.com/mongodb/mongodb-kubernetes-operator/pkg/controller/validation"
27
28
"github.com/mongodb/mongodb-kubernetes-operator/pkg/controller/watch"
28
29
29
30
"github.com/mongodb/mongodb-kubernetes-operator/pkg/kube/persistentvolumeclaim"
@@ -82,7 +83,8 @@ const (
82
83
83
84
// lastVersionAnnotationKey should indicate which version of MongoDB was last
84
85
// configured
85
- lastVersionAnnotationKey = "mongodb.com/v1.lastVersion"
86
+ lastVersionAnnotationKey = "mongodb.com/v1.lastVersion"
87
+ lastSuccessfulConfiguration = "mongodb.com/v1.lastSuccessfulConfiguration"
86
88
// tlsRolledOutAnnotationKey indicates if TLS has been fully rolled out
87
89
tlsRolledOutAnnotationKey = "mongodb.com/v1.tlsRolledOut"
88
90
hasLeftReadyStateAnnotationKey = "mongodb.com/v1.hasLeftReadyStateAnnotationKey"
@@ -181,6 +183,15 @@ func (r *ReplicaSetReconciler) Reconcile(request reconcile.Request) (reconcile.R
181
183
r .log = zap .S ().With ("ReplicaSet" , request .NamespacedName )
182
184
r .log .Infow ("Reconciling MongoDB" , "MongoDB.Spec" , mdb .Spec , "MongoDB.Status" , mdb .Status )
183
185
186
+ r .log .Debug ("Validating MongoDB.Spec" )
187
+ if err := r .validateUpdate (mdb ); err != nil {
188
+ return status .Update (r .client .Status (), & mdb ,
189
+ statusOptions ().
190
+ withMessage (Error , fmt .Sprintf ("error validating new Spec: %s" , err )).
191
+ withFailedPhase (),
192
+ )
193
+ }
194
+
184
195
r .log .Debug ("Ensuring Automation Config for deployment" )
185
196
if err := r .ensureAutomationConfig (mdb ); err != nil {
186
197
return status .Update (r .client .Status (), & mdb ,
@@ -290,7 +301,6 @@ func (r *ReplicaSetReconciler) Reconcile(request reconcile.Request) (reconcile.R
290
301
}
291
302
292
303
r .log .Debug ("Setting MongoDB Annotations" )
293
-
294
304
annotations := map [string ]string {
295
305
lastVersionAnnotationKey : mdb .Spec .Version ,
296
306
hasLeftReadyStateAnnotationKey : "false" ,
@@ -331,12 +341,15 @@ func (r *ReplicaSetReconciler) Reconcile(request reconcile.Request) (reconcile.R
331
341
withMessage (None , "" ).
332
342
withRunningPhase (),
333
343
)
334
-
335
344
if err != nil {
336
345
r .log .Errorf ("Error updating the status of the MongoDB resource: %s" , err )
337
346
return res , err
338
347
}
339
348
349
+ if err := r .updateCurrentSpecAnnotation (mdb ); err != nil {
350
+ r .log .Errorf ("Could not save current state as an annotation: %s" , err )
351
+ }
352
+
340
353
if res .RequeueAfter > 0 || res .Requeue {
341
354
r .log .Infow ("Requeuing reconciliation" , "MongoDB.Spec:" , mdb .Spec , "MongoDB.Status:" , mdb .Status )
342
355
return res , nil
@@ -537,6 +550,25 @@ func getCurrentAutomationConfig(getUpdater secret.GetUpdater, mdb mdbv1.MongoDB)
537
550
return currentAc , nil
538
551
}
539
552
553
+ // validateUpdate validates that the new Spec, corresponding to the existing one
554
+ // is still valid. If there is no a previous Spec, then the function assumes this is
555
+ // the first version of the MongoDB resource and skips.
556
+ func (r ReplicaSetReconciler ) validateUpdate (mdb mdbv1.MongoDB ) error {
557
+ lastSuccessfulConfigurationSaved , ok := mdb .Annotations [lastSuccessfulConfiguration ]
558
+ if ! ok {
559
+ // First version of Spec, no need to validate
560
+ return nil
561
+ }
562
+
563
+ prevSpec := mdbv1.MongoDBSpec {}
564
+ err := json .Unmarshal ([]byte (lastSuccessfulConfigurationSaved ), & prevSpec )
565
+ if err != nil {
566
+ return err
567
+ }
568
+
569
+ return validation .Validate (prevSpec , mdb .Spec )
570
+ }
571
+
540
572
func (r ReplicaSetReconciler ) buildAutomationConfigSecret (mdb mdbv1.MongoDB ) (corev1.Secret , error ) {
541
573
542
574
manifest , err := r .manifestProvider ()
@@ -581,6 +613,18 @@ func (r ReplicaSetReconciler) buildAutomationConfigSecret(mdb mdbv1.MongoDB) (co
581
613
Build (), nil
582
614
}
583
615
616
+ func (r ReplicaSetReconciler ) updateCurrentSpecAnnotation (mdb mdbv1.MongoDB ) error {
617
+ currentSpec , err := json .Marshal (mdb .Spec )
618
+ if err != nil {
619
+ return err
620
+ }
621
+
622
+ annotations := map [string ]string {
623
+ lastSuccessfulConfiguration : string (currentSpec ),
624
+ }
625
+ return r .setAnnotations (mdb .NamespacedName (), annotations )
626
+ }
627
+
584
628
// getMongodConfigModification will merge the additional configuration in the CRD
585
629
// into the configuration set up by the operator.
586
630
func getMongodConfigModification (mdb mdbv1.MongoDB ) automationconfig.Modification {
0 commit comments