Skip to content

Commit e2cff0f

Browse files
authored
Only include DBSubnetGroupName inside ModifyDBInstanceRequest when there is delta (#61)
Issue #, if available: aws-controllers-k8s/community#1147 Description of changes: * By default, ACK code-generator creates `UpdateRequest` payload completely from desired state of the resource and does not consider `delta` between `desired` & `latest` while creating the UpdateRequest payload. * Due to above the UpdateRequest also contains the fields which are same between desired and latest state. * This works fine in most cases where AWS Update APIs ignore the no-op updates in the backend but RDS's `ModifyDBInstance` API does not. If ModifyDBInstance API tries to update `DBSubnetGroupName` with the same name, it returns an error "InvalidVPCNetworkStateFault: The specified DB instance is already in the target DB subnet group.\n\tstatus code: 400" * I have added a hook that checks for the delta of `DBSubnetGroupName` before making the ModifyDBInstance API call ----- * Tested manually and validated that the "InvalidVPCNetworkStateFault" error goes away * added e2e test as well covering above case By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 0465deb commit e2cff0f

File tree

10 files changed

+66
-5
lines changed

10 files changed

+66
-5
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
ack_generate_info:
2-
build_date: "2022-02-08T20:23:58Z"
2+
build_date: "2022-02-15T17:20:43Z"
33
build_hash: edec6dad2fbd530d615d01e96f5251a806e1f36d
44
go_version: go1.17.5
55
version: v0.16.5
66
api_directory_checksum: c5762d0b5707ca20866f2f0e85bc23863733ca11
77
api_version: v1alpha1
88
aws_sdk_go_version: v1.42.0
99
generator_config_info:
10-
file_checksum: 4b6518ecbce521a28d8a406d7b07f2662601136b
10+
file_checksum: a0cccebb7e683a3b9b6082b5cde6630fd5ad4237
1111
original_file_name: generator.yaml
1212
last_modification:
1313
reason: API generation

apis/v1alpha1/generator.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ resources:
120120
template_path: hooks/db_instance/sdk_read_many_post_set_output.go.tpl
121121
sdk_update_pre_build_request:
122122
template_path: hooks/db_instance/sdk_update_pre_build_request.go.tpl
123+
sdk_update_post_build_request:
124+
template_path: hooks/db_instance/sdk_update_post_build_request.go.tpl
123125
sdk_delete_pre_build_request:
124126
template_path: hooks/db_instance/sdk_delete_pre_build_request.go.tpl
125127
exceptions:

generator.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ resources:
120120
template_path: hooks/db_instance/sdk_read_many_post_set_output.go.tpl
121121
sdk_update_pre_build_request:
122122
template_path: hooks/db_instance/sdk_update_pre_build_request.go.tpl
123+
sdk_update_post_build_request:
124+
template_path: hooks/db_instance/sdk_update_post_build_request.go.tpl
123125
sdk_delete_pre_build_request:
124126
template_path: hooks/db_instance/sdk_delete_pre_build_request.go.tpl
125127
exceptions:

pkg/resource/db_instance/sdk.go

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// ModifyDBInstance call will return ValidationError when the
2+
// ModifyDBInstanceRequest contains the same DBSubnetGroupName
3+
// as the DBInstance. So, if there is no delta between
4+
// desired and latest for Spec.DBSubnetGroupName, exclude it
5+
// from ModifyDBInstanceRequest
6+
if !delta.DifferentAt("Spec.DBSubnetGroupName") {
7+
input.DBSubnetGroupName = nil
8+
}

test/e2e/bootstrap_resources.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class TestBootstrapResources:
2828
VPCID: str
2929
SubnetAZ1: str
3030
SubnetAZ2: str
31+
DBSubnetGroupName: str
3132

3233
_bootstrap_resources = None
3334

test/e2e/resources/db_instance_postgres13_t3_micro.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ spec:
77
copyTagsToSnapshot: $COPY_TAGS_TO_SNAPSHOT
88
dbInstanceClass: db.t3.micro
99
dbInstanceIdentifier: $DB_INSTANCE_ID
10+
dbSubnetGroupName: $DB_SUBNET_GROUP_NAME
1011
engine: postgres
1112
engineVersion: "13.2"
1213
masterUsername: root

test/e2e/service_bootstrap.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import time
1919

2020
from acktest import resources
21+
from acktest.resources import random_suffix_name
2122
from acktest.aws.identity import get_region
2223
from e2e import bootstrap_directory
2324
from e2e.bootstrap_resources import (
@@ -94,6 +95,21 @@ def create_subnet(vpc_id: str, az_id: str, cidr: str) -> str:
9495
return subnet_id
9596

9697

98+
def create_db_subnet_group(db_subnet_group_name: str, subnet_az1_id: str, subnet_az2_id:str):
99+
region = get_region()
100+
rds = boto3.client("rds", region_name=region)
101+
102+
logging.debug(f"Creating DBSubnetGroup with name {db_subnet_group_name}")
103+
104+
rds.create_db_subnet_group(
105+
DBSubnetGroupName=db_subnet_group_name,
106+
DBSubnetGroupDescription='DBSubnetGroup for e2e testing of ACK rds-controller',
107+
SubnetIds=[subnet_az1_id, subnet_az2_id],
108+
)
109+
110+
logging.info(f"Created DBSubnetGroup {db_subnet_group_name}")
111+
112+
97113
def service_bootstrap() -> dict:
98114
logging.getLogger().setLevel(logging.INFO)
99115
region = get_region()
@@ -103,14 +119,17 @@ def service_bootstrap() -> dict:
103119
subnet_az1_id = create_subnet(vpc_id, az1, SUBNET_AZ1_CIDR)
104120
az2 = f"{region}b"
105121
subnet_az2_id = create_subnet(vpc_id, az2, SUBNET_AZ2_CIDR)
106-
122+
db_subnet_group_name = random_suffix_name("ack-test-subnet-group", 30)
123+
create_db_subnet_group(db_subnet_group_name, subnet_az1_id, subnet_az2_id)
107124

108125
return TestBootstrapResources(
109126
vpc_id,
110127
subnet_az1_id,
111128
subnet_az2_id,
129+
db_subnet_group_name
112130
).__dict__
113131

132+
114133
if __name__ == "__main__":
115134
config = service_bootstrap()
116135
# Write config to current directory by default

test/e2e/service_cleanup.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,29 @@ def delete_vpc(vpc_id: str):
4242
logging.info(f"Deleted VPC {vpc_id}")
4343

4444

45+
def delete_db_subnet_group(db_subnet_group_name: str):
46+
region = get_region()
47+
rds = boto3.client("rds", region_name=region)
48+
49+
rds.delete_db_subnet_group(
50+
DBSubnetGroupName=db_subnet_group_name,
51+
)
52+
53+
logging.info(f"Deleted DBSubnetGroup {db_subnet_group_name}")
54+
55+
4556
def service_cleanup(config: dict):
4657
logging.getLogger().setLevel(logging.INFO)
4758

4859
resources = TestBootstrapResources(
4960
**config
5061
)
5162

63+
try:
64+
delete_db_subnet_group(resources.DBSubnetGroupName)
65+
except:
66+
logging.exception(f"Unable to delete DBSubnetGroup {resources.DBSubnetGroupName}")
67+
5268
try:
5369
delete_subnet(resources.SubnetAZ1)
5470
except:
@@ -64,6 +80,7 @@ def service_cleanup(config: dict):
6480
except:
6581
logging.exception(f"Unable to delete VPC {resources.VPCID}")
6682

83+
6784
if __name__ == "__main__":
6885
bootstrap_config = resources.read_bootstrap_config(bootstrap_directory)
6986
service_cleanup(bootstrap_config)

test/e2e/tests/test_db_instance.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import pytest
2020

2121
from acktest.k8s import resource as k8s
22+
from acktest.resources import random_suffix_name
2223
from e2e import service_marker, CRD_GROUP, CRD_VERSION, load_rds_resource
2324
from e2e.replacement_values import REPLACEMENT_VALUES
2425
from e2e.bootstrap_resources import get_bootstrap_resources
@@ -67,7 +68,7 @@ def test_crud_postgres13_t3_micro(
6768
self,
6869
k8s_secret,
6970
):
70-
db_instance_id = "pg13-t3-micro"
71+
db_instance_id = random_suffix_name("pg13-t3-micro", 20)
7172
secret = k8s_secret(
7273
self.MUP_NS,
7374
self.MUP_SEC_NAME,
@@ -81,6 +82,7 @@ def test_crud_postgres13_t3_micro(
8182
replacements["MASTER_USER_PASS_SECRET_NAMESPACE"] = secret.ns
8283
replacements["MASTER_USER_PASS_SECRET_NAME"] = secret.name
8384
replacements["MASTER_USER_PASS_SECRET_KEY"] = secret.key
85+
replacements["DB_SUBNET_GROUP_NAME"] = get_bootstrap_resources().DBSubnetGroupName
8486

8587
resource_data = load_rds_resource(
8688
"db_instance_postgres13_t3_micro",
@@ -128,7 +130,8 @@ def test_crud_postgres13_t3_micro(
128130
# shows the new value of the field.
129131
latest = db_instance.get(db_instance_id)
130132
assert latest is not None
131-
assert latest['CopyTagsToSnapshot'] == False
133+
assert latest['CopyTagsToSnapshot'] is False
134+
assert latest['DBSubnetGroup']['DBSubnetGroupName'] == get_bootstrap_resources().DBSubnetGroupName
132135
updates = {
133136
"spec": {"copyTagsToSnapshot": True},
134137
}

0 commit comments

Comments
 (0)