from __future__ import unicode_literals
import json
import yaml
from urllib.parse import urlparse
from moto.core.responses import BaseResponse
from moto.core.utils import amzn_request_id
from moto.s3 import s3_backend
from moto.core import ACCOUNT_ID
from .models import cloudformation_backends
from .exceptions import ValidationError
from .utils import yaml_tag_constructor
def get_template_summary_response_from_template(template_body):
def get_resource_types(template_dict):
resources = {}
for key, value in template_dict.items():
if key == "Resources":
resources = value
resource_types = []
for key, value in resources.items():
resource_types.append(value["Type"])
return resource_types
yaml.add_multi_constructor("", yaml_tag_constructor)
try:
template_dict = yaml.load(template_body, Loader=yaml.Loader)
except (yaml.parser.ParserError, yaml.scanner.ScannerError):
template_dict = json.loads(template_body)
resources_types = get_resource_types(template_dict)
template_dict["resourceTypes"] = resources_types
return template_dict
class CloudFormationResponse(BaseResponse):
@property
def cloudformation_backend(self):
return cloudformation_backends[self.region]
def _get_stack_from_s3_url(self, template_url):
template_url_parts = urlparse(template_url)
if "localhost" in template_url:
bucket_name, key_name = template_url_parts.path.lstrip("/").split("/", 1)
else:
if template_url_parts.netloc.endswith(
"amazonaws.com"
) and template_url_parts.netloc.startswith("s3"):
# Handle when S3 url uses amazon url with bucket in path
# Also handles getting region as technically s3 is region'd
# region = template_url.netloc.split('.')[1]
bucket_name, key_name = template_url_parts.path.lstrip("/").split(
"/", 1
)
else:
bucket_name = template_url_parts.netloc.split(".")[0]
key_name = template_url_parts.path.lstrip("/")
key = s3_backend.get_object(bucket_name, key_name)
return key.value.decode("utf-8")
def create_stack(self):
stack_name = self._get_param("StackName")
stack_body = self._get_param("TemplateBody")
template_url = self._get_param("TemplateURL")
role_arn = self._get_param("RoleARN")
parameters_list = self._get_list_prefix("Parameters.member")
tags = dict(
(item["key"], item["value"])
for item in self._get_list_prefix("Tags.member")
)
if self.stack_name_exists(new_stack_name=stack_name):
template = self.response_template(
CREATE_STACK_NAME_EXISTS_RESPONSE_TEMPLATE
)
return 400, {"status": 400}, template.render(name=stack_name)
# Hack dict-comprehension
parameters = dict(
[
(parameter["parameter_key"], parameter["parameter_value"])
for parameter in parameters_list
]
)
if template_url:
stack_body = self._get_stack_from_s3_url(template_url)
stack_notification_arns = self._get_multi_param("NotificationARNs.member")
stack = self.cloudformation_backend.create_stack(
name=stack_name,
template=stack_body,
parameters=parameters,
region_name=self.region,
notification_arns=stack_notification_arns,
tags=tags,
role_arn=role_arn,
)
if self.request_json:
return json.dumps(
{
"CreateStackResponse": {
"CreateStackResult": {"StackId": stack.stack_id}
}
}
)
else:
template = self.response_template(CREATE_STACK_RESPONSE_TEMPLATE)
return template.render(stack=stack)
def stack_name_exists(self, new_stack_name):
for stack in self.cloudformation_backend.stacks.values():
if stack.name == new_stack_name:
return True
return False
@amzn_request_id
def create_change_set(self):
stack_name = self._get_param("StackName")
change_set_name = self._get_param("ChangeSetName")
stack_body = self._get_param("TemplateBody")
template_url = self._get_param("TemplateURL")
description = self._get_param("Description")
role_arn = self._get_param("RoleARN")
update_or_create = self._get_param("ChangeSetType", "CREATE")
parameters_list = self._get_list_prefix("Parameters.member")
tags = dict(
(item["key"], item["value"])
for item in self._get_list_prefix("Tags.member")
)
parameters = {
param["parameter_key"]: param["parameter_value"]
for param in parameters_list
}
if template_url:
stack_body = self._get_stack_from_s3_url(template_url)
stack_notification_arns = self._get_multi_param("NotificationARNs.member")
change_set_id, stack_id = self.cloudformation_backend.create_change_set(
stack_name=stack_name,
change_set_name=change_set_name,
template=stack_body,
parameters=parameters,
description=description,
region_name=self.region,
notification_arns=stack_notification_arns,
tags=tags,
role_arn=role_arn,
change_set_type=update_or_create,
)
if self.request_json:
return json.dumps(
{
"CreateChangeSetResponse": {
"CreateChangeSetResult": {
"Id": change_set_id,
"StackId": stack_id,
}
}
}
)
else:
template = self.response_template(CREATE_CHANGE_SET_RESPONSE_TEMPLATE)
return template.render(stack_id=stack_id, change_set_id=change_set_id)
def delete_change_set(self):
stack_name = self._get_param("StackName")
change_set_name = self._get_param("ChangeSetName")
self.cloudformation_backend.delete_change_set(
change_set_name=change_set_name, stack_name=stack_name
)
if self.request_json:
return json.dumps(
{"DeleteChangeSetResponse": {"DeleteChangeSetResult": {}}}
)
else:
template = self.response_template(DELETE_CHANGE_SET_RESPONSE_TEMPLATE)
return template.render()
def describe_change_set(self):
stack_name = self._get_param("StackName")
change_set_name = self._get_param("ChangeSetName")
change_set = self.cloudformation_backend.describe_change_set(
change_set_name=change_set_name, stack_name=stack_name
)
template = self.response_template(DESCRIBE_CHANGE_SET_RESPONSE_TEMPLATE)
return template.render(change_set=change_set)
@amzn_request_id
def execute_change_set(self):
stack_name = self._get_param("StackName")
change_set_name = self._get_param("ChangeSetName")
self.cloudformation_backend.execute_change_set(
stack_name=stack_name, change_set_name=change_set_name
)
if self.request_json:
return json.dumps(
{"ExecuteChangeSetResponse": {"ExecuteChangeSetResult": {}}}
)
else:
template = self.response_template(EXECUTE_CHANGE_SET_RESPONSE_TEMPLATE)
return template.render()
def describe_stacks(self):
stack_name_or_id = None
if self._get_param("StackName"):
stack_name_or_id = self.querystring.get("StackName")[0]
token = self._get_param("NextToken")
stacks = self.cloudformation_backend.describe_stacks(stack_name_or_id)
stack_ids = [stack.stack_id for stack in stacks]
if token:
start = stack_ids.index(token) + 1
else:
start = 0
max_results = 50 # using this to mske testing of paginated stacks more convenient than default 1 MB
stacks_resp = stacks[start : start + max_results]
next_token = None
if len(stacks) > (start + max_results):
next_token = stacks_resp[-1].stack_id
template = self.response_template(DESCRIBE_STACKS_TEMPLATE)
return template.render(stacks=stacks_resp, next_token=next_token)
def describe_stack_resource(self):
stack_name = self._get_param("StackName")
stack = self.cloudformation_backend.get_stack(stack_name)
logical_resource_id = self._get_param("LogicalResourceId")
resource = None
for stack_resource in stack.stack_resources:
if stack_resource.logical_resource_id == logical_resource_id:
resource = stack_resource
break
if not resource:
message = "Resource {0} does not exist for stack {1}".format(
logical_resource_id, stack_name
)
raise ValidationError(stack_name, message)
template = self.response_template(DESCRIBE_STACK_RESOURCE_RESPONSE_TEMPLATE)
return template.render(stack=stack, resource=resource)
def describe_stack_resources(self):
stack_name = self._get_param("StackName")
stack = self.cloudformation_backend.get_stack(stack_name)
template = self.response_template(DESCRIBE_STACK_RESOURCES_RESPONSE)
return template.render(stack=stack)
def describe_stack_events(self):
stack_name = self._get_param("StackName")
stack = self.cloudformation_backend.get_stack(stack_name)
template = self.response_template(DESCRIBE_STACK_EVENTS_RESPONSE)
return template.render(stack=stack)
def list_change_sets(self):
change_sets = self.cloudformation_backend.list_change_sets()
template = self.response_template(LIST_CHANGE_SETS_RESPONSE)
return template.render(change_sets=change_sets)
def list_stacks(self):
status_filter = self._get_multi_param("StackStatusFilter.member")
stacks = self.cloudformation_backend.list_stacks(status_filter)
template = self.response_template(LIST_STACKS_RESPONSE)
return template.render(stacks=stacks)
def list_stack_resources(self):
stack_name_or_id = self._get_param("StackName")
resources = self.cloudformation_backend.list_stack_resources(stack_name_or_id)
template = self.response_template(LIST_STACKS_RESOURCES_RESPONSE)
return template.render(resources=resources)
def get_template(self):
name_or_stack_id = self.querystring.get("StackName")[0]
stack = self.cloudformation_backend.get_stack(name_or_stack_id)
if self.request_json:
return json.dumps(
{
"GetTemplateResponse": {
"GetTemplateResult": {
"TemplateBody": stack.template,
"ResponseMetadata": {
"RequestId": "2d06e36c-ac1d-11e0-a958-f9382b6eb86bEXAMPLE"
},
}
}
}
)
else:
template = self.response_template(GET_TEMPLATE_RESPONSE_TEMPLATE)
return template.render(stack=stack)
def get_template_summary(self):
stack_name = self._get_param("StackName")
template_url = self._get_param("TemplateURL")
stack_body = self._get_param("TemplateBody")
if stack_name:
stack_body = self.cloudformation_backend.get_stack(stack_name).template
elif template_url:
stack_body = self._get_stack_from_s3_url(template_url)
template_summary = get_template_summary_response_from_template(stack_body)
template = self.response_template(GET_TEMPLATE_SUMMARY_TEMPLATE)
return template.render(template_summary=template_summary)
def update_stack(self):
stack_name = self._get_param("StackName")
role_arn = self._get_param("RoleARN")
template_url = self._get_param("TemplateURL")
stack_body = self._get_param("TemplateBody")
stack = self.cloudformation_backend.get_stack(stack_name)
if self._get_param("UsePreviousTemplate") == "true":
stack_body = stack.template
elif not stack_body and template_url:
stack_body = self._get_stack_from_s3_url(template_url)
incoming_params = self._get_list_prefix("Parameters.member")
# 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.
tags = dict(
(item["key"], item["value"])
for item in self._get_list_prefix("Tags.member")
)
# so that if we don't pass the parameter, we don't clear all the tags accidentally
if not tags:
tags = None
stack = self.cloudformation_backend.get_stack(stack_name)
if stack.status == "ROLLBACK_COMPLETE":
raise ValidationError(
stack.stack_id,
message="Stack:{0} is in ROLLBACK_COMPLETE state and can not be updated.".format(
stack.stack_id
),
)
stack = self.cloudformation_backend.update_stack(
name=stack_name,
template=stack_body,
role_arn=role_arn,
parameters=incoming_params,
tags=tags,
)
if self.request_json:
stack_body = {
"UpdateStackResponse": {"UpdateStackResult": {"StackId": stack.name}}
}
return json.dumps(stack_body)
else:
template = self.response_template(UPDATE_STACK_RESPONSE_TEMPLATE)
return template.render(stack=stack)
def delete_stack(self):
name_or_stack_id = self.querystring.get("StackName")[0]
self.cloudformation_backend.delete_stack(name_or_stack_id)
if self.request_json:
return json.dumps({"DeleteStackResponse": {"DeleteStackResult": {}}})
else:
template = self.response_template(DELETE_STACK_RESPONSE_TEMPLATE)
return template.render()
def list_exports(self):
token = self._get_param("NextToken")
exports, next_token = self.cloudformation_backend.list_exports(token=token)
template = self.response_template(LIST_EXPORTS_RESPONSE)
return template.render(exports=exports, next_token=next_token)
def validate_template(self):
template_body = self._get_param("TemplateBody")
template_url = self._get_param("TemplateURL")
if template_url:
template_body = self._get_stack_from_s3_url(template_url)
cfn_lint = self.cloudformation_backend.validate_template(template_body)
if cfn_lint:
raise ValidationError(cfn_lint[0].message)
description = ""
try:
description = json.loads(template_body)["Description"]
except (ValueError, KeyError):
pass
try:
description = yaml.load(template_body, Loader=yaml.Loader)["Description"]
except (yaml.parser.ParserError, yaml.scanner.ScannerError, KeyError):
pass
template = self.response_template(VALIDATE_STACK_RESPONSE_TEMPLATE)
return template.render(description=description)
def create_stack_set(self):
stackset_name = self._get_param("StackSetName")
stack_body = self._get_param("TemplateBody")
template_url = self._get_param("TemplateURL")
# role_arn = self._get_param('RoleARN')
parameters_list = self._get_list_prefix("Parameters.member")
tags = dict(
(item["key"], item["value"])
for item in self._get_list_prefix("Tags.member")
)
# Copy-Pasta - Hack dict-comprehension
parameters = dict(
[
(parameter["parameter_key"], parameter["parameter_value"])
for parameter in parameters_list
]
)
if template_url:
stack_body = self._get_stack_from_s3_url(template_url)
stackset = self.cloudformation_backend.create_stack_set(
name=stackset_name,
template=stack_body,
parameters=parameters,
tags=tags,
# role_arn=role_arn,
)
if self.request_json:
return json.dumps(
{
"CreateStackSetResponse": {
"CreateStackSetResult": {"StackSetId": stackset.id}
}
}
)
else:
template = self.response_template(CREATE_STACK_SET_RESPONSE_TEMPLATE)
return template.render(stackset=stackset)
def create_stack_instances(self):
stackset_name = self._get_param("StackSetName")
accounts = self._get_multi_param("Accounts.member")
regions = self._get_multi_param("Regions.member")
parameters = self._get_multi_param("ParameterOverrides.member")
self.cloudformation_backend.create_stack_instances(
stackset_name, accounts, regions, parameters
)
template = self.response_template(CREATE_STACK_INSTANCES_TEMPLATE)
return template.render()
def delete_stack_set(self):
stackset_name = self._get_param("StackSetName")
self.cloudformation_backend.delete_stack_set(stackset_name)
template = self.response_template(DELETE_STACK_SET_RESPONSE_TEMPLATE)
return template.render()
def delete_stack_instances(self):
stackset_name = self._get_param("StackSetName")
accounts = self._get_multi_param("Accounts.member")
regions = self._get_multi_param("Regions.member")
operation = self.cloudformation_backend.delete_stack_instances(
stackset_name, accounts, regions
)
template = self.response_template(DELETE_STACK_INSTANCES_TEMPLATE)
return template.render(operation=operation)
def describe_stack_set(self):
stackset_name = self._get_param("StackSetName")
stackset = self.cloudformation_backend.get_stack_set(stackset_name)
if not stackset.admin_role:
stackset.admin_role = "arn:aws:iam::{AccountId}:role/AWSCloudFormationStackSetAdministrationRole".format(
AccountId=ACCOUNT_ID
)
if not stackset.execution_role:
stackset.execution_role = "AWSCloudFormationStackSetExecutionRole"
template = self.response_template(DESCRIBE_STACK_SET_RESPONSE_TEMPLATE)
return template.render(stackset=stackset)
def describe_stack_instance(self):
stackset_name = self._get_param("StackSetName")
account = self._get_param("StackInstanceAccount")
region = self._get_param("StackInstanceRegion")
instance = self.cloudformation_backend.get_stack_set(
stackset_name
).instances.get_instance(account, region)
template = self.response_template(DESCRIBE_STACK_INSTANCE_TEMPLATE)
rendered = template.render(instance=instance)
return rendered
def list_stack_sets(self):
stacksets = self.cloudformation_backend.stacksets
template = self.response_template(LIST_STACK_SETS_TEMPLATE)
return template.render(stacksets=stacksets)
def list_stack_instances(self):
stackset_name = self._get_param("StackSetName")
stackset = self.cloudformation_backend.get_stack_set(stackset_name)
template = self.response_template(LIST_STACK_INSTANCES_TEMPLATE)
return template.render(stackset=stackset)
def list_stack_set_operations(self):
stackset_name = self._get_param("StackSetName")
stackset = self.cloudformation_backend.get_stack_set(stackset_name)
template = self.response_template(LIST_STACK_SET_OPERATIONS_RESPONSE_TEMPLATE)
return template.render(stackset=stackset)
def stop_stack_set_operation(self):
stackset_name = self._get_param("StackSetName")
operation_id = self._get_param("OperationId")
stackset = self.cloudformation_backend.get_stack_set(stackset_name)
stackset.update_operation(operation_id, "STOPPED")
template = self.response_template(STOP_STACK_SET_OPERATION_RESPONSE_TEMPLATE)
return template.render()
def describe_stack_set_operation(self):
stackset_name = self._get_param("StackSetName")
operation_id = self._get_param("OperationId")
stackset = self.cloudformation_backend.get_stack_set(stackset_name)
operation = stackset.get_operation(operation_id)
template = self.response_template(DESCRIBE_STACKSET_OPERATION_RESPONSE_TEMPLATE)
return template.render(stackset=stackset, operation=operation)
def list_stack_set_operation_results(self):
stackset_name = self._get_param("StackSetName")
operation_id = self._get_param("OperationId")
stackset = self.cloudformation_backend.get_stack_set(stackset_name)
operation = stackset.get_operation(operation_id)
template = self.response_template(
LIST_STACK_SET_OPERATION_RESULTS_RESPONSE_TEMPLATE
)
return template.render(operation=operation)
def update_stack_set(self):
stackset_name = self._get_param("StackSetName")
operation_id = self._get_param("OperationId")
description = self._get_param("Description")
execution_role = self._get_param("ExecutionRoleName")
admin_role = self._get_param("AdministrationRoleARN")
accounts = self._get_multi_param("Accounts.member")
regions = self._get_multi_param("Regions.member")
template_body = self._get_param("TemplateBody")
template_url = self._get_param("TemplateURL")
if template_url:
template_body = self._get_stack_from_s3_url(template_url)
tags = dict(
(item["key"], item["value"])
for item in self._get_list_prefix("Tags.member")
)
parameters_list = self._get_list_prefix("Parameters.member")
operation = self.cloudformation_backend.update_stack_set(
stackset_name=stackset_name,
template=template_body,
description=description,
parameters=parameters_list,
tags=tags,
admin_role=admin_role,
execution_role=execution_role,
accounts=accounts,
regions=regions,
operation_id=operation_id,
)
template = self.response_template(UPDATE_STACK_SET_RESPONSE_TEMPLATE)
return template.render(operation=operation)
def update_stack_instances(self):
stackset_name = self._get_param("StackSetName")
accounts = self._get_multi_param("Accounts.member")
regions = self._get_multi_param("Regions.member")
parameters = self._get_multi_param("ParameterOverrides.member")
operation = self.cloudformation_backend.get_stack_set(
stackset_name
).update_instances(accounts, regions, parameters)
template = self.response_template(UPDATE_STACK_INSTANCES_RESPONSE_TEMPLATE)
return template.render(operation=operation)
VALIDATE_STACK_RESPONSE_TEMPLATE = """
{{ description }}
"""
CREATE_STACK_RESPONSE_TEMPLATE = """
{{ stack.stack_id }}
b9b4b068-3a41-11e5-94eb-example
"""
CREATE_STACK_NAME_EXISTS_RESPONSE_TEMPLATE = """
Sender
AlreadyExistsException
Stack [{{ name }}] already exists
950ff8d7-812a-44b3-bb0c-9b271b954104
"""
UPDATE_STACK_RESPONSE_TEMPLATE = """
{{ stack.stack_id }}
b9b4b068-3a41-11e5-94eb-example
"""
CREATE_CHANGE_SET_RESPONSE_TEMPLATE = """
{{change_set_id}}
{{ stack_id }}
{{ request_id }}
"""
DELETE_CHANGE_SET_RESPONSE_TEMPLATE = """
3d3200a1-810e-3023-6cc3-example
"""
DESCRIBE_CHANGE_SET_RESPONSE_TEMPLATE = """
{{ change_set.change_set_id }}
{{ change_set.change_set_name }}
{{ change_set.stack_id }}
{{ change_set.stack_name }}
{{ change_set.description }}
{% for param_name, param_value in change_set.parameters.items() %}
{{ param_name }}
{{ param_value }}
{% endfor %}
{{ change_set.creation_time_iso_8601 }}
{{ change_set.execution_status }}
{{ change_set.status }}
{{ change_set.status_reason }}
{% if change_set.notification_arns %}
{% for notification_arn in change_set.notification_arns %}
{{ notification_arn }}
{% endfor %}
{% else %}
{% endif %}
{% if change_set.role_arn %}
{{ change_set.role_arn }}
{% endif %}
{% if change_set.changes %}
{% for change in change_set.changes %}
Resource
{{ change.action }}
{{ change.logical_resource_id }}
{{ change.resource_type }}
{% endfor %}
{% endif %}
{% if next_token %}
{{ next_token }}
{% endif %}
"""
EXECUTE_CHANGE_SET_RESPONSE_TEMPLATE = """
{{ request_id }}
"""
DESCRIBE_STACKS_TEMPLATE = """
{% for stack in stacks %}
{{ stack.name }}
{{ stack.stack_id }}
{% if stack.change_set_id %}
{{ stack.change_set_id }}
{% endif %}
{{ stack.creation_time_iso_8601 }}
{{ stack.status }}
{% if stack.notification_arns %}
{% for notification_arn in stack.notification_arns %}
{{ notification_arn }}
{% endfor %}
{% else %}
{% endif %}
false
{% for output in stack.stack_outputs %}
{{ output.key }}
{{ output.value }}
{% endfor %}
{% for param_name, param_value in stack.stack_parameters.items() %}
{{ param_name }}
{% if param_name in stack.resource_map.no_echo_parameter_keys %}
****
{% else %}
{{ param_value }}
{% endif %}
{% endfor %}
{% if stack.role_arn %}
{{ stack.role_arn }}
{% endif %}
{% for tag_key, tag_value in stack.tags.items() %}
{{ tag_key }}
{{ tag_value }}
{% endfor %}
{% endfor %}
{% if next_token %}
{{ next_token }}
{% endif %}
"""
DESCRIBE_STACK_RESOURCE_RESPONSE_TEMPLATE = """
{{ stack.stack_id }}
{{ stack.name }}
{{ resource.logical_resource_id }}
{{ resource.physical_resource_id }}
{{ resource.type }}
2010-07-27T22:27:28Z
{{ stack.status }}
"""
DESCRIBE_STACK_RESOURCES_RESPONSE = """
{% for resource in stack.stack_resources %}
{{ stack.stack_id }}
{{ stack.name }}
{{ resource.logical_resource_id }}
{{ resource.physical_resource_id }}
{{ resource.type }}
2010-07-27T22:27:28Z
{{ stack.status }}
{% endfor %}
"""
DESCRIBE_STACK_EVENTS_RESPONSE = """
{% for event in stack.events[::-1] %}
{{ event.timestamp.strftime('%Y-%m-%dT%H:%M:%S.%fZ') }}
{{ event.resource_status }}
{{ event.stack_id }}
{{ event.event_id }}
{{ event.logical_resource_id }}
{% if event.resource_status_reason %}{{ event.resource_status_reason }}{% endif %}
{{ event.stack_name }}
{{ event.physical_resource_id }}
{% if event.resource_properties %}{{ event.resource_properties }}{% endif %}
{{ event.resource_type }}
{% endfor %}
b9b4b068-3a41-11e5-94eb-example
"""
LIST_CHANGE_SETS_RESPONSE = """
{% for change_set in change_sets %}
{{ change_set.stack_id }}
{{ change_set.stack_name }}
{{ change_set.change_set_id }}
{{ change_set.change_set_name }}
{{ change_set.execution_status }}
{{ change_set.status }}
{{ change_set.status_reason }}
2011-05-23T15:47:44Z
{{ change_set.description }}
{% endfor %}
"""
LIST_STACKS_RESPONSE = """
{% for stack in stacks %}
{{ stack.stack_id }}
{{ stack.status }}
{{ stack.name }}
{{ stack.creation_time_iso_8601 }}
{{ stack.description }}
{% endfor %}
"""
LIST_STACKS_RESOURCES_RESPONSE = """
{% for resource in resources %}
CREATE_COMPLETE
{{ resource.logical_resource_id }}
2011-06-21T20:15:58Z
{{ resource.physical_resource_id }}
{{ resource.type }}
{% endfor %}
2d06e36c-ac1d-11e0-a958-f9382b6eb86b
"""
GET_TEMPLATE_RESPONSE_TEMPLATE = """
{{ stack.template }}
b9b4b068-3a41-11e5-94eb-example
"""
DELETE_STACK_RESPONSE_TEMPLATE = """
5ccc7dcd-744c-11e5-be70-example
"""
LIST_EXPORTS_RESPONSE = """
{% for export in exports %}
{{ export.exporting_stack_id }}
{{ export.name }}
{{ export.value }}
{% endfor %}
{% if next_token %}
{{ next_token }}
{% endif %}
5ccc7dcd-744c-11e5-be70-example
"""
CREATE_STACK_SET_RESPONSE_TEMPLATE = """
{{ stackset.id }}
f457258c-391d-41d1-861f-example
"""
DESCRIBE_STACK_SET_RESPONSE_TEMPLATE = """
{{ stackset.arn }}
{{ stackset.execution_role }}
{{ stackset.admin_role }}
{{ stackset.id }}
{{ stackset.template }}
{{ stackset.name }}
{% for param_name, param_value in stackset.parameters.items() %}
{{ param_name }}
{{ param_value }}
{% endfor %}
{% for tag_key, tag_value in stackset.tags.items() %}
{{ tag_key }}
{{ tag_value }}
{% endfor %}
{{ stackset.status }}
d8b64e11-5332-46e1-9603-example
"""
DELETE_STACK_SET_RESPONSE_TEMPLATE = """
c35ec2d0-d69f-4c4d-9bd7-example
"""
CREATE_STACK_INSTANCES_TEMPLATE = """
1459ad6d-63cc-4c96-a73e-example
6b29f7e3-69be-4d32-b374-example
"""
LIST_STACK_INSTANCES_TEMPLATE = """
{% for instance in stackset.stack_instances %}
{{ instance.StackId }}
{{ instance.StackSetId }}
{{ instance.Region }}
{{ instance.Account }}
{{ instance.Status }}
{% endfor %}
83c27e73-b498-410f-993c-example
"""
DELETE_STACK_INSTANCES_TEMPLATE = """
{{ operation.OperationId }}
e5325090-66f6-4ecd-a531-example
"""
DESCRIBE_STACK_INSTANCE_TEMPLATE = """
{{ instance.StackId }}
{{ instance.StackSetId }}
{% if instance.ParameterOverrides %}
{% for override in instance.ParameterOverrides %}
{% if override['ParameterKey'] or override['ParameterValue'] %}
{{ override.ParameterKey }}
false
{{ override.ParameterValue }}
{% endif %}
{% endfor %}
{% else %}
{% endif %}
{{ instance.Region }}
{{ instance.Account }}
{{ instance.Status }}
c6c7be10-0343-4319-8a25-example
"""
LIST_STACK_SETS_TEMPLATE = """
{% for key, value in stacksets.items() %}
{{ value.name }}
{{ value.id }}
{{ value.status }}
{% endfor %}
4dcacb73-841e-4ed8-b335-example
"""
UPDATE_STACK_INSTANCES_RESPONSE_TEMPLATE = """
{{ operation }}
bdbf8e94-19b6-4ce4-af85-example
"""
UPDATE_STACK_SET_RESPONSE_TEMPLATE = """
{{ operation.OperationId }}
adac907b-17e3-43e6-a254-example
"""
LIST_STACK_SET_OPERATIONS_RESPONSE_TEMPLATE = """
{% for operation in stackset.operations %}
{{ operation.CreationTimestamp }}
{{ operation.OperationId }}
{{ operation.Action }}
{{ operation.EndTimestamp }}
{{ operation.Status }}
{% endfor %}
65b9d9be-08bb-4a43-9a21-example
"""
STOP_STACK_SET_OPERATION_RESPONSE_TEMPLATE = """
2188554a-07c6-4396-b2c5-example
"""
DESCRIBE_STACKSET_OPERATION_RESPONSE_TEMPLATE = (
"""
{{ stackset.execution_role }}
arn:aws:iam::"""
+ ACCOUNT_ID
+ """:role/{{ stackset.admin_role }}
{{ stackset.id }}
{{ operation.CreationTimestamp }}
{{ operation.OperationId }}
{{ operation.Action }}
{{ operation.EndTimestamp }}
{{ operation.Status }}
2edc27b6-9ce2-486a-a192-example
"""
)
LIST_STACK_SET_OPERATION_RESULTS_RESPONSE_TEMPLATE = (
"""
{% for instance in operation.Instances %}
{% for account, region in instance.items() %}
Function not found: arn:aws:lambda:us-west-2:"""
+ ACCOUNT_ID
+ """:function:AWSCloudFormationStackSetAccountGate
SKIPPED
{{ region }}
{{ account }}
{{ operation.Status }}
{% endfor %}
{% endfor %}
ac05a9ce-5f98-4197-a29b-example
"""
)
GET_TEMPLATE_SUMMARY_TEMPLATE = """
{{ template_summary.Description }}
{% for resource in template_summary.resourceTypes %}
{{ resource }}
{% endfor %}
{{ template_summary.AWSTemplateFormatVersion }}
b9b4b068-3a41-11e5-94eb-example
"""