@@ -78,3 +78,86 @@ def render_join(elem: dict):
7878 else :
7979 raise ValueError ("Found unsupported item type while rendering Fn::Join" )
8080 return sep .join (rendered_body )
81+
82+
83+ @pytest .mark .parametrize (
84+ "config_file_name, keep_original_subnet" ,
85+ [
86+ ("config-1.yaml" , True ),
87+ ("config-2.yaml" , False ),
88+ ],
89+ )
90+ def test_target_group_with_config_files (mocker , test_datadir , config_file_name , keep_original_subnet ):
91+ """
92+ Test target group logical ID and name change when subnet is modified.
93+
94+ This test verifies that:
95+ 1. Target group logical ID and name are generated correctly
96+ 2. When subnet changes, both logical ID and target group name change
97+ 3. Target group name stays within AWS 32 char limit
98+
99+ This ensures that cluster updates with subnet changes create new target groups,
100+ avoiding "target group cannot be associated with more than one load balancer"
101+ and "target group name already exists" errors.
102+ """
103+ mock_aws_api (mocker )
104+ mock_bucket_object_utils (mocker )
105+
106+ def get_target_group_info (cdk_assets ):
107+ """Extract target group logical ID and name from CDK assets."""
108+ for asset in cdk_assets :
109+ asset_content = asset .get ("content" )
110+ if asset_content and "Resources" in asset_content :
111+ for resource_name , resource in asset_content ["Resources" ].items ():
112+ if resource .get ("Type" ) == "AWS::ElasticLoadBalancingV2::TargetGroup" :
113+ return resource_name , resource ["Properties" ]["Name" ]
114+ return None , None
115+
116+ def build_template (config_yaml ):
117+ """Build CDK template from config yaml."""
118+ cluster_config = ClusterSchema (cluster_name = "clustername" ).load (config_yaml )
119+ _ , cdk_assets = CDKTemplateBuilder ().build_cluster_template (
120+ cluster_config = cluster_config , bucket = dummy_cluster_bucket (), stack_name = "clustername"
121+ )
122+ return cdk_assets
123+
124+ def assert_target_group_info (logical_id , tg_name ):
125+ """Verify target group logical ID and name are not None and within AWS 32 char limit."""
126+ assert_that (logical_id ).is_not_none ()
127+ assert_that (tg_name ).is_not_none ()
128+ assert_that (len (tg_name )).is_less_than_or_equal_to (32 )
129+
130+ # Read yaml config
131+ input_yaml = load_yaml_dict (test_datadir / config_file_name )
132+ original_subnet = input_yaml ["LoginNodes" ]["Pools" ][0 ]["Networking" ]["SubnetIds" ][0 ]
133+
134+ # Build template with original subnet
135+ cdk_assets_original = build_template (input_yaml )
136+ logical_id_original , tg_name_original = get_target_group_info (cdk_assets_original )
137+
138+ # Verify original target group was created correctly
139+ assert_target_group_info (logical_id_original , tg_name_original )
140+
141+ # Modify subnet to a new value
142+ new_subnet = "subnet-12345678901234567"
143+ new_pool_count = 0
144+ if keep_original_subnet :
145+ new_subnet = original_subnet
146+ new_pool_count = 1
147+ input_yaml ["LoginNodes" ]["Pools" ][0 ]["Networking" ]["SubnetIds" ][0 ] = new_subnet
148+ input_yaml ["LoginNodes" ]["Pools" ][0 ]["Count" ] = new_pool_count
149+
150+ # Build template with new subnet
151+ cdk_assets_new = build_template (input_yaml )
152+ logical_id_new , tg_name_new = get_target_group_info (cdk_assets_new )
153+
154+ if keep_original_subnet :
155+ assert_that (logical_id_new ).is_equal_to (logical_id_original )
156+ assert_that (tg_name_new ).is_equal_to (tg_name_original )
157+ else :
158+ # Verify that both logical ID and target group name changed when subnet changed
159+ assert_that (logical_id_new ).is_not_equal_to (logical_id_original )
160+ assert_that (tg_name_new ).is_not_equal_to (tg_name_original )
161+
162+ # Verify new target group was created correctly
163+ assert_target_group_info (logical_id_new , tg_name_new )
0 commit comments