1
1
import os
2
+ from collections .abc import Callable
2
3
3
4
import pytest
4
5
from localstack_snapshot .snapshots .transformer import SortingTransformer
5
- from tests .aws .services .cloudformation .conftest import skip_if_v2_provider
6
+ from tests .aws .services .cloudformation .conftest import skip_if_v1_provider
6
7
8
+ from localstack .aws .api .cloudformation import Parameter
7
9
from localstack .testing .pytest import markers
8
10
from localstack .utils .files import load_file
9
11
from localstack .utils .strings import short_uid
10
12
11
13
12
14
class TestCdkInit :
13
- @pytest .mark .parametrize ("bootstrap_version" , ["10" , "11" , "12" ])
15
+ @pytest .mark .parametrize (
16
+ "bootstrap_version,parameters" ,
17
+ [
18
+ ("10" , {"FileAssetsBucketName" : f"cdk-bootstrap-{ short_uid ()} " }),
19
+ ("11" , {"FileAssetsBucketName" : f"cdk-bootstrap-{ short_uid ()} " }),
20
+ ("12" , {"FileAssetsBucketName" : f"cdk-bootstrap-{ short_uid ()} " }),
21
+ (
22
+ "28" ,
23
+ {
24
+ "CloudFormationExecutionPolicies" : "" ,
25
+ "FileAssetsBucketKmsKeyId" : "AWS_MANAGED_KEY" ,
26
+ "PublicAccessBlockConfiguration" : "true" ,
27
+ "TrustedAccounts" : "" ,
28
+ "TrustedAccountsForLookup" : "" ,
29
+ },
30
+ ),
31
+ ],
32
+ ids = ["10" , "11" , "12" , "28" ],
33
+ )
14
34
@markers .aws .validated
15
- def test_cdk_bootstrap (self , deploy_cfn_template , bootstrap_version , aws_client ):
35
+ def test_cdk_bootstrap (self , deploy_cfn_template , aws_client , bootstrap_version , parameters ):
16
36
deploy_cfn_template (
17
37
template_path = os .path .join (
18
38
os .path .dirname (__file__ ),
19
39
f"../../../templates/cdk_bootstrap_v{ bootstrap_version } .yaml" ,
20
40
),
21
- parameters = { "FileAssetsBucketName" : f"cdk-bootstrap- { short_uid () } " } ,
41
+ parameters = parameters ,
22
42
)
23
43
init_stack_result = deploy_cfn_template (
24
44
template_path = os .path .join (
@@ -32,61 +52,136 @@ def test_cdk_bootstrap(self, deploy_cfn_template, bootstrap_version, aws_client)
32
52
assert len (stack_res ["StackResources" ]) == 1
33
53
assert stack_res ["StackResources" ][0 ]["LogicalResourceId" ] == "CDKMetadata"
34
54
35
- @skip_if_v2_provider (reason = "CFNV2:Provider" )
36
55
@markers .aws .validated
37
- def test_cdk_bootstrap_redeploy (self , aws_client , cleanup_stacks , cleanup_changesets , cleanups ):
56
+ @pytest .mark .parametrize (
57
+ "template,parameters_fn" ,
58
+ [
59
+ pytest .param (
60
+ "cdk_bootstrap.yml" ,
61
+ lambda qualifier : [
62
+ {
63
+ "ParameterKey" : "BootstrapVariant" ,
64
+ "ParameterValue" : "AWS CDK: Default Resources" ,
65
+ },
66
+ {"ParameterKey" : "TrustedAccounts" , "ParameterValue" : "" },
67
+ {"ParameterKey" : "TrustedAccountsForLookup" , "ParameterValue" : "" },
68
+ {"ParameterKey" : "CloudFormationExecutionPolicies" , "ParameterValue" : "" },
69
+ {
70
+ "ParameterKey" : "FileAssetsBucketKmsKeyId" ,
71
+ "ParameterValue" : "AWS_MANAGED_KEY" ,
72
+ },
73
+ {
74
+ "ParameterKey" : "PublicAccessBlockConfiguration" ,
75
+ "ParameterValue" : "true" ,
76
+ },
77
+ {"ParameterKey" : "Qualifier" , "ParameterValue" : qualifier },
78
+ {
79
+ "ParameterKey" : "UseExamplePermissionsBoundary" ,
80
+ "ParameterValue" : "false" ,
81
+ },
82
+ ],
83
+ id = "v20" ,
84
+ ),
85
+ pytest .param (
86
+ "cdk_bootstrap_v28.yaml" ,
87
+ lambda qualifier : [
88
+ {"ParameterKey" : "CloudFormationExecutionPolicies" , "ParameterValue" : "" },
89
+ {
90
+ "ParameterKey" : "FileAssetsBucketKmsKeyId" ,
91
+ "ParameterValue" : "AWS_MANAGED_KEY" ,
92
+ },
93
+ {
94
+ "ParameterKey" : "PublicAccessBlockConfiguration" ,
95
+ "ParameterValue" : "true" ,
96
+ },
97
+ {"ParameterKey" : "Qualifier" , "ParameterValue" : qualifier },
98
+ {"ParameterKey" : "TrustedAccounts" , "ParameterValue" : "" },
99
+ {"ParameterKey" : "TrustedAccountsForLookup" , "ParameterValue" : "" },
100
+ ],
101
+ id = "v28" ,
102
+ ),
103
+ ],
104
+ )
105
+ @markers .snapshot .skip_snapshot_verify (
106
+ paths = [
107
+ # CFNV2:Provider
108
+ "$..Description" ,
109
+ # Wrong format, they are our internal parameter format
110
+ "$..Parameters" ,
111
+ # from the list of changes
112
+ "$..Changes..Details" ,
113
+ "$..Changes..LogicalResourceId" ,
114
+ "$..Changes..ResourceType" ,
115
+ "$..Changes..Scope" ,
116
+ # provider
117
+ "$..IncludeNestedStacks" ,
118
+ "$..NotificationARNs" ,
119
+ # CFNV2:Describe not supported yet
120
+ "$..Outputs..ExportName" ,
121
+ # mismatch between amazonaws.com and localhost.localstack.cloud
122
+ "$..Outputs..OutputValue" ,
123
+ ]
124
+ )
125
+ @skip_if_v1_provider (reason = "Changes array not in parity" )
126
+ def test_cdk_bootstrap_redeploy (
127
+ self ,
128
+ aws_client ,
129
+ cleanup_stacks ,
130
+ cleanup_changesets ,
131
+ cleanups ,
132
+ snapshot ,
133
+ template ,
134
+ parameters_fn : Callable [[str ], list [Parameter ]],
135
+ ):
38
136
"""Test that simulates a sequence of commands executed by CDK when running 'cdk bootstrap' twice"""
137
+ snapshot .add_transformer (snapshot .transform .cloudformation_api ())
138
+ snapshot .add_transformer (SortingTransformer ("Parameters" , lambda p : p ["ParameterKey" ]))
139
+ snapshot .add_transformer (SortingTransformer ("Outputs" , lambda p : p ["OutputKey" ]))
39
140
40
141
stack_name = f"CDKToolkit-{ short_uid ()} "
41
142
change_set_name = f"cdk-deploy-change-set-{ short_uid ()} "
143
+ qualifier = short_uid ()
144
+ snapshot .add_transformer (snapshot .transform .regex (qualifier , "<qualifier>" ))
42
145
43
146
def clean_resources ():
44
147
cleanup_stacks ([stack_name ])
45
148
cleanup_changesets ([change_set_name ])
46
149
47
150
cleanups .append (clean_resources )
48
151
49
- template_body = load_file (
50
- os .path .join (os .path .dirname (__file__ ), "../../../templates/cdk_bootstrap.yml " )
152
+ template_path = os . path . realpath (
153
+ os .path .join (os .path .dirname (__file__ ), f "../../../templates/{ template } " )
51
154
)
155
+ template_body = load_file (template_path )
156
+ if template_body is None :
157
+ raise RuntimeError (f"Template { template_path } not loaded" )
158
+
52
159
aws_client .cloudformation .create_change_set (
53
160
StackName = stack_name ,
54
161
ChangeSetName = change_set_name ,
55
162
TemplateBody = template_body ,
56
163
ChangeSetType = "CREATE" ,
57
164
Capabilities = ["CAPABILITY_IAM" , "CAPABILITY_NAMED_IAM" , "CAPABILITY_AUTO_EXPAND" ],
58
165
Description = "CDK Changeset for execution 731ed7da-8b2d-49c6-bca3-4698b6875954" ,
59
- Parameters = [
60
- {
61
- "ParameterKey" : "BootstrapVariant" ,
62
- "ParameterValue" : "AWS CDK: Default Resources" ,
63
- },
64
- {"ParameterKey" : "TrustedAccounts" , "ParameterValue" : "" },
65
- {"ParameterKey" : "TrustedAccountsForLookup" , "ParameterValue" : "" },
66
- {"ParameterKey" : "CloudFormationExecutionPolicies" , "ParameterValue" : "" },
67
- {"ParameterKey" : "FileAssetsBucketKmsKeyId" , "ParameterValue" : "AWS_MANAGED_KEY" },
68
- {"ParameterKey" : "PublicAccessBlockConfiguration" , "ParameterValue" : "true" },
69
- {"ParameterKey" : "Qualifier" , "ParameterValue" : "hnb659fds" },
70
- {"ParameterKey" : "UseExamplePermissionsBoundary" , "ParameterValue" : "false" },
71
- ],
166
+ Parameters = parameters_fn (qualifier ),
72
167
)
73
- aws_client .cloudformation .describe_change_set (
168
+ aws_client .cloudformation .get_waiter ( "change_set_create_complete" ). wait (
74
169
StackName = stack_name , ChangeSetName = change_set_name
75
170
)
76
-
77
- aws_client .cloudformation .get_waiter ("change_set_create_complete" ).wait (
171
+ describe_change_set = aws_client .cloudformation .describe_change_set (
78
172
StackName = stack_name , ChangeSetName = change_set_name
79
173
)
174
+ snapshot .match ("describe-change-set" , describe_change_set )
80
175
81
176
aws_client .cloudformation .execute_change_set (
82
177
StackName = stack_name , ChangeSetName = change_set_name
83
178
)
84
179
85
180
aws_client .cloudformation .get_waiter ("stack_create_complete" ).wait (StackName = stack_name )
86
- aws_client .cloudformation .describe_stacks (StackName = stack_name )
181
+ stacks = aws_client .cloudformation .describe_stacks (StackName = stack_name )["Stacks" ][0 ]
182
+ snapshot .match ("describe-stacks" , stacks )
87
183
88
- # When CDK toolstrap command is executed again it just confirms that the template is the same
89
- aws_client .sts .get_caller_identity ()
184
+ # When CDK bootstrap command is executed again it just confirms that the template is the same
90
185
aws_client .cloudformation .get_template (StackName = stack_name , TemplateStage = "Original" )
91
186
92
187
# TODO: create scenario where the template is different to catch cdk behavior
0 commit comments