Skip to content

Commit 26e36b9

Browse files
authored
Add annotations to configure final snapshot and automated backup deletion (#186)
This commit adds support for configuring delete options for DBInstances and DBclusters via resource annotations: - `SkipFinalSnapshot` (default: true): Skip taking a final snapshot before deletion - `FinalDBSnapshotIdentifier`: Specify the identifier of the final snapshot - `DeleteAutomatedBackups` (default: true): Delete automated backups associated with the instance/cluster The generator config is updated to use `sdk_delete_post_build_request` hook which parses the annotations and set the appropriate fields on `DeleteDBInstanceInput` and `DeleteDBClusterInput`. The default behaviour remains unchanged (skip final snapshot, retain automated backups), but users can now opt-in to taking a final snapshot or deleting automatedd backups by setting the corresponding annotations on the resource. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 8b189bf commit 26e36b9

File tree

12 files changed

+228
-29
lines changed

12 files changed

+228
-29
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
ack_generate_info:
2-
build_date: "2024-06-11T19:26:48Z"
2+
build_date: "2024-06-11T21:00:10Z"
33
build_hash: 14cef51778d471698018b6c38b604181a6948248
44
go_version: go1.22.3
55
version: v0.34.0
6-
api_directory_checksum: 471f6857e01011a1a487f29512fa093d340122d2
6+
api_directory_checksum: 03d7817f582e395d13fd3eb447996b9c6ff7a0e7
77
api_version: v1alpha1
88
aws_sdk_go_version: v1.44.232
99
generator_config_info:
10-
file_checksum: 00210e222c5049e16a3951f79273ec678156ed08
10+
file_checksum: 6289988e39ed3478c6a38753adc1298031f0acf9
1111
original_file_name: generator.yaml
1212
last_modification:
1313
reason: API generation

apis/v1alpha1/annotation.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,19 @@ var (
2727
// compute the "reference" delta, and can result in the rds-controller making unnecessary password
2828
// updates to the DBInstance or DBCluster.
2929
LastAppliedSecretAnnotation = fmt.Sprintf("%s/last-applied-secret-reference", GroupVersion.Group)
30+
// SkipFinalSnapshot is the annotation key used to skip the final snapshot when deleting a DBInstance
31+
// or DBCluster. If this annotation is set to "true", the final snapshot will be skipped. The default
32+
// value is "true" - meaning that when the annotation is not present, the final snapshot will be skipped.
33+
SkipFinalSnapshotAnnotation = fmt.Sprintf("%s/skip-final-snapshot", GroupVersion.Group)
34+
// FinalDBSnapshotIdentifier is the annotation key used to specify the final snapshot identifier when
35+
// deleting a DBInstance or DBCluster. If this annotation is set, the final snapshot will be created with
36+
// the specified identifier.
37+
//
38+
// If the SkipFinalSnapshot annotation is set to "true", this annotation will be ignored.
39+
FinalDBSnapshotIdentifierAnnotation = fmt.Sprintf("%s/final-db-snapshot-identifier", GroupVersion.Group)
40+
// DeleteAutomatedBackups is the annotation key used to specify whether automated backups should be
41+
// deleted when deleting a DBInstance or DBCluster. If this annotation is set to "true", automated backups
42+
// will be deleted. The default value is "false" - meaning that when the annotation is not present, automated
43+
// backups will not be deleted.
44+
DeleteAutomatedBackupsAnnotation = fmt.Sprintf("%s/delete-automated-backups", GroupVersion.Group)
3045
)

apis/v1alpha1/generator.yaml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,6 @@ operations:
4848
# This flag was designed as a protect flag but not necessary in controller
4949
# side when customer need to make the engine version change
5050
AllowMajorVersionUpgrade: true
51-
DeleteDBCluster:
52-
override_values:
53-
# Clearly this is not ideal, but will suffice until we add custom hook
54-
# points to the build_request methods to enable a genmeration of the
55-
# final snapshot identifier to use.
56-
SkipFinalSnapshot: true
5751
ModifyDBInstance:
5852
override_values:
5953
# The whole concept of a "maintenance window" isn't aligned with the
@@ -73,12 +67,6 @@ operations:
7367
# makes to a resource's Spec to be reconciled by the ACK service
7468
# controller, not a different service.
7569
AllowMajorVersionUpgrade: true
76-
DeleteDBInstance:
77-
override_values:
78-
# Clearly this is not ideal, but will suffice until we add custom hook
79-
# points to the build_request methods to enable a genmeration of the
80-
# final snapshot identifier to use.
81-
SkipFinalSnapshot: true
8270
resources:
8371
DBCluster:
8472
update_operation:
@@ -97,6 +85,8 @@ resources:
9785
template_path: hooks/db_cluster/sdk_read_many_post_set_output.go.tpl
9886
sdk_delete_pre_build_request:
9987
template_path: hooks/db_cluster/sdk_delete_pre_build_request.go.tpl
88+
sdk_delete_post_build_request:
89+
template_path: hooks/db_cluster/sdk_delete_post_build_request.go.tpl
10090
sdk_file_end:
10191
template_path: hooks/db_cluster/sdk_file_end.go.tpl
10292
exceptions:
@@ -228,6 +218,8 @@ resources:
228218
template_path: hooks/db_instance/sdk_update_post_set_output.go.tpl
229219
sdk_delete_pre_build_request:
230220
template_path: hooks/db_instance/sdk_delete_pre_build_request.go.tpl
221+
sdk_delete_post_build_request:
222+
template_path: hooks/db_instance/sdk_delete_post_build_request.go.tpl
231223
sdk_file_end:
232224
template_path: hooks/db_instance/sdk_file_end.go.tpl
233225
exceptions:

generator.yaml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,6 @@ operations:
4848
# This flag was designed as a protect flag but not necessary in controller
4949
# side when customer need to make the engine version change
5050
AllowMajorVersionUpgrade: true
51-
DeleteDBCluster:
52-
override_values:
53-
# Clearly this is not ideal, but will suffice until we add custom hook
54-
# points to the build_request methods to enable a genmeration of the
55-
# final snapshot identifier to use.
56-
SkipFinalSnapshot: true
5751
ModifyDBInstance:
5852
override_values:
5953
# The whole concept of a "maintenance window" isn't aligned with the
@@ -73,12 +67,6 @@ operations:
7367
# makes to a resource's Spec to be reconciled by the ACK service
7468
# controller, not a different service.
7569
AllowMajorVersionUpgrade: true
76-
DeleteDBInstance:
77-
override_values:
78-
# Clearly this is not ideal, but will suffice until we add custom hook
79-
# points to the build_request methods to enable a genmeration of the
80-
# final snapshot identifier to use.
81-
SkipFinalSnapshot: true
8270
resources:
8371
DBCluster:
8472
update_operation:
@@ -97,6 +85,8 @@ resources:
9785
template_path: hooks/db_cluster/sdk_read_many_post_set_output.go.tpl
9886
sdk_delete_pre_build_request:
9987
template_path: hooks/db_cluster/sdk_delete_pre_build_request.go.tpl
88+
sdk_delete_post_build_request:
89+
template_path: hooks/db_cluster/sdk_delete_post_build_request.go.tpl
10090
sdk_file_end:
10191
template_path: hooks/db_cluster/sdk_file_end.go.tpl
10292
exceptions:
@@ -228,6 +218,8 @@ resources:
228218
template_path: hooks/db_instance/sdk_update_post_set_output.go.tpl
229219
sdk_delete_pre_build_request:
230220
template_path: hooks/db_instance/sdk_delete_pre_build_request.go.tpl
221+
sdk_delete_post_build_request:
222+
template_path: hooks/db_instance/sdk_delete_post_build_request.go.tpl
231223
sdk_file_end:
232224
template_path: hooks/db_instance/sdk_file_end.go.tpl
233225
exceptions:

pkg/resource/db_cluster/hooks.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,19 @@ func compareSecretReferenceChanges(
350350
delta.Add("Spec.MasterUserPassword", oldRef, newRef)
351351
}
352352
}
353+
354+
// setDeleteDBClusterInput uses the resource annotations to complete
355+
// the input for the DeleteDBCluster API call.
356+
func setDeleteDBClusterInput(
357+
r *resource,
358+
input *svcsdk.DeleteDBClusterInput,
359+
) error {
360+
params, err := util.ParseDeletionAnnotations(r.ko.GetAnnotations())
361+
if err != nil {
362+
return err
363+
}
364+
input.SkipFinalSnapshot = params.SkipFinalSnapshot
365+
input.FinalDBSnapshotIdentifier = params.FinalDBSnapshotIdentifier
366+
input.DeleteAutomatedBackups = params.DeleteAutomatedBackup
367+
return nil
368+
}

