diff --git a/apis/v1alpha1/ack-generate-metadata.yaml b/apis/v1alpha1/ack-generate-metadata.yaml index d17f94bd..9c43f988 100755 --- a/apis/v1alpha1/ack-generate-metadata.yaml +++ b/apis/v1alpha1/ack-generate-metadata.yaml @@ -1,13 +1,13 @@ ack_generate_info: - build_date: "2025-07-22T22:12:13Z" + build_date: "2025-07-23T17:40:52Z" build_hash: b2dc0f44e0b08f041de14c3944a5cc005ba97c8f - go_version: go1.24.5 + go_version: go1.24.4 version: v0.50.0 api_directory_checksum: 52968d74358773de28be65be320d1bfb9c91e0bf api_version: v1alpha1 aws_sdk_go_version: v1.32.6 generator_config_info: - file_checksum: ced2b68c703e2daf7b04da8f84f6ad6c95114fb9 + file_checksum: c2e5556f70b93834cadb221ec373fa29d6c1692b original_file_name: generator.yaml last_modification: reason: API generation diff --git a/apis/v1alpha1/generator.yaml b/apis/v1alpha1/generator.yaml index 015164f6..7fb18cb7 100644 --- a/apis/v1alpha1/generator.yaml +++ b/apis/v1alpha1/generator.yaml @@ -308,8 +308,8 @@ resources: template_path: hooks/db_instance/sdk_update_pre_build_request.go.tpl sdk_update_post_build_request: template_path: hooks/db_instance/sdk_update_post_build_request.go.tpl - sdk_update_post_set_output: - template_path: hooks/db_instance/sdk_update_post_set_output.go.tpl + sdk_update_pre_set_output: + template_path: hooks/db_instance/sdk_update_pre_set_output.go.tpl sdk_delete_pre_build_request: template_path: hooks/db_instance/sdk_delete_pre_build_request.go.tpl sdk_delete_post_build_request: @@ -332,7 +332,7 @@ resources: name: "STATUS" MasterUserPassword: is_secret: true - KmsKeyId: + KMSKeyId: references: resource: Key service_name: kms @@ -395,6 +395,12 @@ resources: from: operation: CreateDBInstanceReadReplica path: PreSignedUrl + PerformanceInsightsKMSKeyID: + late_initialize: + skip_incomplete_check: {} + PerformanceInsightsRetentionPeriod: + late_initialize: + skip_incomplete_check: {} Tags: compare: # We have a custom comparison function... diff --git a/generator.yaml b/generator.yaml index 015164f6..7fb18cb7 100644 --- a/generator.yaml +++ b/generator.yaml @@ -308,8 +308,8 @@ resources: template_path: hooks/db_instance/sdk_update_pre_build_request.go.tpl sdk_update_post_build_request: template_path: hooks/db_instance/sdk_update_post_build_request.go.tpl - sdk_update_post_set_output: - template_path: hooks/db_instance/sdk_update_post_set_output.go.tpl + sdk_update_pre_set_output: + template_path: hooks/db_instance/sdk_update_pre_set_output.go.tpl sdk_delete_pre_build_request: template_path: hooks/db_instance/sdk_delete_pre_build_request.go.tpl sdk_delete_post_build_request: @@ -332,7 +332,7 @@ resources: name: "STATUS" MasterUserPassword: is_secret: true - KmsKeyId: + KMSKeyId: references: resource: Key service_name: kms @@ -395,6 +395,12 @@ resources: from: operation: CreateDBInstanceReadReplica path: PreSignedUrl + PerformanceInsightsKMSKeyID: + late_initialize: + skip_incomplete_check: {} + PerformanceInsightsRetentionPeriod: + late_initialize: + skip_incomplete_check: {} Tags: compare: # We have a custom comparison function... diff --git a/pkg/resource/db_instance/delta.go b/pkg/resource/db_instance/delta.go index fa264315..67c86691 100644 --- a/pkg/resource/db_instance/delta.go +++ b/pkg/resource/db_instance/delta.go @@ -63,14 +63,9 @@ func newResourceDelta( *b.ko.Spec.NetworkType == ServiceDefaultNetworkType { a.ko.Spec.NetworkType = b.ko.Spec.NetworkType } - if a.ko.Spec.PerformanceInsightsRetentionPeriod == nil && - b.ko.Spec.PerformanceInsightsRetentionPeriod != nil && - *b.ko.Spec.PerformanceInsightsRetentionPeriod == ServiceDefaultInsightsRetentionPeriod { - a.ko.Spec.PerformanceInsightsRetentionPeriod = b.ko.Spec.PerformanceInsightsRetentionPeriod - } - if a.ko.Spec.PerformanceInsightsKMSKeyID == nil && - b.ko.Spec.PerformanceInsightsKMSKeyID != nil { - a.ko.Spec.PerformanceInsightsKMSKeyID = b.ko.Spec.PerformanceInsightsKMSKeyID + if a.ko.Spec.PerformanceInsightsEnabled == nil && + b.ko.Spec.PerformanceInsightsEnabled != nil { + a.ko.Spec.PerformanceInsightsEnabled = func() *bool { a := false; return &a }() } // RDS will choose preferred engine minor version if only diff --git a/pkg/resource/db_instance/manager.go b/pkg/resource/db_instance/manager.go index fb6f4bc5..54e98837 100644 --- a/pkg/resource/db_instance/manager.go +++ b/pkg/resource/db_instance/manager.go @@ -50,7 +50,7 @@ var ( // +kubebuilder:rbac:groups=rds.services.k8s.aws,resources=dbinstances,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=rds.services.k8s.aws,resources=dbinstances/status,verbs=get;update;patch -var lateInitializeFieldNames = []string{"AvailabilityZone", "BackupTarget", "NetworkType"} +var lateInitializeFieldNames = []string{"AvailabilityZone", "BackupTarget", "NetworkType", "PerformanceInsightsKMSKeyID", "PerformanceInsightsRetentionPeriod"} // resourceManager is responsible for providing a consistent way to perform // CRUD operations in a backend AWS service API for Book custom resources. @@ -278,6 +278,12 @@ func (rm *resourceManager) lateInitializeFromReadOneOutput( if observedKo.Spec.NetworkType != nil && latestKo.Spec.NetworkType == nil { latestKo.Spec.NetworkType = observedKo.Spec.NetworkType } + if observedKo.Spec.PerformanceInsightsKMSKeyID != nil && latestKo.Spec.PerformanceInsightsKMSKeyID == nil { + latestKo.Spec.PerformanceInsightsKMSKeyID = observedKo.Spec.PerformanceInsightsKMSKeyID + } + if observedKo.Spec.PerformanceInsightsRetentionPeriod != nil && latestKo.Spec.PerformanceInsightsRetentionPeriod == nil { + latestKo.Spec.PerformanceInsightsRetentionPeriod = observedKo.Spec.PerformanceInsightsRetentionPeriod + } return &resource{latestKo} } diff --git a/pkg/resource/db_instance/sdk.go b/pkg/resource/db_instance/sdk.go index 974fd909..9cdc5d4b 100644 --- a/pkg/resource/db_instance/sdk.go +++ b/pkg/resource/db_instance/sdk.go @@ -1907,26 +1907,29 @@ func (rm *resourceManager) sdkUpdate( defer func() { exit(err) }() + res := desired.ko.DeepCopy() + res.Status = latest.ko.Status + if instanceDeleting(latest) { msg := "DB instance is currently being deleted" - ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil) - return desired, requeueWaitWhileDeleting + ackcondition.SetSynced(&resource{res}, corev1.ConditionFalse, &msg, nil) + return &resource{res}, requeueWaitWhileDeleting } if instanceCreating(latest) { msg := "DB instance is currently being created" - ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil) - return desired, requeueWaitUntilCanModify(latest) + ackcondition.SetSynced(&resource{res}, corev1.ConditionFalse, &msg, nil) + return &resource{res}, requeueWaitUntilCanModify(latest) } if instanceHasTerminalStatus(latest) { msg := "DB instance is in '" + *latest.ko.Status.DBInstanceStatus + "' status" - ackcondition.SetTerminal(desired, corev1.ConditionTrue, &msg, nil) - ackcondition.SetSynced(desired, corev1.ConditionTrue, nil, nil) - return desired, nil + ackcondition.SetTerminal(&resource{res}, corev1.ConditionTrue, &msg, nil) + ackcondition.SetSynced(&resource{res}, corev1.ConditionTrue, nil, nil) + return &resource{res}, nil } if !instanceAvailable(latest) && !needStorageUpdate(latest, delta) { msg := "DB instance cannot be modifed while in '" + *latest.ko.Status.DBInstanceStatus + "' status" - ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil) - return desired, requeueWaitUntilCanModify(latest) + ackcondition.SetSynced(&resource{res}, corev1.ConditionFalse, &msg, nil) + return &resource{res}, requeueWaitUntilCanModify(latest) } if delta.DifferentAt("Spec.Tags") { if err = rm.syncTags(ctx, desired, latest); err != nil { @@ -1987,6 +1990,12 @@ func (rm *resourceManager) sdkUpdate( // Merge in the information we read from the API call above to the copy of // the original Kubernetes object we passed to the function ko := desired.ko.DeepCopy() + ko.Status = latest.ko.Status + setLastAppliedSecretReferenceAnnotation(&resource{ko}) + // Setting resource synced condition to false will trigger a requeue of + // the resource. No need to return a requeue error here. + ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) + return &resource{ko}, nil if resp.DBInstance.ActivityStreamEngineNativeAuditFieldsIncluded != nil { ko.Status.ActivityStreamEngineNativeAuditFieldsIncluded = resp.DBInstance.ActivityStreamEngineNativeAuditFieldsIncluded @@ -2663,99 +2672,6 @@ func (rm *resourceManager) sdkUpdate( } rm.setStatusDefaults(ko) - // ModifyDBInstance returns a DBInstance struct that contains the - // *previously set* values for various mutable fields. This is problematic - // because it causes a "flopping" behaviour when the user has modified a - // Spec field from value A to value B but the output shape from - // ModifyDBInstance for that field contains value A, the standard SetOutput - // Go code generated above will set the Spec field to the *old* value - // again. The next time the reconciler runs, it will attempt to modify the - // field from value B to value A again, causing a flop loop. - // - // Luckily, the Output shape's DBInstance struct contains a - // `PendingModifiedValues` struct which contains those field values that - // the user specified. So, we can use these to "reset" the Spec back to the - // appropriate user-specific values. - pmv := resp.DBInstance.PendingModifiedValues - if pmv != nil { - if pmv.AllocatedStorage != nil { - ko.Spec.AllocatedStorage = aws.Int64(int64(*pmv.AllocatedStorage)) - } - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.AutomationMode != nil { - // ko.Spec.AutomationMode = pmv.AutomationMode - //} - if pmv.BackupRetentionPeriod != nil { - ko.Spec.BackupRetentionPeriod = aws.Int64(int64(*pmv.BackupRetentionPeriod)) - } - if pmv.CACertificateIdentifier != nil { - ko.Spec.CACertificateIdentifier = pmv.CACertificateIdentifier - } - if pmv.DBInstanceClass != nil { - ko.Spec.DBInstanceClass = pmv.DBInstanceClass - } - if pmv.DBInstanceIdentifier != nil { - ko.Spec.DBInstanceIdentifier = pmv.DBInstanceIdentifier - } - if pmv.DBSubnetGroupName != nil { - ko.Spec.DBSubnetGroupName = pmv.DBSubnetGroupName - } - if pmv.EngineVersion != nil { - ko.Spec.EngineVersion = pmv.EngineVersion - } - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.IAMDatabaseAuthenticationEnabled != nil { - // ko.Spec.IAMDatabaseAuthenticationEnabled = pmv.IAMDatabaseAuthenticationEnabled - //} - if pmv.Iops != nil { - ko.Spec.IOPS = aws.Int64(int64(*pmv.Iops)) - } - if pmv.LicenseModel != nil { - ko.Spec.LicenseModel = pmv.LicenseModel - } - if pmv.MasterUserPassword != nil { - // NOTE(jaypipes): Type mismatch with Spec and - // PendingModifiedValues, so just reset to the desired... - ko.Spec.MasterUserPassword = desired.ko.Spec.MasterUserPassword - } - if pmv.MultiAZ != nil { - ko.Spec.MultiAZ = pmv.MultiAZ - } - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.PendingCloudwatchLogsExports != nil { - // ko.Spec.PendingCloudwatchLogsExports = pmv.PendingCloudwatchLogsExports - //} - if pmv.Port != nil { - ko.Spec.Port = aws.Int64(int64(*pmv.Port)) - } - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.ProcessorFeatures != nil { - // ko.Spec.ProcessorFeatures = pmv.ProcessorFeatures - //} - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.ResumeFullAutomationModeTime != nil { - // ko.Spec.ResumeFullAutomationModeTime = pmv.ResumeFullAutomationModeTime - //} - if pmv.StorageThroughput != nil { - ko.Spec.StorageThroughput = aws.Int64(int64(*pmv.StorageThroughput)) - } - if pmv.StorageType != nil { - ko.Spec.StorageType = pmv.StorageType - } - } - // When ModifyDBInstance API is successful, it asynchronously - // updates the DBInstanceStatus. Requeue to find the current - // DBInstance status and set Synced condition accordingly - if err == nil { - // set the last-applied-secret-reference annotation on the DB instance - // resource. - r := &resource{ko} - setLastAppliedSecretReferenceAnnotation(r) - // Setting resource synced condition to false will trigger a requeue of - // the resource. No need to return a requeue error here. - ackcondition.SetSynced(r, corev1.ConditionFalse, nil, nil) - } - return &resource{ko}, nil } diff --git a/templates/hooks/db_instance/delta_pre_compare.go.tpl b/templates/hooks/db_instance/delta_pre_compare.go.tpl index aee45e5b..c6f9b051 100644 --- a/templates/hooks/db_instance/delta_pre_compare.go.tpl +++ b/templates/hooks/db_instance/delta_pre_compare.go.tpl @@ -19,14 +19,9 @@ *b.ko.Spec.NetworkType == ServiceDefaultNetworkType { a.ko.Spec.NetworkType = b.ko.Spec.NetworkType } - if a.ko.Spec.PerformanceInsightsRetentionPeriod == nil && - b.ko.Spec.PerformanceInsightsRetentionPeriod != nil && - *b.ko.Spec.PerformanceInsightsRetentionPeriod == ServiceDefaultInsightsRetentionPeriod { - a.ko.Spec.PerformanceInsightsRetentionPeriod = b.ko.Spec.PerformanceInsightsRetentionPeriod - } - if a.ko.Spec.PerformanceInsightsKMSKeyID == nil && - b.ko.Spec.PerformanceInsightsKMSKeyID != nil { - a.ko.Spec.PerformanceInsightsKMSKeyID = b.ko.Spec.PerformanceInsightsKMSKeyID + if a.ko.Spec.PerformanceInsightsEnabled == nil && + b.ko.Spec.PerformanceInsightsEnabled != nil { + a.ko.Spec.PerformanceInsightsEnabled = func() *bool {a := false; return &a }() } // RDS will choose preferred engine minor version if only diff --git a/templates/hooks/db_instance/sdk_update_post_set_output.go.tpl b/templates/hooks/db_instance/sdk_update_post_set_output.go.tpl deleted file mode 100644 index 5b712e1c..00000000 --- a/templates/hooks/db_instance/sdk_update_post_set_output.go.tpl +++ /dev/null @@ -1,92 +0,0 @@ - // ModifyDBInstance returns a DBInstance struct that contains the - // *previously set* values for various mutable fields. This is problematic - // because it causes a "flopping" behaviour when the user has modified a - // Spec field from value A to value B but the output shape from - // ModifyDBInstance for that field contains value A, the standard SetOutput - // Go code generated above will set the Spec field to the *old* value - // again. The next time the reconciler runs, it will attempt to modify the - // field from value B to value A again, causing a flop loop. - // - // Luckily, the Output shape's DBInstance struct contains a - // `PendingModifiedValues` struct which contains those field values that - // the user specified. So, we can use these to "reset" the Spec back to the - // appropriate user-specific values. - pmv := resp.DBInstance.PendingModifiedValues - if pmv != nil { - if pmv.AllocatedStorage != nil { - ko.Spec.AllocatedStorage = aws.Int64(int64(*pmv.AllocatedStorage)) - } - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.AutomationMode != nil { - // ko.Spec.AutomationMode = pmv.AutomationMode - //} - if pmv.BackupRetentionPeriod != nil { - ko.Spec.BackupRetentionPeriod = aws.Int64(int64(*pmv.BackupRetentionPeriod)) - } - if pmv.CACertificateIdentifier != nil { - ko.Spec.CACertificateIdentifier = pmv.CACertificateIdentifier - } - if pmv.DBInstanceClass != nil { - ko.Spec.DBInstanceClass = pmv.DBInstanceClass - } - if pmv.DBInstanceIdentifier != nil { - ko.Spec.DBInstanceIdentifier = pmv.DBInstanceIdentifier - } - if pmv.DBSubnetGroupName != nil { - ko.Spec.DBSubnetGroupName = pmv.DBSubnetGroupName - } - if pmv.EngineVersion != nil { - ko.Spec.EngineVersion = pmv.EngineVersion - } - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.IAMDatabaseAuthenticationEnabled != nil { - // ko.Spec.IAMDatabaseAuthenticationEnabled = pmv.IAMDatabaseAuthenticationEnabled - //} - if pmv.Iops != nil { - ko.Spec.IOPS = aws.Int64(int64(*pmv.Iops)) - } - if pmv.LicenseModel != nil { - ko.Spec.LicenseModel = pmv.LicenseModel - } - if pmv.MasterUserPassword != nil { - // NOTE(jaypipes): Type mismatch with Spec and - // PendingModifiedValues, so just reset to the desired... - ko.Spec.MasterUserPassword = desired.ko.Spec.MasterUserPassword - } - if pmv.MultiAZ != nil { - ko.Spec.MultiAZ = pmv.MultiAZ - } - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.PendingCloudwatchLogsExports != nil { - // ko.Spec.PendingCloudwatchLogsExports = pmv.PendingCloudwatchLogsExports - //} - if pmv.Port != nil { - ko.Spec.Port = aws.Int64(int64(*pmv.Port)) - } - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.ProcessorFeatures != nil { - // ko.Spec.ProcessorFeatures = pmv.ProcessorFeatures - //} - // NOTE(jaypipes): Handle when aws-sdk-go update - //if pmv.ResumeFullAutomationModeTime != nil { - // ko.Spec.ResumeFullAutomationModeTime = pmv.ResumeFullAutomationModeTime - //} - if pmv.StorageThroughput != nil { - ko.Spec.StorageThroughput = aws.Int64(int64(*pmv.StorageThroughput)) - } - if pmv.StorageType != nil { - ko.Spec.StorageType = pmv.StorageType - } - } - // When ModifyDBInstance API is successful, it asynchronously - // updates the DBInstanceStatus. Requeue to find the current - // DBInstance status and set Synced condition accordingly - if err == nil { - // set the last-applied-secret-reference annotation on the DB instance - // resource. - r := &resource{ko} - setLastAppliedSecretReferenceAnnotation(r) - // Setting resource synced condition to false will trigger a requeue of - // the resource. No need to return a requeue error here. - ackcondition.SetSynced(r, corev1.ConditionFalse, nil, nil) - } diff --git a/templates/hooks/db_instance/sdk_update_pre_build_request.go.tpl b/templates/hooks/db_instance/sdk_update_pre_build_request.go.tpl index a7d851ea..4545329a 100644 --- a/templates/hooks/db_instance/sdk_update_pre_build_request.go.tpl +++ b/templates/hooks/db_instance/sdk_update_pre_build_request.go.tpl @@ -1,23 +1,26 @@ + res := desired.ko.DeepCopy() + res.Status = latest.ko.Status + if instanceDeleting(latest) { msg := "DB instance is currently being deleted" - ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil) - return desired, requeueWaitWhileDeleting + ackcondition.SetSynced(&resource{res}, corev1.ConditionFalse, &msg, nil) + return &resource{res}, requeueWaitWhileDeleting } if instanceCreating(latest) { msg := "DB instance is currently being created" - ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil) - return desired, requeueWaitUntilCanModify(latest) + ackcondition.SetSynced(&resource{res}, corev1.ConditionFalse, &msg, nil) + return &resource{res}, requeueWaitUntilCanModify(latest) } if instanceHasTerminalStatus(latest) { msg := "DB instance is in '"+*latest.ko.Status.DBInstanceStatus+"' status" - ackcondition.SetTerminal(desired, corev1.ConditionTrue, &msg, nil) - ackcondition.SetSynced(desired, corev1.ConditionTrue, nil, nil) - return desired, nil + ackcondition.SetTerminal(&resource{res}, corev1.ConditionTrue, &msg, nil) + ackcondition.SetSynced(&resource{res}, corev1.ConditionTrue, nil, nil) + return &resource{res}, nil } if !instanceAvailable(latest) && !needStorageUpdate(latest, delta) { msg := "DB instance cannot be modifed while in '" + *latest.ko.Status.DBInstanceStatus + "' status" - ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil) - return desired, requeueWaitUntilCanModify(latest) + ackcondition.SetSynced(&resource{res}, corev1.ConditionFalse, &msg, nil) + return &resource{res}, requeueWaitUntilCanModify(latest) } if delta.DifferentAt("Spec.Tags") { if err = rm.syncTags(ctx, desired, latest); err != nil { diff --git a/templates/hooks/db_instance/sdk_update_pre_set_output.go.tpl b/templates/hooks/db_instance/sdk_update_pre_set_output.go.tpl new file mode 100644 index 00000000..8779fead --- /dev/null +++ b/templates/hooks/db_instance/sdk_update_pre_set_output.go.tpl @@ -0,0 +1,6 @@ + ko.Status = latest.ko.Status + setLastAppliedSecretReferenceAnnotation(&resource{ko}) + // Setting resource synced condition to false will trigger a requeue of + // the resource. No need to return a requeue error here. + ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) + return &resource{ko}, nil diff --git a/test/e2e/tests/test_db_instance.py b/test/e2e/tests/test_db_instance.py index cd293a44..ec274784 100644 --- a/test/e2e/tests/test_db_instance.py +++ b/test/e2e/tests/test_db_instance.py @@ -315,9 +315,11 @@ def test_enable_pi_postgres14_t3_micro( assert latest is not None assert latest['PerformanceInsightsEnabled'] is True - # TODO: Ensure that the server side defaults - # (PerformanceInsightsRetentionPeriod and PerformanceInsightsKMSKeyID) - # are also persisted back into the spec. This currently does not work + cr = k8s.get_resource(ref) + assert 'performanceInsightsRetentionPeriod' in cr['spec'] + assert 'performanceInsightsKMSKeyID' in cr['spec'] + assert latest['PerformanceInsightsRetentionPeriod'] == cr['spec']['performanceInsightsRetentionPeriod'] + assert latest['PerformanceInsightsKMSKeyId'] == cr['spec']['performanceInsightsKMSKeyID'] def test_state_field_flapping( self, @@ -408,3 +410,59 @@ def test_state_field_flapping( assert "PendingModifiedValues" in latest assert "MultiAZ" in latest["PendingModifiedValues"] assert bool(latest["PendingModifiedValues"]["MultiAZ"]) + + def test_crud_postgres14_update_multiAZ( + self, + postgres14_t3_micro_instance, + ): + (ref, cr, _) = postgres14_t3_micro_instance + db_instance_id = cr["spec"]["dbInstanceIdentifier"] + + assert 'status' in cr + assert 'dbInstanceStatus' in cr['status'] + assert cr['status']['dbInstanceStatus'] == 'creating' + condition.assert_not_synced(ref) + + # Assert that the last-applied-secret-reference annotation is set + assert 'metadata' in cr + assert 'annotations' in cr['metadata'] + assert 'rds.services.k8s.aws/last-applied-secret-reference' in cr['metadata']['annotations'] + + # Wait for the resource to get synced + assert k8s.wait_on_condition(ref, "ACK.ResourceSynced", "True", wait_periods=MAX_WAIT_FOR_SYNCED_MINUTES) + + # After the resource is synced, assert that DBInstanceStatus is available + latest = db_instance.get(db_instance_id) + assert latest is not None + assert latest['DBInstanceStatus'] == 'available' + assert latest['MultiAZ'] is False + + cr = k8s.get_resource(ref) + assert cr is not None + assert 'spec' in cr + assert 'multiAZ' in cr['spec'] + assert cr['spec']['multiAZ'] is False + condition.assert_synced(ref) + + # Let's now update the DBInstance MultiAZ to be true + updates = { + "spec": { + "multiAZ": True + }, + } + + k8s.patch_custom_resource(ref, updates) + time.sleep(35) + condition.assert_not_synced(ref) + cr = k8s.get_resource(ref) + assert cr is not None + assert 'status' in cr + assert 'spec' in cr + assert 'multiAZ' in cr['spec'] + assert cr['spec']['multiAZ'] is True + assert k8s.wait_on_condition(ref, "ACK.ResourceSynced", "True", wait_periods=MAX_WAIT_FOR_SYNCED_MINUTES) + + latest = db_instance.get(db_instance_id) + assert latest is not None + assert latest['DBInstanceStatus'] == 'available' + assert latest['MultiAZ'] is True