Fix stackset describe/delete. Fix stackset update. (#3713)

* Fix stack set fetching and deleting.

* Also fix stackset update operation to accept previous values.

* Fix linting.

* Rename aliased test.
This commit is contained in:
Jakub Musko 2021-02-21 10:47:10 +01:00 committed by GitHub
parent 0912abe5f6
commit c8c6b0bf58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 29 deletions

View File

@ -467,6 +467,28 @@ class CloudFormationBackend(BaseBackend):
self.exports = OrderedDict()
self.change_sets = OrderedDict()
def _resolve_update_parameters(self, instance, incoming_params):
parameters = dict(
[
(parameter["parameter_key"], parameter["parameter_value"])
for parameter in incoming_params
if "parameter_value" in parameter
]
)
previous = dict(
[
(
parameter["parameter_key"],
instance.parameters[parameter["parameter_key"]],
)
for parameter in incoming_params
if "use_previous_value" in parameter
]
)
parameters.update(previous)
return parameters
def create_stack_set(
self,
name,
@ -494,6 +516,8 @@ class CloudFormationBackend(BaseBackend):
def get_stack_set(self, name):
stacksets = self.stacksets.keys()
if name in stacksets:
return self.stacksets[name]
for stackset in stacksets:
if self.stacksets[stackset].name == name:
return self.stacksets[stackset]
@ -501,6 +525,8 @@ class CloudFormationBackend(BaseBackend):
def delete_stack_set(self, name):
stacksets = self.stacksets.keys()
if name in stacksets:
self.stacksets[name].delete()
for stackset in stacksets:
if self.stacksets[stackset].name == name:
self.stacksets[stackset].delete()
@ -532,10 +558,13 @@ class CloudFormationBackend(BaseBackend):
operation_id=None,
):
stackset = self.get_stack_set(stackset_name)
resolved_parameters = self._resolve_update_parameters(
instance=stackset, incoming_params=parameters
)
update = stackset.update(
template=template,
description=description,
parameters=parameters,
parameters=resolved_parameters,
tags=tags,
admin_role=admin_role,
execution_role=execution_role,
@ -711,7 +740,10 @@ class CloudFormationBackend(BaseBackend):
def update_stack(self, name, template, role_arn=None, parameters=None, tags=None):
stack = self.get_stack(name)
stack.update(template, role_arn, parameters=parameters, tags=tags)
resolved_parameters = self._resolve_update_parameters(
instance=stack, incoming_params=parameters
)
stack.update(template, role_arn, parameters=resolved_parameters, tags=tags)
return stack
def list_stack_resources(self, stack_name_or_id):

View File

@ -315,24 +315,6 @@ class CloudFormationResponse(BaseResponse):
stack_body = self._get_stack_from_s3_url(template_url)
incoming_params = self._get_list_prefix("Parameters.member")
parameters = dict(
[
(parameter["parameter_key"], parameter["parameter_value"])
for parameter in incoming_params
if "parameter_value" in parameter
]
)
previous = dict(
[
(
parameter["parameter_key"],
stack.parameters[parameter["parameter_key"]],
)
for parameter in incoming_params
if "use_previous_value" in parameter
]
)
parameters.update(previous)
# boto3 is supposed to let you clear the tags by passing an empty value, but the request body doesn't
# end up containing anything we can use to differentiate between passing an empty value versus not
# passing anything. so until that changes, moto won't be able to clear tags, only update them.
@ -357,7 +339,7 @@ class CloudFormationResponse(BaseResponse):
name=stack_name,
template=stack_body,
role_arn=role_arn,
parameters=parameters,
parameters=incoming_params,
tags=tags,
)
if self.request_json:
@ -560,17 +542,12 @@ class CloudFormationResponse(BaseResponse):
for item in self._get_list_prefix("Tags.member")
)
parameters_list = self._get_list_prefix("Parameters.member")
parameters = dict(
[
(parameter["parameter_key"], parameter["parameter_value"])
for parameter in parameters_list
]
)
operation = self.cloudformation_backend.update_stack_set(
stackset_name=stackset_name,
template=template_body,
description=description,
parameters=parameters,
parameters=parameters_list,
tags=tags,
admin_role=admin_role,
execution_role=execution_role,

View File

@ -558,6 +558,43 @@ def test_update_stack_set():
)
@mock_cloudformation
def test_update_stack_set_with_previous_value():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
param = [
{"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"},
{"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"},
]
param_overrides = [
{"ParameterKey": "TagDescription", "ParameterValue": "OverrideValue"},
{"ParameterKey": "TagName", "UsePreviousValue": True},
]
cf_conn.create_stack_set(
StackSetName="test_stack_set",
TemplateBody=dummy_template_yaml_with_ref,
Parameters=param,
)
cf_conn.update_stack_set(
StackSetName="test_stack_set",
TemplateBody=dummy_template_yaml_with_ref,
Parameters=param_overrides,
)
stackset = cf_conn.describe_stack_set(StackSetName="test_stack_set")
stackset["StackSet"]["Parameters"][0]["ParameterValue"].should.equal(
param_overrides[0]["ParameterValue"]
)
stackset["StackSet"]["Parameters"][1]["ParameterValue"].should.equal(
param[1]["ParameterValue"]
)
stackset["StackSet"]["Parameters"][0]["ParameterKey"].should.equal(
param_overrides[0]["ParameterKey"]
)
stackset["StackSet"]["Parameters"][1]["ParameterKey"].should.equal(
param_overrides[1]["ParameterKey"]
)
@mock_cloudformation
def test_boto3_list_stack_set_operations():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
@ -588,7 +625,7 @@ def test_boto3_bad_list_stack_resources():
@mock_cloudformation
def test_boto3_delete_stack_set():
def test_boto3_delete_stack_set_by_name():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
cf_conn.create_stack_set(
StackSetName="test_stack_set", TemplateBody=dummy_template_json
@ -600,6 +637,20 @@ def test_boto3_delete_stack_set():
].should.equal("DELETED")
@mock_cloudformation
def test_boto3_delete_stack_set_by_id():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
response = cf_conn.create_stack_set(
StackSetName="test_stack_set", TemplateBody=dummy_template_json
)
stack_set_id = response["StackSetId"]
cf_conn.delete_stack_set(StackSetName=stack_set_id)
cf_conn.describe_stack_set(StackSetName="test_stack_set")["StackSet"][
"Status"
].should.equal("DELETED")
@mock_cloudformation
def test_boto3_create_stack_set():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
@ -680,6 +731,19 @@ def test_boto3_describe_stack_set_params():
].should.equal(params)
@mock_cloudformation
def test_boto3_describe_stack_set_by_id():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
response = cf_conn.create_stack_set(
StackSetName="test_stack", TemplateBody=dummy_template_json,
)
stack_set_id = response["StackSetId"]
cf_conn.describe_stack_set(StackSetName=stack_set_id)["StackSet"][
"TemplateBody"
].should.equal(dummy_template_json)
@mock_cloudformation
def test_boto3_create_stack():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")