Skip to content

Commit b1b33cd

Browse files
authored
feat(terraform-init): use account tags for cloudformation tags (#5239)
* feat(terraform-init): use account tags for cloudformation tags * refactor(terraform-init): update tests tag values Signed-off-by: Di Wang <dwan@redhat.com>
1 parent bd1fbe4 commit b1b33cd

File tree

9 files changed

+209
-21
lines changed

9 files changed

+209
-21
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# qenerate: plugin=pydantic_v1
2+
3+
fragment AWSOrganization on AWSOrganization_v1 {
4+
payerAccount {
5+
organizationAccountTags
6+
}
7+
tags
8+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""
2+
Generated by qenerate plugin=pydantic_v1. DO NOT MODIFY MANUALLY!
3+
"""
4+
from collections.abc import Callable # noqa: F401 # pylint: disable=W0611
5+
from datetime import datetime # noqa: F401 # pylint: disable=W0611
6+
from enum import Enum # noqa: F401 # pylint: disable=W0611
7+
from typing import ( # noqa: F401 # pylint: disable=W0611
8+
Any,
9+
Optional,
10+
Union,
11+
)
12+
13+
from pydantic import ( # noqa: F401 # pylint: disable=W0611
14+
BaseModel,
15+
Extra,
16+
Field,
17+
Json,
18+
)
19+
20+
21+
class ConfiguredBaseModel(BaseModel):
22+
class Config:
23+
smart_union=True
24+
extra=Extra.forbid
25+
26+
27+
class AWSAccountV1(ConfiguredBaseModel):
28+
organization_account_tags: Optional[Json] = Field(..., alias="organizationAccountTags")
29+
30+
31+
class AWSOrganization(ConfiguredBaseModel):
32+
payer_account: AWSAccountV1 = Field(..., alias="payerAccount")
33+
tags: Json = Field(..., alias="tags")

reconcile/gql_definitions/terraform_init/aws_accounts.gql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ query TerraformInitAWSAccounts {
1515
disable {
1616
integrations
1717
}
18+
organization {
19+
...AWSOrganization
20+
}
1821
}
1922
}

reconcile/gql_definitions/terraform_init/aws_accounts.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,18 @@
1717
Json,
1818
)
1919

20+
from reconcile.gql_definitions.fragments.aws_organization import AWSOrganization
2021
from reconcile.gql_definitions.fragments.vault_secret import VaultSecret
2122

2223

2324
DEFINITION = """
25+
fragment AWSOrganization on AWSOrganization_v1 {
26+
payerAccount {
27+
organizationAccountTags
28+
}
29+
tags
30+
}
31+
2432
fragment VaultSecret on VaultSecret_v1 {
2533
path
2634
field
@@ -43,6 +51,9 @@
4351
disable {
4452
integrations
4553
}
54+
organization {
55+
...AWSOrganization
56+
}
4657
}
4758
}
4859
"""
@@ -70,6 +81,7 @@ class AWSAccountV1(ConfiguredBaseModel):
7081
resources_default_region: str = Field(..., alias="resourcesDefaultRegion")
7182
automation_token: VaultSecret = Field(..., alias="automationToken")
7283
disable: Optional[DisableClusterAutomationsV1] = Field(..., alias="disable")
84+
organization: Optional[AWSOrganization] = Field(..., alias="organization")
7385

7486

7587
class TerraformInitAWSAccountsQueryData(ConfiguredBaseModel):

reconcile/terraform_init/integration.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from reconcile.terraform_init.merge_request import Renderer, create_parser
1212
from reconcile.terraform_init.merge_request_manager import MergeRequestManager, MrData
1313
from reconcile.typed_queries.app_interface_repo_url import get_app_interface_repo_url
14+
from reconcile.typed_queries.aws_account_tags import get_aws_account_tags
1415
from reconcile.typed_queries.external_resources import get_settings
1516
from reconcile.typed_queries.github_orgs import get_github_orgs
1617
from reconcile.typed_queries.gitlab_instances import get_gitlab_instances
@@ -115,7 +116,7 @@ def reconcile_account(
115116
state_template: str,
116117
cloudformation_template: str,
117118
cloudformation_import_template: str,
118-
tags: dict[str, str],
119+
default_tags: dict[str, str],
119120
) -> None:
120121
"""
121122
Reconcile the terraform state for a given account.
@@ -140,7 +141,7 @@ def reconcile_account(
140141
state_template: str: Jinja2 template for the Terraform state configuration.
141142
cloudformation_template: str: CloudFormation template to create the S3 bucket.
142143
cloudformation_import_template: str: CloudFormation template to import existing S3 bucket.
143-
tags: dict[str, str]: Tags to apply to the CloudFormation stack.
144+
default_tags: dict[str, str]: Default tags to apply to the CloudFormation stack.
144145
145146
Returns:
146147
None
@@ -151,6 +152,8 @@ def reconcile_account(
151152
else f"terraform-{account.name}"
152153
)
153154

155+
tags = default_tags | get_aws_account_tags(account.organization)
156+
154157
if account.terraform_state is None:
155158
return self._provision_terraform_state(
156159
aws_api=aws_api,
@@ -324,5 +327,5 @@ def run(self, dry_run: bool, defer: Callable | None = None) -> None:
324327
state_template=state_template,
325328
cloudformation_template=cloudformation_template,
326329
cloudformation_import_template=cloudformation_import_template,
327-
tags=default_tags,
330+
default_tags=default_tags,
328331
)

reconcile/test/fixtures/terraform_init/accounts.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ accounts:
2121
resourcesDefaultRegion: us-east-1
2222
automationToken:
2323
path: path/to/creds
24+
organization:
25+
payerAccount:
26+
organizationAccountTags: '{"common_key": "not_final_common_value", "payer_key": "payer_value"}'
27+
tags: '{"common_key": "final_common_value", "account_key": "account_value"}'
2428

2529
# all accounts below must be ignored
2630
- name: no-terraform-username

reconcile/test/terraform_init/test_terraform_init_integration.py

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def test_terraform_init_integration_reconcile_account_with_new_account(
8585
state_template="{{bucket_name}}",
8686
cloudformation_template="cloudformation_template",
8787
cloudformation_import_template="cloudformation_import_template",
88-
tags={"env": "test"},
88+
default_tags={"env": "test"},
8989
)
9090

9191
aws_api.cloudformation.create_stack.assert_called_once_with(
@@ -119,7 +119,7 @@ def test_terraform_init_integration_reconcile_account_with_new_account_dry_run(
119119
state_template="{{bucket_name}}",
120120
cloudformation_template="cloudformation_template",
121121
cloudformation_import_template="cloudformation_import_template",
122-
tags={"env": "test"},
122+
default_tags={"env": "test"},
123123
)
124124

125125
aws_api.cloudformation.create_stack.assert_not_called()
@@ -149,7 +149,7 @@ def test_terraform_init_integration_reconcile_account_when_import_stack(
149149
state_template="{{bucket_name}}",
150150
cloudformation_template="cloudformation_template",
151151
cloudformation_import_template="cloudformation_import_template",
152-
tags={"env": "test"},
152+
default_tags={"env": "test"},
153153
)
154154

155155
aws_api.cloudformation.get_stack.assert_called_once_with(
@@ -160,13 +160,23 @@ def test_terraform_init_integration_reconcile_account_when_import_stack(
160160
change_set_name="import-existing-bucket",
161161
template_body="cloudformation_import_template",
162162
parameters={"BucketName": "existing-bucket"},
163-
tags={"env": "test"},
163+
tags={
164+
"account_key": "account_value",
165+
"common_key": "final_common_value",
166+
"env": "test",
167+
"payer_key": "payer_value",
168+
},
164169
)
165170
aws_api.cloudformation.update_stack.assert_called_once_with(
166171
stack_name="existing-bucket",
167172
template_body="cloudformation_template",
168173
parameters={"BucketName": "existing-bucket"},
169-
tags={"env": "test"},
174+
tags={
175+
"account_key": "account_value",
176+
"common_key": "final_common_value",
177+
"env": "test",
178+
"payer_key": "payer_value",
179+
},
170180
)
171181
merge_request_manager.create_merge_request.assert_not_called()
172182

@@ -188,7 +198,7 @@ def test_terraform_init_integration_reconcile_account_when_import_stack_dry_run(
188198
state_template="{{bucket_name}}",
189199
cloudformation_template="cloudformation_template",
190200
cloudformation_import_template="cloudformation_import_template",
191-
tags={"env": "test"},
201+
default_tags={"env": "test"},
192202
)
193203

194204
aws_api.cloudformation.get_stack.assert_called_once_with(
@@ -208,7 +218,12 @@ def test_terraform_init_integration_reconcile_account_when_tags_mismatch(
208218
account = next(a for a in aws_accounts if a.name == "terraform-state-already-set")
209219
aws_api.cloudformation.get_stack.return_value = {
210220
"StackName": "terraform-terraform-state-already-set",
211-
"Tags": [{"Key": "env", "Value": "test-old"}],
221+
"Tags": [
222+
{"Key": "account_key", "Value": "account_value"},
223+
{"Key": "common_key", "Value": "final_common_value"},
224+
{"Key": "env", "Value": "test-old"},
225+
{"Key": "payer_key", "Value": "payer_value"},
226+
],
212227
}
213228

214229
intg.reconcile_account(
@@ -219,7 +234,7 @@ def test_terraform_init_integration_reconcile_account_when_tags_mismatch(
219234
state_template="{{bucket_name}}",
220235
cloudformation_template="cloudformation_template",
221236
cloudformation_import_template="cloudformation_import_template",
222-
tags={"env": "test"},
237+
default_tags={"env": "test"},
223238
)
224239

225240
aws_api.cloudformation.get_stack.assert_called_once_with(
@@ -229,7 +244,12 @@ def test_terraform_init_integration_reconcile_account_when_tags_mismatch(
229244
stack_name="existing-bucket",
230245
template_body="cloudformation_template",
231246
parameters={"BucketName": "existing-bucket"},
232-
tags={"env": "test"},
247+
tags={
248+
"account_key": "account_value",
249+
"common_key": "final_common_value",
250+
"env": "test",
251+
"payer_key": "payer_value",
252+
},
233253
)
234254
aws_api.cloudformation.create_stack.assert_not_called()
235255
aws_api.cloudformation.get_template.assert_not_called()
@@ -245,7 +265,12 @@ def test_terraform_init_integration_reconcile_account_when_tags_mismatch_dry_run
245265
account = next(a for a in aws_accounts if a.name == "terraform-state-already-set")
246266
aws_api.cloudformation.get_stack.return_value = {
247267
"StackName": "terraform-terraform-state-already-set",
248-
"Tags": [{"Key": "env", "Value": "test-old"}],
268+
"Tags": [
269+
{"Key": "account_key", "Value": "account_value"},
270+
{"Key": "common_key", "Value": "final_common_value"},
271+
{"Key": "env", "Value": "test-old"},
272+
{"Key": "payer_key", "Value": "payer_value"},
273+
],
249274
}
250275

251276
intg.reconcile_account(
@@ -256,7 +281,7 @@ def test_terraform_init_integration_reconcile_account_when_tags_mismatch_dry_run
256281
state_template="{{bucket_name}}",
257282
cloudformation_template="cloudformation_template",
258283
cloudformation_import_template="cloudformation_import_template",
259-
tags={"env": "test"},
284+
default_tags={"env": "test"},
260285
)
261286

262287
aws_api.cloudformation.get_stack.assert_called_once_with(
@@ -277,7 +302,12 @@ def test_terraform_init_integration_reconcile_account_when_template_body_mismatc
277302
account = next(a for a in aws_accounts if a.name == "terraform-state-already-set")
278303
aws_api.cloudformation.get_stack.return_value = {
279304
"StackName": "terraform-terraform-state-already-set",
280-
"Tags": [{"Key": "env", "Value": "test"}],
305+
"Tags": [
306+
{"Key": "account_key", "Value": "account_value"},
307+
{"Key": "common_key", "Value": "final_common_value"},
308+
{"Key": "env", "Value": "test"},
309+
{"Key": "payer_key", "Value": "payer_value"},
310+
],
281311
}
282312
aws_api.cloudformation.get_template_body.return_value = "old_template_body"
283313

@@ -289,7 +319,7 @@ def test_terraform_init_integration_reconcile_account_when_template_body_mismatc
289319
state_template="{{bucket_name}}",
290320
cloudformation_template="cloudformation_template",
291321
cloudformation_import_template="cloudformation_import_template",
292-
tags={"env": "test"},
322+
default_tags={"env": "test"},
293323
)
294324

295325
aws_api.cloudformation.get_stack.assert_called_once_with(
@@ -302,7 +332,12 @@ def test_terraform_init_integration_reconcile_account_when_template_body_mismatc
302332
stack_name="existing-bucket",
303333
template_body="cloudformation_template",
304334
parameters={"BucketName": "existing-bucket"},
305-
tags={"env": "test"},
335+
tags={
336+
"account_key": "account_value",
337+
"common_key": "final_common_value",
338+
"env": "test",
339+
"payer_key": "payer_value",
340+
},
306341
)
307342
aws_api.cloudformation.create_stack.assert_not_called()
308343
merge_request_manager.create_merge_request.assert_not_called()
@@ -317,7 +352,12 @@ def test_terraform_init_integration_reconcile_account_when_template_body_mismatc
317352
account = next(a for a in aws_accounts if a.name == "terraform-state-already-set")
318353
aws_api.cloudformation.get_stack.return_value = {
319354
"StackName": "terraform-terraform-state-already-set",
320-
"Tags": [{"Key": "env", "Value": "test"}],
355+
"Tags": [
356+
{"Key": "account_key", "Value": "account_value"},
357+
{"Key": "env", "Value": "test"},
358+
{"Key": "common_key", "Value": "final_common_value"},
359+
{"Key": "payer_key", "Value": "payer_value"},
360+
],
321361
}
322362
aws_api.cloudformation.get_template_body.return_value = "old_template_body"
323363

@@ -329,7 +369,7 @@ def test_terraform_init_integration_reconcile_account_when_template_body_mismatc
329369
state_template="{{bucket_name}}",
330370
cloudformation_template="cloudformation_template",
331371
cloudformation_import_template="cloudformation_import_template",
332-
tags={"env": "test"},
372+
default_tags={"env": "test"},
333373
)
334374

335375
aws_api.cloudformation.get_stack.assert_called_once_with(
@@ -352,7 +392,12 @@ def test_terraform_init_integration_reconcile_account_when_no_changes(
352392
account = next(a for a in aws_accounts if a.name == "terraform-state-already-set")
353393
aws_api.cloudformation.get_stack.return_value = {
354394
"StackName": "terraform-terraform-state-already-set",
355-
"Tags": [{"Key": "env", "Value": "test"}],
395+
"Tags": [
396+
{"Key": "account_key", "Value": "account_value"},
397+
{"Key": "common_key", "Value": "final_common_value"},
398+
{"Key": "env", "Value": "test"},
399+
{"Key": "payer_key", "Value": "payer_value"},
400+
],
356401
}
357402
aws_api.cloudformation.get_template_body.return_value = "cloudformation_template"
358403

@@ -364,7 +409,7 @@ def test_terraform_init_integration_reconcile_account_when_no_changes(
364409
state_template="{{bucket_name}}",
365410
cloudformation_template="cloudformation_template",
366411
cloudformation_import_template="cloudformation_import_template",
367-
tags={"env": "test"},
412+
default_tags={"env": "test"},
368413
)
369414

370415
aws_api.cloudformation.get_stack.assert_called_once_with(

0 commit comments

Comments
 (0)