Skip to content

Commit bb344e4

Browse files
authored
Merge pull request #69 from ting-lan-wang/fix-adb-webhook-and-reconcile
fix adb webhook and reconcile issue
2 parents c614050 + 1096f1f commit bb344e4

File tree

3 files changed

+51
-40
lines changed

3 files changed

+51
-40
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ test: manifests generate fmt vet envtest ## Run unit tests.
6161

6262
E2ETEST ?= ./test/e2e/
6363
e2e: manifests generate fmt vet envtest ## Run e2e tests.
64-
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" ginkgo -v --timeout=2h30m --fail-fast $(E2ETEST)
64+
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test $(E2ETEST) -test.timeout 0 -test.v --ginkgo.fail-fast
6565

6666
##@ Build
6767

apis/database/v1alpha1/autonomousdatabase_webhook.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ func (r *AutonomousDatabase) ValidateUpdate(old runtime.Object) error {
164164
// cannot change lifecycleState with other fields together (except the oci config)
165165
var lifecycleChanged, otherFieldsChanged bool
166166

167-
lifecycleChanged = oldADB.Spec.Details.LifecycleState != "" && oldADB.Spec.Details.LifecycleState != r.Spec.Details.LifecycleState
167+
lifecycleChanged = oldADB.Spec.Details.LifecycleState != "" &&
168+
r.Spec.Details.LifecycleState != "" &&
169+
oldADB.Spec.Details.LifecycleState != r.Spec.Details.LifecycleState
168170
var copiedADB *AutonomousDatabaseSpec = r.Spec.DeepCopy()
169171
copiedADB.Details.LifecycleState = oldADB.Spec.Details.LifecycleState
170172
copiedADB.OCIConfig = oldADB.Spec.OCIConfig

controllers/database/autonomousdatabase_controller.go

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,17 @@ func (r *AutonomousDatabaseReconciler) eventFilterPredicate() predicate.Predicat
157157
if adbOk {
158158
oldADB := e.ObjectOld.(*dbv1alpha1.AutonomousDatabase)
159159

160-
if !reflect.DeepEqual(oldADB.Status, desiredADB.Status) ||
161-
(controllerutil.ContainsFinalizer(oldADB, dbv1alpha1.LastSuccessfulSpec) != controllerutil.ContainsFinalizer(desiredADB, dbv1alpha1.LastSuccessfulSpec)) ||
160+
specChanged := !reflect.DeepEqual(oldADB.Spec, desiredADB.Spec)
161+
statusChanged := !reflect.DeepEqual(oldADB.Status, desiredADB.Status)
162+
163+
oldLastSucSpec := oldADB.GetAnnotations()[dbv1alpha1.LastSuccessfulSpec]
164+
desiredLastSucSpec := desiredADB.GetAnnotations()[dbv1alpha1.LastSuccessfulSpec]
165+
lastSucSpecChanged := oldLastSucSpec != desiredLastSucSpec
166+
167+
if (!specChanged && statusChanged) || lastSucSpecChanged ||
162168
(controllerutil.ContainsFinalizer(oldADB, dbv1alpha1.ADBFinalizer) != controllerutil.ContainsFinalizer(desiredADB, dbv1alpha1.ADBFinalizer)) {
163-
// Don't enqueue if the status, lastSucSpec, or the finalizler changes
169+
// Don't enqueue in the folowing condition:
170+
// 1. only status changes 2. lastSucSpec changes 3. ADBFinalizer changes
164171
return false
165172
}
166173

@@ -271,31 +278,36 @@ func (r *AutonomousDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.R
271278
}
272279

273280
/******************************************************************
274-
* Requeue if it's in an intermediate state. Update the status right before
275-
* exiting the reconcile, otherwise the modifiedADB will be overwritten
276-
* by the object returned from the cluster.
281+
* Update the resource if the spec has been changed.
282+
* Requeue if it's in an intermediate state. Update the status first
283+
* , otherwise the modifiedADB will be overwritten by the object
284+
* returned from the cluster.
277285
******************************************************************/
278-
if dbv1alpha1.IsADBIntermediateState(modifiedADB.Status.LifecycleState) {
279-
logger.WithName("IsADBIntermediateState").Info("LifecycleState is " + string(modifiedADB.Status.LifecycleState) + "; reconcile queued")
280-
281-
if err := r.KubeClient.Status().Update(context.TODO(), modifiedADB); err != nil {
286+
if !reflect.DeepEqual(modifiedADB.Spec, desiredADB.Spec) {
287+
if err := r.KubeClient.Update(context.TODO(), modifiedADB); err != nil {
282288
return r.manageError(logger.WithName("IsADBIntermediateState"), modifiedADB, err)
283289
}
290+
return emptyResult, nil
291+
}
284292

293+
copiedADB := modifiedADB.DeepCopy()
294+
if err := r.KubeClient.Status().Update(context.TODO(), modifiedADB); err != nil {
295+
return r.manageError(logger.WithName("Status().Update"), modifiedADB, err)
296+
}
297+
modifiedADB.Spec = copiedADB.Spec
298+
299+
if dbv1alpha1.IsADBIntermediateState(modifiedADB.Status.LifecycleState) {
300+
logger.WithName("IsADBIntermediateState").Info("LifecycleState is " + string(modifiedADB.Status.LifecycleState) + "; reconcile queued")
285301
return requeueResult, nil
286302
}
287303

288304
/******************************************************************
289-
* Update the lastSucSpec and the status, and then finish the reconcile.
290-
* Requeue if it's in an intermediate state or the modifiedADB
291-
* doesn't match the desiredADB.
305+
* Update the lastSucSpec, and then finish the reconcile.
306+
* Requeue if the ADB is terminated, but the finalizer is not yet
307+
* removed.
292308
******************************************************************/
293-
// Do the comparison before updating the status to avoid being overwritten
294-
var requeue bool = false
295-
if !reflect.DeepEqual(modifiedADB.Spec, desiredADB.Spec) {
296-
requeue = true
297-
}
298309

310+
var requeue bool = false
299311
if modifiedADB.GetDeletionTimestamp() != nil &&
300312
controllerutil.ContainsFinalizer(modifiedADB, dbv1alpha1.ADBFinalizer) &&
301313
modifiedADB.Status.LifecycleState == database.AutonomousDatabaseLifecycleStateTerminated {
@@ -307,10 +319,6 @@ func (r *AutonomousDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.R
307319
return r.manageError(logger.WithName("patchLastSuccessfulSpec"), modifiedADB, err)
308320
}
309321

310-
if err := r.KubeClient.Status().Update(context.TODO(), modifiedADB); err != nil {
311-
return r.manageError(logger.WithName("Status().Update"), modifiedADB, err)
312-
}
313-
314322
if requeue {
315323
logger.Info("Reconcile queued")
316324
return requeueResult, nil
@@ -458,8 +466,6 @@ func (r *AutonomousDatabaseReconciler) validateOperation(
458466
} else {
459467
l.Info("No operation specified; sync the resource")
460468

461-
testOldADB := adb.DeepCopy()
462-
463469
// The user doesn't change the spec and the controller should pull the spec from the OCI.
464470
specChanged, err := r.getADB(logger, adb)
465471
if err != nil {
@@ -470,12 +476,12 @@ func (r *AutonomousDatabaseReconciler) validateOperation(
470476
l.Info("The local spec doesn't match the oci's spec; update the CR")
471477

472478
// Erase the status.lifecycleState temporarily to avoid the webhook error.
473-
oldADB := adb.DeepCopy()
479+
tmpADB := adb.DeepCopy()
474480
adb.Status.LifecycleState = ""
475-
r.KubeClient.Status().Update(context.TODO(), adb)
476-
adb.Spec = oldADB.Spec
477-
478-
adb.DeepCopy().RemoveUnchangedDetails(testOldADB.Spec)
481+
if err := r.KubeClient.Status().Update(context.TODO(), adb); err != nil {
482+
return false, emptyResult, err
483+
}
484+
adb.Spec = tmpADB.Spec
479485

480486
if err := r.updateCR(adb); err != nil {
481487
return false, emptyResult, err
@@ -580,7 +586,9 @@ func (r *AutonomousDatabaseReconciler) validateFinalizer(logger logr.Logger, adb
580586
// updateCR updates the lastSucSpec and the CR
581587
func (r *AutonomousDatabaseReconciler) updateCR(adb *dbv1alpha1.AutonomousDatabase) error {
582588
// Update the lastSucSpec
583-
if err := adb.UpdateLastSuccessfulSpec(); err != nil {
589+
// Should patch the lastSuccessfulSpec first, otherwise, the update event will be
590+
// filtered out by predicate since the lastSuccessfulSpec is changed.
591+
if err := r.patchLastSuccessfulSpec(adb); err != nil {
584592
return err
585593
}
586594

@@ -933,22 +941,23 @@ func (r *AutonomousDatabaseReconciler) validateDesiredLifecycleState(
933941
}
934942

935943
// The logic of updating the network access configurations is as follows:
936-
// 1. Shared databases:
937-
// If the network access type changes
938-
// a. to PUBLIC:
944+
//
945+
// 1. Shared databases:
946+
// If the network access type changes
947+
// a. to PUBLIC:
939948
// was RESTRICTED: re-enable IsMTLSConnectionRequired if its not. Then set WhitelistedIps to an array with a single empty string entry.
940949
// was PRIVATE: re-enable IsMTLSConnectionRequired if its not. Then set PrivateEndpointLabel to an emtpy string.
941-
// b. to RESTRICTED:
950+
// b. to RESTRICTED:
942951
// was PUBLIC: set WhitelistedIps to desired IPs/CIDR blocks/VCN OCID. Configure the IsMTLSConnectionRequired settings if it is set to disabled.
943952
// was PRIVATE: re-enable IsMTLSConnectionRequired if its not. Set the type to PUBLIC first, and then configure the WhitelistedIps. Finally resume the IsMTLSConnectionRequired settings if it was, or is configured as disabled.
944-
// c. to PRIVATE:
953+
// c. to PRIVATE:
945954
// was PUBLIC: set subnetOCID and nsgOCIDs. Configure the IsMTLSConnectionRequired settings if it is set.
946955
// was RESTRICTED: set subnetOCID and nsgOCIDs. Configure the IsMTLSConnectionRequired settings if it is set.
947956
//
948-
// Otherwise, if the network access type remains the same, apply the network configuration, and then set the IsMTLSConnectionRequired.
957+
// Otherwise, if the network access type remains the same, apply the network configuration, and then set the IsMTLSConnectionRequired.
949958
//
950-
// 2. Dedicated databases:
951-
// Apply the configs directly
959+
// 2. Dedicated databases:
960+
// Apply the configs directly
952961
func (r *AutonomousDatabaseReconciler) validateGeneralNetworkAccess(
953962
logger logr.Logger,
954963
adb *dbv1alpha1.AutonomousDatabase,

0 commit comments

Comments
 (0)