pkg/resource/db_cluster/sdk.go

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/resource/db_instance/hooks.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,3 +565,19 @@ func compareSecretReferenceChanges(
565565
delta.Add("Spec.MasterUserPassword", oldRef, newRef)
566566
}
567567
}
568+
569+
// setDeleteDBInstanceInput uses the resource annotations to complete
570+
// the input for the DeleteDBInstance API call.
571+
func setDeleteDBInstanceInput(
572+
r *resource,
573+
input *svcsdk.DeleteDBInstanceInput,
574+
) error {
575+
params, err := util.ParseDeletionAnnotations(r.ko.GetAnnotations())
576+
if err != nil {
577+
return err
578+
}
579+
input.SkipFinalSnapshot = params.SkipFinalSnapshot
580+
input.FinalDBSnapshotIdentifier = params.FinalDBSnapshotIdentifier
581+
input.DeleteAutomatedBackups = params.DeleteAutomatedBackup
582+
return nil
583+
}

pkg/resource/db_instance/sdk.go

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/util/annotations.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package util
2+
3+
import (
4+
"strconv"
5+
6+
svcapitypes "github.com/aws-controllers-k8s/rds-controller/apis/v1alpha1"
7+
)
8+
9+
type DeleteInputAnnotationParameters struct {
10+
SkipFinalSnapshot *bool
11+
FinalDBSnapshotIdentifier *string
12+
DeleteAutomatedBackup *bool
13+
}
14+
15+
var (
16+
// If not specified skipFinalSnapshot will be set to true by default.
17+
//
18+
// Kept for historical purpuse: This was the value that we set in the generator.yaml
19+
// before writing this annotation parsing functions.
20+
//
21+
// DeleteDBCluster:
22+
// override_values:
23+
// # Clearly this is not ideal, but will suffice until we add custom hook
24+
// # points to the build_request methods to enable a genmeration of the
25+
// # final snapshot identifier to use.
26+
// SkipFinalSnapshot: true
27+
defaultSkipFinalSnapshot = true
28+
)
29+
30+
// parseDeletionAnnotations parses the deletion annotations on the supplied
31+
// resource.
32+
func ParseDeletionAnnotations(annotations map[string]string) (*DeleteInputAnnotationParameters, error) {
33+
params := &DeleteInputAnnotationParameters{
34+
SkipFinalSnapshot: &defaultSkipFinalSnapshot,
35+
}
36+
if len(annotations) == 0 {
37+
return params, nil
38+
}
39+
40+
// Parse SkipFinalSnapshot annotation
41+
skipFinalSnapshotAnnotationValue, ok := annotations[svcapitypes.SkipFinalSnapshotAnnotation]
42+
if ok && skipFinalSnapshotAnnotationValue != "" {
43+
skipFinalSnapshot, err := strconv.ParseBool(skipFinalSnapshotAnnotationValue)
44+
if err != nil {
45+
return nil, err
46+
}
47+
params.SkipFinalSnapshot = &skipFinalSnapshot
48+
}
49+
50+
// Parse FinalDBSnapshotIdentifier annotation
51+
finalDBSnapshotIdentifierAnnotationValue, ok := annotations[svcapitypes.FinalDBSnapshotIdentifierAnnotation]
52+
if ok {
53+
params.FinalDBSnapshotIdentifier = &finalDBSnapshotIdentifierAnnotationValue
54+
}
55+
56+
// Parse DeleteAutomatedBackup annotation
57+
deleteAutomatedBackupAnnotationValue, ok := annotations[svcapitypes.DeleteAutomatedBackupsAnnotation]
58+
if ok && deleteAutomatedBackupAnnotationValue != "" {
59+
deleteAutomatedBackup, err := strconv.ParseBool(deleteAutomatedBackupAnnotationValue)
60+
if err != nil {
61+
return nil, err
62+
}
63+
params.DeleteAutomatedBackup = &deleteAutomatedBackup
64+
}
65+
return params, nil
66+
}

