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:
parent
0912abe5f6
commit
c8c6b0bf58
@ -467,6 +467,28 @@ class CloudFormationBackend(BaseBackend):
|
|||||||
self.exports = OrderedDict()
|
self.exports = OrderedDict()
|
||||||
self.change_sets = 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(
|
def create_stack_set(
|
||||||
self,
|
self,
|
||||||
name,
|
name,
|
||||||
@ -494,6 +516,8 @@ class CloudFormationBackend(BaseBackend):
|
|||||||
|
|
||||||
def get_stack_set(self, name):
|
def get_stack_set(self, name):
|
||||||
stacksets = self.stacksets.keys()
|
stacksets = self.stacksets.keys()
|
||||||
|
if name in stacksets:
|
||||||
|
return self.stacksets[name]
|
||||||
for stackset in stacksets:
|
for stackset in stacksets:
|
||||||
if self.stacksets[stackset].name == name:
|
if self.stacksets[stackset].name == name:
|
||||||
return self.stacksets[stackset]
|
return self.stacksets[stackset]
|
||||||
@ -501,6 +525,8 @@ class CloudFormationBackend(BaseBackend):
|
|||||||
|
|
||||||
def delete_stack_set(self, name):
|
def delete_stack_set(self, name):
|
||||||
stacksets = self.stacksets.keys()
|
stacksets = self.stacksets.keys()
|
||||||
|
if name in stacksets:
|
||||||
|
self.stacksets[name].delete()
|
||||||
for stackset in stacksets:
|
for stackset in stacksets:
|
||||||
if self.stacksets[stackset].name == name:
|
if self.stacksets[stackset].name == name:
|
||||||
self.stacksets[stackset].delete()
|
self.stacksets[stackset].delete()
|
||||||
@ -532,10 +558,13 @@ class CloudFormationBackend(BaseBackend):
|
|||||||
operation_id=None,
|
operation_id=None,
|
||||||
):
|
):
|
||||||
stackset = self.get_stack_set(stackset_name)
|
stackset = self.get_stack_set(stackset_name)
|
||||||
|
resolved_parameters = self._resolve_update_parameters(
|
||||||
|
instance=stackset, incoming_params=parameters
|
||||||
|
)
|
||||||
update = stackset.update(
|
update = stackset.update(
|
||||||
template=template,
|
template=template,
|
||||||
description=description,
|
description=description,
|
||||||
parameters=parameters,
|
parameters=resolved_parameters,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
admin_role=admin_role,
|
admin_role=admin_role,
|
||||||
execution_role=execution_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):
|
def update_stack(self, name, template, role_arn=None, parameters=None, tags=None):
|
||||||
stack = self.get_stack(name)
|
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
|
return stack
|
||||||
|
|
||||||
def list_stack_resources(self, stack_name_or_id):
|
def list_stack_resources(self, stack_name_or_id):
|
||||||
|
@ -315,24 +315,6 @@ class CloudFormationResponse(BaseResponse):
|
|||||||
stack_body = self._get_stack_from_s3_url(template_url)
|
stack_body = self._get_stack_from_s3_url(template_url)
|
||||||
|
|
||||||
incoming_params = self._get_list_prefix("Parameters.member")
|
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
|
# 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
|
# 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.
|
# 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,
|
name=stack_name,
|
||||||
template=stack_body,
|
template=stack_body,
|
||||||
role_arn=role_arn,
|
role_arn=role_arn,
|
||||||
parameters=parameters,
|
parameters=incoming_params,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
)
|
)
|
||||||
if self.request_json:
|
if self.request_json:
|
||||||
@ -560,17 +542,12 @@ class CloudFormationResponse(BaseResponse):
|
|||||||
for item in self._get_list_prefix("Tags.member")
|
for item in self._get_list_prefix("Tags.member")
|
||||||
)
|
)
|
||||||
parameters_list = self._get_list_prefix("Parameters.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(
|
operation = self.cloudformation_backend.update_stack_set(
|
||||||
stackset_name=stackset_name,
|
stackset_name=stackset_name,
|
||||||
template=template_body,
|
template=template_body,
|
||||||
description=description,
|
description=description,
|
||||||
parameters=parameters,
|
parameters=parameters_list,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
admin_role=admin_role,
|
admin_role=admin_role,
|
||||||
execution_role=execution_role,
|
execution_role=execution_role,
|
||||||
|
@ -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
|
@mock_cloudformation
|
||||||
def test_boto3_list_stack_set_operations():
|
def test_boto3_list_stack_set_operations():
|
||||||
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
@ -588,7 +625,7 @@ def test_boto3_bad_list_stack_resources():
|
|||||||
|
|
||||||
|
|
||||||
@mock_cloudformation
|
@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 = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
cf_conn.create_stack_set(
|
cf_conn.create_stack_set(
|
||||||
StackSetName="test_stack_set", TemplateBody=dummy_template_json
|
StackSetName="test_stack_set", TemplateBody=dummy_template_json
|
||||||
@ -600,6 +637,20 @@ def test_boto3_delete_stack_set():
|
|||||||
].should.equal("DELETED")
|
].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
|
@mock_cloudformation
|
||||||
def test_boto3_create_stack_set():
|
def test_boto3_create_stack_set():
|
||||||
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
@ -680,6 +731,19 @@ def test_boto3_describe_stack_set_params():
|
|||||||
].should.equal(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
|
@mock_cloudformation
|
||||||
def test_boto3_create_stack():
|
def test_boto3_create_stack():
|
||||||
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user