diff --git a/apis/docdb/v1alpha1/custom_types.go b/apis/docdb/v1alpha1/custom_types.go index 9747938f57..7b9f3862f3 100644 --- a/apis/docdb/v1alpha1/custom_types.go +++ b/apis/docdb/v1alpha1/custom_types.go @@ -158,13 +158,13 @@ type CustomDBClusterParameters struct { } // SnapshotRestoreBackupConfiguration defines the details of the snapshot to restore from. -type SnapshotRestoreBackupConfiguration struct { +type RestoreSnapshotConfiguration struct { // SnapshotIdentifier is the identifier of the snapshot to restore. - SnapshotIdentifier *string `json:"snapshotIdentifier"` + SnapshotIdentifier string `json:"snapshotIdentifier"` } // PointInTimeRestoreDBClusterBackupConfiguration defines the details of the time to restore from -type PointInTimeRestoreDBClusterBackupConfiguration struct { +type RestorePointInTimeConfiguration struct { // RestoreTime is the date and time (UTC) to restore from. // Must be before the latest restorable time for the DB instance. // Can't be specified if the useLatestRestorableTime parameter is enabled. @@ -180,7 +180,7 @@ type PointInTimeRestoreDBClusterBackupConfiguration struct { // SourceDBClusterIdentifier specifies the identifier of the source DB cluster from which to restore. Constraints: // Must match the identifier of an existing DB instance. // +optional - SourceDBClusterIdentifier *string `json:"sourceDBClusterIdentifier,omitempty"` + SourceDBClusterIdentifier string `json:"sourceDBClusterIdentifier"` // The type of restore to be performed. You can specify one of the following // values: @@ -203,18 +203,26 @@ type PointInTimeRestoreDBClusterBackupConfiguration struct { RestoreType *string `json:"restoreType,omitempty"` } +type RestoreSource string + +// RestoreSource values +const ( + RestoreSourceSnapshot = "Snapshot" + RestoreSourcePointInTime = "PointInTime" +) + // RestoreDBClusterBackupConfiguration defines the backup to restore a new DBCluster from. type RestoreDBClusterBackupConfiguration struct { // Snapshot specifies the details of the snapshot to restore from. // +optional - Snapshot *SnapshotRestoreBackupConfiguration `json:"snapshot,omitempty"` + Snapshot *RestoreSnapshotConfiguration `json:"snapshot,omitempty"` // PointInTime specifies the details of the point in time restore. // +optional - PointInTime *PointInTimeRestoreDBClusterBackupConfiguration `json:"pointInTime,omitempty"` + PointInTime *RestorePointInTimeConfiguration `json:"pointInTime,omitempty"` // Source is the type of the backup to restore when creating a new DBCluster or DBInstance. // Snapshot and PointInTime are supported. // +kubebuilder:validation:Enum=Snapshot;PointInTime - Source string `json:"source"` + Source RestoreSource `json:"source"` } diff --git a/apis/docdb/v1alpha1/zz_generated.deepcopy.go b/apis/docdb/v1alpha1/zz_generated.deepcopy.go index 2b08611b69..aac016de18 100644 --- a/apis/docdb/v1alpha1/zz_generated.deepcopy.go +++ b/apis/docdb/v1alpha1/zz_generated.deepcopy.go @@ -2629,40 +2629,6 @@ func (in *PendingModifiedValues) DeepCopy() *PendingModifiedValues { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PointInTimeRestoreDBClusterBackupConfiguration) DeepCopyInto(out *PointInTimeRestoreDBClusterBackupConfiguration) { - *out = *in - if in.RestoreTime != nil { - in, out := &in.RestoreTime, &out.RestoreTime - *out = (*in).DeepCopy() - } - if in.UseLatestRestorableTime != nil { - in, out := &in.UseLatestRestorableTime, &out.UseLatestRestorableTime - *out = new(bool) - **out = **in - } - if in.SourceDBClusterIdentifier != nil { - in, out := &in.SourceDBClusterIdentifier, &out.SourceDBClusterIdentifier - *out = new(string) - **out = **in - } - if in.RestoreType != nil { - in, out := &in.RestoreType, &out.RestoreType - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PointInTimeRestoreDBClusterBackupConfiguration. -func (in *PointInTimeRestoreDBClusterBackupConfiguration) DeepCopy() *PointInTimeRestoreDBClusterBackupConfiguration { - if in == nil { - return nil - } - out := new(PointInTimeRestoreDBClusterBackupConfiguration) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourcePendingMaintenanceActions) DeepCopyInto(out *ResourcePendingMaintenanceActions) { *out = *in @@ -2688,12 +2654,12 @@ func (in *RestoreDBClusterBackupConfiguration) DeepCopyInto(out *RestoreDBCluste *out = *in if in.Snapshot != nil { in, out := &in.Snapshot, &out.Snapshot - *out = new(SnapshotRestoreBackupConfiguration) - (*in).DeepCopyInto(*out) + *out = new(RestoreSnapshotConfiguration) + **out = **in } if in.PointInTime != nil { in, out := &in.PointInTime, &out.PointInTime - *out = new(PointInTimeRestoreDBClusterBackupConfiguration) + *out = new(RestorePointInTimeConfiguration) (*in).DeepCopyInto(*out) } } @@ -2709,21 +2675,45 @@ func (in *RestoreDBClusterBackupConfiguration) DeepCopy() *RestoreDBClusterBacku } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SnapshotRestoreBackupConfiguration) DeepCopyInto(out *SnapshotRestoreBackupConfiguration) { +func (in *RestorePointInTimeConfiguration) DeepCopyInto(out *RestorePointInTimeConfiguration) { *out = *in - if in.SnapshotIdentifier != nil { - in, out := &in.SnapshotIdentifier, &out.SnapshotIdentifier + if in.RestoreTime != nil { + in, out := &in.RestoreTime, &out.RestoreTime + *out = (*in).DeepCopy() + } + if in.UseLatestRestorableTime != nil { + in, out := &in.UseLatestRestorableTime, &out.UseLatestRestorableTime + *out = new(bool) + **out = **in + } + if in.RestoreType != nil { + in, out := &in.RestoreType, &out.RestoreType *out = new(string) **out = **in } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotRestoreBackupConfiguration. -func (in *SnapshotRestoreBackupConfiguration) DeepCopy() *SnapshotRestoreBackupConfiguration { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestorePointInTimeConfiguration. +func (in *RestorePointInTimeConfiguration) DeepCopy() *RestorePointInTimeConfiguration { + if in == nil { + return nil + } + out := new(RestorePointInTimeConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestoreSnapshotConfiguration) DeepCopyInto(out *RestoreSnapshotConfiguration) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreSnapshotConfiguration. +func (in *RestoreSnapshotConfiguration) DeepCopy() *RestoreSnapshotConfiguration { if in == nil { return nil } - out := new(SnapshotRestoreBackupConfiguration) + out := new(RestoreSnapshotConfiguration) in.DeepCopyInto(out) return out } diff --git a/go.mod b/go.mod index bf5a19af72..4b5d6b9de7 100644 --- a/go.mod +++ b/go.mod @@ -44,6 +44,7 @@ require ( k8s.io/api v0.26.1 k8s.io/apimachinery v0.26.1 k8s.io/client-go v0.26.1 + k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 sigs.k8s.io/controller-runtime v0.14.1 sigs.k8s.io/controller-tools v0.11.1 sigs.k8s.io/yaml v1.3.0 @@ -153,7 +154,6 @@ require ( k8s.io/component-base v0.26.1 // indirect k8s.io/klog/v2 v2.80.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/pkg/clients/docdb/fake/fake.go b/pkg/clients/docdb/fake/fake.go index 1fa8adf087..99b1f525b0 100644 --- a/pkg/clients/docdb/fake/fake.go +++ b/pkg/clients/docdb/fake/fake.go @@ -53,6 +53,9 @@ type MockDocDBClient struct { MockModifyDBClusterWithContext func(context.Context, *docdb.ModifyDBClusterInput, []request.Option) (*docdb.ModifyDBClusterOutput, error) MockDeleteDBClusterWithContext func(context.Context, *docdb.DeleteDBClusterInput, []request.Option) (*docdb.DeleteDBClusterOutput, error) + MockRestoreDBClusterFromSnapshotWithContext func(context.Context, *docdb.RestoreDBClusterFromSnapshotInput, []request.Option) (*docdb.RestoreDBClusterFromSnapshotOutput, error) + MockRestoreDBClusterToPointInTimeWithContext func(context.Context, *docdb.RestoreDBClusterToPointInTimeInput, []request.Option) (*docdb.RestoreDBClusterToPointInTimeOutput, error) + Called MockDocDBClientCall } @@ -328,6 +331,34 @@ func (m *MockDocDBClient) DeleteDBClusterWithContext(ctx context.Context, i *doc return m.MockDeleteDBClusterWithContext(ctx, i, opts) } +// CallRestoreDBClusterFromSnapshotWithContext to log call +type CallRestoreDBClusterFromSnapshotWithContext struct { + Ctx aws.Context + I *docdb.RestoreDBClusterFromSnapshotInput + Opts []request.Option +} + +// RestoreDBClusterFromSnapshotWithContext calls MockRestoreDBClusterFromSnapshotWithContext +func (m *MockDocDBClient) RestoreDBClusterFromSnapshotWithContext(ctx context.Context, i *docdb.RestoreDBClusterFromSnapshotInput, opts ...request.Option) (*docdb.RestoreDBClusterFromSnapshotOutput, error) { + m.Called.RestoreDBClusterFromSnapshotWithContext = append(m.Called.RestoreDBClusterFromSnapshotWithContext, &CallRestoreDBClusterFromSnapshotWithContext{Ctx: ctx, I: i, Opts: opts}) + + return m.MockRestoreDBClusterFromSnapshotWithContext(ctx, i, opts) +} + +// CallRestoreDBClusterToPointInTimeWithContext to log call +type CallRestoreDBClusterToPointInTimeWithContext struct { + Ctx aws.Context + I *docdb.RestoreDBClusterToPointInTimeInput + Opts []request.Option +} + +// RestoreDBClusterToPointInTimeWithContext calls MockRestoreDBClusterToPointInTimeWithContext +func (m *MockDocDBClient) RestoreDBClusterToPointInTimeWithContext(ctx context.Context, i *docdb.RestoreDBClusterToPointInTimeInput, opts ...request.Option) (*docdb.RestoreDBClusterToPointInTimeOutput, error) { + m.Called.RestoreDBClusterToPointInTimeWithContext = append(m.Called.RestoreDBClusterToPointInTimeWithContext, &CallRestoreDBClusterToPointInTimeWithContext{Ctx: ctx, I: i, Opts: opts}) + + return m.MockRestoreDBClusterToPointInTimeWithContext(ctx, i, opts) +} + // MockDocDBClientCall to log calls type MockDocDBClientCall struct { ListTagsForResource []*CallListTagsForResource @@ -353,4 +384,7 @@ type MockDocDBClientCall struct { CreateDBClusterWithContext []*CallCreateDBClusterWithContext ModifyDBClusterWithContext []*CallModifyDBClusterWithContext DeleteDBClusterWithContext []*CallDeleteDBClusterWithContext + + RestoreDBClusterFromSnapshotWithContext []*CallRestoreDBClusterFromSnapshotWithContext + RestoreDBClusterToPointInTimeWithContext []*CallRestoreDBClusterToPointInTimeWithContext } diff --git a/pkg/controller/docdb/dbcluster/setup.go b/pkg/controller/docdb/dbcluster/setup.go index 0f8b340129..06363c1e57 100644 --- a/pkg/controller/docdb/dbcluster/setup.go +++ b/pkg/controller/docdb/dbcluster/setup.go @@ -229,8 +229,8 @@ func (e *hooks) preCreate(ctx context.Context, cr *svcapitypes.DBCluster, obj *s obj.MasterUserPassword = awsclient.String(pw) if cr.Spec.ForProvider.RestoreFrom != nil { - switch *cr.Spec.ForProvider.RestoreFrom.Source { - case "Snapshot": + switch cr.Spec.ForProvider.RestoreFrom.Source { + case svcapitypes.RestoreSourceSnapshot: input := generateRestoreDBClusterFromSnapshotInput(cr) input.DBClusterIdentifier = obj.DBClusterIdentifier input.VpcSecurityGroupIds = obj.VpcSecurityGroupIds @@ -238,7 +238,7 @@ func (e *hooks) preCreate(ctx context.Context, cr *svcapitypes.DBCluster, obj *s if _, err = e.client.RestoreDBClusterFromSnapshotWithContext(ctx, input); err != nil { return errors.Wrap(err, errRestore) } - case "PointInTime": + case svcapitypes.RestoreSourcePointInTime: input := generateRestoreDBClusterToPointInTimeInput(cr) input.DBClusterIdentifier = obj.DBClusterIdentifier input.VpcSecurityGroupIds = obj.VpcSecurityGroupIds @@ -308,7 +308,7 @@ func generateRestoreDBClusterFromSnapshotInput(cr *svcapitypes.DBCluster) *svcsd } if cr.Spec.ForProvider.RestoreFrom != nil && cr.Spec.ForProvider.RestoreFrom.Snapshot != nil { - res.SetSnapshotIdentifier(*cr.Spec.ForProvider.RestoreFrom.Snapshot.SnapshotIdentifier) + res.SetSnapshotIdentifier(cr.Spec.ForProvider.RestoreFrom.Snapshot.SnapshotIdentifier) } if cr.Spec.ForProvider.Tags != nil { @@ -324,7 +324,6 @@ func generateRestoreDBClusterFromSnapshotInput(cr *svcapitypes.DBCluster) *svcsd } func generateRestoreDBClusterToPointInTimeInput(cr *svcapitypes.DBCluster) *svcsdk.RestoreDBClusterToPointInTimeInput { // nolint:gocyclo - p := cr.Spec.ForProvider res := &svcsdk.RestoreDBClusterToPointInTimeInput{ DBSubnetGroupName: p.DBSubnetGroupName, @@ -332,17 +331,17 @@ func generateRestoreDBClusterToPointInTimeInput(cr *svcapitypes.DBCluster) *svcs EnableCloudwatchLogsExports: p.EnableCloudwatchLogsExports, KmsKeyId: p.KMSKeyID, Port: p.Port, - UseLatestRestorableTime: &p.RestoreFrom.PointInTime.UseLatestRestorableTime, + UseLatestRestorableTime: p.RestoreFrom.PointInTime.UseLatestRestorableTime, VpcSecurityGroupIds: p.VPCSecurityGroupIDs, } - if p.RestoreFrom.PointInTime != nil && p.RestoreFrom.PointInTime.RestoreTime != nil { - res.RestoreToTime = &p.RestoreFrom.PointInTime.RestoreTime.Time - } - if p.RestoreFrom.PointInTime != nil && p.RestoreFrom.PointInTime.RestoreTime != nil { - res.RestoreType = p.RestoreFrom.PointInTime.RestoreType - } - if p.RestoreFrom.PointInTime != nil && p.RestoreFrom.PointInTime.SourceDBClusterIdentifier != nil { - res.SourceDBClusterIdentifier = p.RestoreFrom.PointInTime.SourceDBClusterIdentifier + if p.RestoreFrom != nil { + if p.RestoreFrom.PointInTime != nil { + if p.RestoreFrom.PointInTime.RestoreTime != nil { + res.SetRestoreToTime(p.RestoreFrom.PointInTime.RestoreTime.Time) + } + res.RestoreType = p.RestoreFrom.PointInTime.RestoreType + res.SourceDBClusterIdentifier = &p.RestoreFrom.PointInTime.SourceDBClusterIdentifier + } } if cr.Spec.ForProvider.Tags != nil { var tags []*svcsdk.Tag diff --git a/pkg/controller/docdb/dbcluster/setup_test.go b/pkg/controller/docdb/dbcluster/setup_test.go index 864715270b..48dec6bbdc 100644 --- a/pkg/controller/docdb/dbcluster/setup_test.go +++ b/pkg/controller/docdb/dbcluster/setup_test.go @@ -20,10 +20,13 @@ import ( "context" "strconv" "testing" + "time" "github.com/google/go-cmp/cmp" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/aws/aws-sdk-go/aws/request" @@ -86,6 +89,8 @@ var ( testErrModifyDBClusterFailed = "ModifyDBCluster failed" testErrBoom = "boom" testErrGetSecret = "testErrGetSecret" + + timeNow = time.Now() ) type args struct { @@ -297,6 +302,24 @@ func withFinalDBSnapshotIdentifier(value string) docDBModifier { } } +func withRestoreFromSnapshot(v *svcapitypes.RestoreSnapshotConfiguration) docDBModifier { + return func(o *svcapitypes.DBCluster) { + o.Spec.ForProvider.RestoreFrom = &svcapitypes.RestoreDBClusterBackupConfiguration{ + Snapshot: v, + Source: svcapitypes.RestoreSourceSnapshot, + } + } +} + +func withRestoreToPointInTime(v *svcapitypes.RestorePointInTimeConfiguration) docDBModifier { + return func(o *svcapitypes.DBCluster) { + o.Spec.ForProvider.RestoreFrom = &svcapitypes.RestoreDBClusterBackupConfiguration{ + PointInTime: v, + Source: svcapitypes.RestoreSourcePointInTime, + } + } +} + func mergeTags(lists ...[]*svcapitypes.Tag) []*svcapitypes.Tag { res := []*svcapitypes.Tag{} for _, list := range lists { @@ -1964,6 +1987,461 @@ func TestCreate(t *testing.T) { }, }, }, + "SuccessfulRestoreFromSnapshot": { + args: args{ + kube: &test.MockClient{ + MockGet: func(ctx context.Context, key client.ObjectKey, obj client.Object) error { + s := obj.(*v1.Secret) + s.Data = map[string][]byte{ + testMasterPasswordSecretKey: []byte(testMasterUserPassword), + } + return nil + }, + }, + docdb: &fake.MockDocDBClient{ + MockRestoreDBClusterFromSnapshotWithContext: func(c context.Context, cdpgi *docdb.RestoreDBClusterFromSnapshotInput, o []request.Option) (*docdb.RestoreDBClusterFromSnapshotOutput, error) { + return &docdb.RestoreDBClusterFromSnapshotOutput{ + DBCluster: &docdb.DBCluster{ + AvailabilityZones: []*string{ + &testAvailabilityZone, + &testOtherAvailabilityZone, + }, + BackupRetentionPeriod: awsclient.Int64(testBackupRetentionPeriod), + DBClusterParameterGroup: &testDBClusterParameterGroupName, + DBClusterIdentifier: awsclient.String(testDBClusterIdentifier), + DBClusterArn: awsclient.String(testDBClusterArn), + DeletionProtection: awsclient.Bool(true), + Endpoint: awsclient.String(testEndpoint), + Engine: &testEngine, + EngineVersion: &testEngineVersion, + KmsKeyId: &testKMSKeyID, + MasterUsername: &testMasterUserName, + ReaderEndpoint: awsclient.String(testReaderEndpoint), + Port: awsclient.Int64(testPort), + PreferredBackupWindow: &testPreferredBackupWindow, + PreferredMaintenanceWindow: &testPreferredMaintenanceWindow, + StorageEncrypted: awsclient.Bool(true), + }, + }, nil + }, + MockCreateDBClusterWithContext: func(c context.Context, cdpgi *docdb.CreateDBClusterInput, o []request.Option) (*docdb.CreateDBClusterOutput, error) { + return &docdb.CreateDBClusterOutput{ + DBCluster: &docdb.DBCluster{ + AvailabilityZones: []*string{ + &testAvailabilityZone, + &testOtherAvailabilityZone, + }, + BackupRetentionPeriod: awsclient.Int64(testBackupRetentionPeriod), + DBClusterParameterGroup: &testDBClusterParameterGroupName, + DBClusterIdentifier: awsclient.String(testDBClusterIdentifier), + DBClusterArn: awsclient.String(testDBClusterArn), + DeletionProtection: awsclient.Bool(true), + Endpoint: awsclient.String(testEndpoint), + Engine: &testEngine, + EngineVersion: &testEngineVersion, + KmsKeyId: &testKMSKeyID, + MasterUsername: &testMasterUserName, + ReaderEndpoint: awsclient.String(testReaderEndpoint), + Port: awsclient.Int64(testPort), + PreferredBackupWindow: &testPreferredBackupWindow, + PreferredMaintenanceWindow: &testPreferredMaintenanceWindow, + StorageEncrypted: awsclient.Bool(true), + }, + }, nil + }, + }, + cr: instance( + withDBClusterIdentifier(testDBClusterIdentifier), + withExternalName(testDBClusterIdentifier), + withAvailabilityZones( + testAvailabilityZone, + testOtherAvailabilityZone, + ), + withBackupRetentionPeriod(testBackupRetentionPeriod), + withDBClusterParameterGroupName(testDBClusterParameterGroupName), + withDBSubnetGroup(testDBSubnetGroupName), + withDeletionProtection(true), + withEnableCloudWatchLogsExports( + testCloudWatchLog, + testOtherCloudWatchLog, + ), + withEngine(testEngine), + withEngineVersion(testEngineVersion), + withKmsKeyID(testKMSKeyID), + withMasterUserName(testMasterUserName), + withPort(testPort), + withPreSignedURL(testPresignedURL), + withPreferredBackupWindow(testPreferredBackupWindow), + withPreferredMaintenanceWindow(testPreferredMaintenanceWindow), + withStorageEncrypted(true), + withTags( + &svcapitypes.Tag{Key: awsclient.String(testTagKey), Value: awsclient.String(testTagValue)}, + &svcapitypes.Tag{Key: awsclient.String(testOtherTagKey), Value: awsclient.String(testOtherTagValue)}, + ), + withVpcSecurityGroupIds( + testVpcSecurityGroup, + testOtherVpcSecurityGroup, + ), + withMasterPasswordSecretRef(testMasterPasswordSecretNamespace, testMasterPasswordSecretName, testMasterPasswordSecretKey), + withRestoreFromSnapshot(&svcapitypes.RestoreSnapshotConfiguration{ + SnapshotIdentifier: "abcd", + }), + ), + }, + want: want{ + cr: instance( + withDBClusterIdentifier(testDBClusterIdentifier), + withExternalName(testDBClusterIdentifier), + withConditions(xpv1.Creating()), + withAvailabilityZones( + testAvailabilityZone, + testOtherAvailabilityZone, + ), + withBackupRetentionPeriod(testBackupRetentionPeriod), + withDBClusterParameterGroupName(testDBClusterParameterGroupName), + withDBSubnetGroup(testDBSubnetGroupName), + withStatusDBClusterArn(testDBClusterArn), + withDeletionProtection(true), + withEnableCloudWatchLogsExports( + testCloudWatchLog, + testOtherCloudWatchLog, + ), + withEngine(testEngine), + withEngineVersion(testEngineVersion), + withKmsKeyID(testKMSKeyID), + withMasterUserName(testMasterUserName), + withPort(testPort), + withPreSignedURL(testPresignedURL), + withPreferredBackupWindow(testPreferredBackupWindow), + withPreferredMaintenanceWindow(testPreferredMaintenanceWindow), + withStorageEncrypted(true), + withTags( + &svcapitypes.Tag{Key: awsclient.String(testTagKey), Value: awsclient.String(testTagValue)}, + &svcapitypes.Tag{Key: awsclient.String(testOtherTagKey), Value: awsclient.String(testOtherTagValue)}, + ), + withVpcSecurityGroupIds( + testVpcSecurityGroup, + testOtherVpcSecurityGroup, + ), + withEndpoint(testEndpoint), + withReaderEndpoint(testReaderEndpoint), + withMasterPasswordSecretRef(testMasterPasswordSecretNamespace, testMasterPasswordSecretName, testMasterPasswordSecretKey), + withStatusDBClusterParameterGroupName(testDBClusterParameterGroupName), + withRestoreFromSnapshot(&svcapitypes.RestoreSnapshotConfiguration{ + SnapshotIdentifier: "abcd", + }), + ), + result: managed.ExternalCreation{ + ConnectionDetails: generateConnectionDetails( + testMasterUserName, + testMasterUserPassword, + testReaderEndpoint, + testEndpoint, + testPort, + ), + }, + docdb: fake.MockDocDBClientCall{ + RestoreDBClusterFromSnapshotWithContext: []*fake.CallRestoreDBClusterFromSnapshotWithContext{ + { + Ctx: context.Background(), + I: &docdb.RestoreDBClusterFromSnapshotInput{ + DBClusterIdentifier: awsclient.String(testDBClusterIdentifier), + AvailabilityZones: toStringPtrArray( + testAvailabilityZone, + testOtherAvailabilityZone, + ), + DBSubnetGroupName: awsclient.String(testDBSubnetGroupName), + DeletionProtection: awsclient.Bool(true), + EnableCloudwatchLogsExports: toStringPtrArray( + testCloudWatchLog, + testOtherCloudWatchLog, + ), + Engine: awsclient.String(testEngine), + EngineVersion: awsclient.String(testEngineVersion), + KmsKeyId: awsclient.String(testKMSKeyID), + Port: awsclient.Int64(testPort), + VpcSecurityGroupIds: toStringPtrArray( + testVpcSecurityGroup, + testOtherVpcSecurityGroup, + ), + Tags: []*docdb.Tag{ + {Key: awsclient.String(testTagKey), Value: awsclient.String(testTagValue)}, + {Key: awsclient.String(testOtherTagKey), Value: awsclient.String(testOtherTagValue)}, + }, + SnapshotIdentifier: pointer.String("abcd"), + }, + }, + }, + CreateDBClusterWithContext: []*fake.CallCreateDBClusterWithContext{ + { + Ctx: context.Background(), + I: &docdb.CreateDBClusterInput{ + DBClusterIdentifier: awsclient.String(testDBClusterIdentifier), + AvailabilityZones: toStringPtrArray( + testAvailabilityZone, + testOtherAvailabilityZone, + ), + BackupRetentionPeriod: awsclient.Int64(testBackupRetentionPeriod), + DBClusterParameterGroupName: awsclient.String(testDBClusterParameterGroupName), + DBSubnetGroupName: awsclient.String(testDBSubnetGroupName), + DeletionProtection: awsclient.Bool(true), + EnableCloudwatchLogsExports: toStringPtrArray( + testCloudWatchLog, + testOtherCloudWatchLog, + ), + Engine: awsclient.String(testEngine), + EngineVersion: awsclient.String(testEngineVersion), + KmsKeyId: awsclient.String(testKMSKeyID), + MasterUsername: awsclient.String(testMasterUserName), + MasterUserPassword: awsclient.String(testMasterUserPassword), + Port: awsclient.Int64(testPort), + PreSignedUrl: awsclient.String(testPresignedURL), + PreferredBackupWindow: awsclient.String(testPreferredBackupWindow), + PreferredMaintenanceWindow: awsclient.String(testPreferredMaintenanceWindow), + StorageEncrypted: awsclient.Bool(true), + VpcSecurityGroupIds: toStringPtrArray( + testVpcSecurityGroup, + testOtherVpcSecurityGroup, + ), + Tags: []*docdb.Tag{ + {Key: awsclient.String(testTagKey), Value: awsclient.String(testTagValue)}, + {Key: awsclient.String(testOtherTagKey), Value: awsclient.String(testOtherTagValue)}, + }, + }, + }, + }, + }, + }, + }, + "SuccessfulRestoreFromPointInTime": { + args: args{ + kube: &test.MockClient{ + MockGet: func(ctx context.Context, key client.ObjectKey, obj client.Object) error { + s := obj.(*v1.Secret) + s.Data = map[string][]byte{ + testMasterPasswordSecretKey: []byte(testMasterUserPassword), + } + return nil + }, + }, + docdb: &fake.MockDocDBClient{ + MockRestoreDBClusterToPointInTimeWithContext: func(c context.Context, cdpgi *docdb.RestoreDBClusterToPointInTimeInput, o []request.Option) (*docdb.RestoreDBClusterToPointInTimeOutput, error) { + return &docdb.RestoreDBClusterToPointInTimeOutput{ + DBCluster: &docdb.DBCluster{ + AvailabilityZones: []*string{ + &testAvailabilityZone, + &testOtherAvailabilityZone, + }, + BackupRetentionPeriod: awsclient.Int64(testBackupRetentionPeriod), + DBClusterParameterGroup: &testDBClusterParameterGroupName, + DBClusterIdentifier: awsclient.String(testDBClusterIdentifier), + DBClusterArn: awsclient.String(testDBClusterArn), + DeletionProtection: awsclient.Bool(true), + Endpoint: awsclient.String(testEndpoint), + Engine: &testEngine, + EngineVersion: &testEngineVersion, + KmsKeyId: &testKMSKeyID, + MasterUsername: &testMasterUserName, + ReaderEndpoint: awsclient.String(testReaderEndpoint), + Port: awsclient.Int64(testPort), + PreferredBackupWindow: &testPreferredBackupWindow, + PreferredMaintenanceWindow: &testPreferredMaintenanceWindow, + StorageEncrypted: awsclient.Bool(true), + }, + }, nil + }, + MockCreateDBClusterWithContext: func(c context.Context, cdpgi *docdb.CreateDBClusterInput, o []request.Option) (*docdb.CreateDBClusterOutput, error) { + return &docdb.CreateDBClusterOutput{ + DBCluster: &docdb.DBCluster{ + AvailabilityZones: []*string{ + &testAvailabilityZone, + &testOtherAvailabilityZone, + }, + BackupRetentionPeriod: awsclient.Int64(testBackupRetentionPeriod), + DBClusterParameterGroup: &testDBClusterParameterGroupName, + DBClusterIdentifier: awsclient.String(testDBClusterIdentifier), + DBClusterArn: awsclient.String(testDBClusterArn), + DeletionProtection: awsclient.Bool(true), + Endpoint: awsclient.String(testEndpoint), + Engine: &testEngine, + EngineVersion: &testEngineVersion, + KmsKeyId: &testKMSKeyID, + MasterUsername: &testMasterUserName, + ReaderEndpoint: awsclient.String(testReaderEndpoint), + Port: awsclient.Int64(testPort), + PreferredBackupWindow: &testPreferredBackupWindow, + PreferredMaintenanceWindow: &testPreferredMaintenanceWindow, + StorageEncrypted: awsclient.Bool(true), + }, + }, nil + }, + }, + cr: instance( + withDBClusterIdentifier(testDBClusterIdentifier), + withExternalName(testDBClusterIdentifier), + withAvailabilityZones( + testAvailabilityZone, + testOtherAvailabilityZone, + ), + withBackupRetentionPeriod(testBackupRetentionPeriod), + withDBClusterParameterGroupName(testDBClusterParameterGroupName), + withDBSubnetGroup(testDBSubnetGroupName), + withDeletionProtection(true), + withEnableCloudWatchLogsExports( + testCloudWatchLog, + testOtherCloudWatchLog, + ), + withEngine(testEngine), + withEngineVersion(testEngineVersion), + withKmsKeyID(testKMSKeyID), + withMasterUserName(testMasterUserName), + withPort(testPort), + withPreSignedURL(testPresignedURL), + withPreferredBackupWindow(testPreferredBackupWindow), + withPreferredMaintenanceWindow(testPreferredMaintenanceWindow), + withStorageEncrypted(true), + withTags( + &svcapitypes.Tag{Key: awsclient.String(testTagKey), Value: awsclient.String(testTagValue)}, + &svcapitypes.Tag{Key: awsclient.String(testOtherTagKey), Value: awsclient.String(testOtherTagValue)}, + ), + withVpcSecurityGroupIds( + testVpcSecurityGroup, + testOtherVpcSecurityGroup, + ), + withMasterPasswordSecretRef(testMasterPasswordSecretNamespace, testMasterPasswordSecretName, testMasterPasswordSecretKey), + withRestoreToPointInTime(&svcapitypes.RestorePointInTimeConfiguration{ + RestoreTime: &metav1.Time{Time: timeNow}, + UseLatestRestorableTime: pointer.Bool(true), + SourceDBClusterIdentifier: "abcd", + RestoreType: pointer.String("full-copy"), + }), + ), + }, + want: want{ + cr: instance( + withDBClusterIdentifier(testDBClusterIdentifier), + withExternalName(testDBClusterIdentifier), + withConditions(xpv1.Creating()), + withAvailabilityZones( + testAvailabilityZone, + testOtherAvailabilityZone, + ), + withBackupRetentionPeriod(testBackupRetentionPeriod), + withDBClusterParameterGroupName(testDBClusterParameterGroupName), + withDBSubnetGroup(testDBSubnetGroupName), + withStatusDBClusterArn(testDBClusterArn), + withDeletionProtection(true), + withEnableCloudWatchLogsExports( + testCloudWatchLog, + testOtherCloudWatchLog, + ), + withEngine(testEngine), + withEngineVersion(testEngineVersion), + withKmsKeyID(testKMSKeyID), + withMasterUserName(testMasterUserName), + withPort(testPort), + withPreSignedURL(testPresignedURL), + withPreferredBackupWindow(testPreferredBackupWindow), + withPreferredMaintenanceWindow(testPreferredMaintenanceWindow), + withStorageEncrypted(true), + withTags( + &svcapitypes.Tag{Key: awsclient.String(testTagKey), Value: awsclient.String(testTagValue)}, + &svcapitypes.Tag{Key: awsclient.String(testOtherTagKey), Value: awsclient.String(testOtherTagValue)}, + ), + withVpcSecurityGroupIds( + testVpcSecurityGroup, + testOtherVpcSecurityGroup, + ), + withEndpoint(testEndpoint), + withReaderEndpoint(testReaderEndpoint), + withMasterPasswordSecretRef(testMasterPasswordSecretNamespace, testMasterPasswordSecretName, testMasterPasswordSecretKey), + withStatusDBClusterParameterGroupName(testDBClusterParameterGroupName), + withRestoreToPointInTime(&svcapitypes.RestorePointInTimeConfiguration{ + RestoreTime: &metav1.Time{Time: timeNow}, + UseLatestRestorableTime: pointer.Bool(true), + SourceDBClusterIdentifier: "abcd", + RestoreType: pointer.String("full-copy"), + }), + ), + result: managed.ExternalCreation{ + ConnectionDetails: generateConnectionDetails( + testMasterUserName, + testMasterUserPassword, + testReaderEndpoint, + testEndpoint, + testPort, + ), + }, + docdb: fake.MockDocDBClientCall{ + RestoreDBClusterToPointInTimeWithContext: []*fake.CallRestoreDBClusterToPointInTimeWithContext{ + { + Ctx: context.Background(), + I: &docdb.RestoreDBClusterToPointInTimeInput{ + DBClusterIdentifier: awsclient.String(testDBClusterIdentifier), + DBSubnetGroupName: awsclient.String(testDBSubnetGroupName), + DeletionProtection: awsclient.Bool(true), + EnableCloudwatchLogsExports: toStringPtrArray( + testCloudWatchLog, + testOtherCloudWatchLog, + ), + KmsKeyId: awsclient.String(testKMSKeyID), + Port: awsclient.Int64(testPort), + VpcSecurityGroupIds: toStringPtrArray( + testVpcSecurityGroup, + testOtherVpcSecurityGroup, + ), + Tags: []*docdb.Tag{ + {Key: awsclient.String(testTagKey), Value: awsclient.String(testTagValue)}, + {Key: awsclient.String(testOtherTagKey), Value: awsclient.String(testOtherTagValue)}, + }, + RestoreToTime: &timeNow, + UseLatestRestorableTime: pointer.Bool(true), + SourceDBClusterIdentifier: pointer.String("abcd"), + RestoreType: pointer.String("full-copy"), + }, + }, + }, + CreateDBClusterWithContext: []*fake.CallCreateDBClusterWithContext{ + { + Ctx: context.Background(), + I: &docdb.CreateDBClusterInput{ + DBClusterIdentifier: awsclient.String(testDBClusterIdentifier), + AvailabilityZones: toStringPtrArray( + testAvailabilityZone, + testOtherAvailabilityZone, + ), + BackupRetentionPeriod: awsclient.Int64(testBackupRetentionPeriod), + DBClusterParameterGroupName: awsclient.String(testDBClusterParameterGroupName), + DBSubnetGroupName: awsclient.String(testDBSubnetGroupName), + DeletionProtection: awsclient.Bool(true), + EnableCloudwatchLogsExports: toStringPtrArray( + testCloudWatchLog, + testOtherCloudWatchLog, + ), + Engine: awsclient.String(testEngine), + EngineVersion: awsclient.String(testEngineVersion), + KmsKeyId: awsclient.String(testKMSKeyID), + MasterUsername: awsclient.String(testMasterUserName), + MasterUserPassword: awsclient.String(testMasterUserPassword), + Port: awsclient.Int64(testPort), + PreSignedUrl: awsclient.String(testPresignedURL), + PreferredBackupWindow: awsclient.String(testPreferredBackupWindow), + PreferredMaintenanceWindow: awsclient.String(testPreferredMaintenanceWindow), + StorageEncrypted: awsclient.Bool(true), + VpcSecurityGroupIds: toStringPtrArray( + testVpcSecurityGroup, + testOtherVpcSecurityGroup, + ), + Tags: []*docdb.Tag{ + {Key: awsclient.String(testTagKey), Value: awsclient.String(testTagValue)}, + {Key: awsclient.String(testOtherTagKey), Value: awsclient.String(testOtherTagValue)}, + }, + }, + }, + }, + }, + }, + }, "ErrorCreate": { args: args{ docdb: &fake.MockDocDBClient{