pkg/util/annotations_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package util_test
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
svcapitypes "github.com/aws-controllers-k8s/rds-controller/apis/v1alpha1"
8+
"github.com/aws-controllers-k8s/rds-controller/pkg/util"
9+
"github.com/aws/aws-sdk-go/aws"
10+
)
11+
12+
func TestParseDeletionAnnotations(t *testing.T) {
13+
tests := []struct {
14+
name string
15+
annotations map[string]string
16+
want *util.DeleteInputAnnotationParameters
17+
wantErr bool
18+
}{
19+
{
20+
name: "no annotations",
21+
annotations: map[string]string{},
22+
want: &util.DeleteInputAnnotationParameters{
23+
SkipFinalSnapshot: aws.Bool(true),
24+
FinalDBSnapshotIdentifier: nil,
25+
DeleteAutomatedBackup: nil,
26+
},
27+
wantErr: false,
28+
},
29+
{
30+
name: "all annotations set - turn on all snapshot options",
31+
annotations: map[string]string{
32+
svcapitypes.SkipFinalSnapshotAnnotation: "false",
33+
svcapitypes.FinalDBSnapshotIdentifierAnnotation: "final-snapshot",
34+
svcapitypes.DeleteAutomatedBackupsAnnotation: "false",
35+
},
36+
want: &util.DeleteInputAnnotationParameters{
37+
SkipFinalSnapshot: aws.Bool(false),
38+
FinalDBSnapshotIdentifier: aws.String("final-snapshot"),
39+
DeleteAutomatedBackup: aws.Bool(false),
40+
},
41+
wantErr: false,
42+
},
43+
{
44+
name: "all annotations set - turn off all snapshot options",
45+
annotations: map[string]string{
46+
svcapitypes.SkipFinalSnapshotAnnotation: "true",
47+
svcapitypes.DeleteAutomatedBackupsAnnotation: "true",
48+
},
49+
want: &util.DeleteInputAnnotationParameters{
50+
SkipFinalSnapshot: aws.Bool(true),
51+
FinalDBSnapshotIdentifier: nil,
52+
DeleteAutomatedBackup: aws.Bool(true),
53+
},
54+
wantErr: false,
55+
},
56+
{
57+
name: "invalid SkipFinalSnapshot annotation",
58+
annotations: map[string]string{
59+
svcapitypes.SkipFinalSnapshotAnnotation: "invalid",
60+
},
61+
want: nil,
62+
wantErr: true,
63+
},
64+
{
65+
name: "invalid DeleteAutomatedBackups annotation",
66+
annotations: map[string]string{
67+
svcapitypes.DeleteAutomatedBackupsAnnotation: "invalid",
68+
},
69+
want: nil,
70+
wantErr: true,
71+
},
72+
}
73+
74+
for _, tt := range tests {
75+
t.Run(tt.name, func(t *testing.T) {
76+
got, err := util.ParseDeletionAnnotations(tt.annotations)
77+
if (err != nil) != tt.wantErr {
78+
t.Errorf("ParseDeletionAnnotations() error = %v, wantErr %v", err, tt.wantErr)
79+
return
80+
}
81+
if !reflect.DeepEqual(got, tt.want) {
82+
t.Errorf("ParseDeletionAnnotations() = %v, want %v", got, tt.want)
83+
}
84+
})
85+
}
86+
}

0 commit comments

Comments
 (0)