summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Dines <nathandines@users.noreply.github.com>2019-04-12 18:18:06 +0200
committerJill R <4121322+jillr@users.noreply.github.com>2019-04-12 18:18:06 +0200
commit5eb311782264742451c5ae927bc6514f7e8e5793 (patch)
tree2bc359375c8afa836e314c318efa4701d12df1cf
parentbecome mixin is no more (#54002) (diff)
downloadansible-5eb311782264742451c5ae927bc6514f7e8e5793.tar.xz
ansible-5eb311782264742451c5ae927bc6514f7e8e5793.zip
Added the OnFailure option to the AWS CloudFormation module (#52431)
* Added the OnFailure option to the AWS CloudFormation module * Added unit tests for CloudFormation `on_create_failure`
-rw-r--r--lib/ansible/modules/cloud/amazon/cloudformation.py79
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.CreateStack_1.json17
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_1.json38
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_2.json101
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_3.json121
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_4.json180
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_5.json180
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_1.json42
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_2.json41
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_3.json52
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_4.json51
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_5.json50
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.CreateStack_1.json17
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DeleteStack_1.json16
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStackEvents_1.json38
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStackEvents_2.json121
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStacks_1.json42
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStacks_2.json42
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.CreateStack_1.json17
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DeleteStack_1.json16
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_1.json38
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_2.json121
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_3.json180
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_1.json42
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_2.json52
-rw-r--r--test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_3.json51
-rw-r--r--test/units/modules/cloud/amazon/test_cloudformation.py93
27 files changed, 1815 insertions, 23 deletions
diff --git a/lib/ansible/modules/cloud/amazon/cloudformation.py b/lib/ansible/modules/cloud/amazon/cloudformation.py
index 9d4283f79c..923392c54a 100644
--- a/lib/ansible/modules/cloud/amazon/cloudformation.py
+++ b/lib/ansible/modules/cloud/amazon/cloudformation.py
@@ -33,6 +33,14 @@ options:
- If a stacks fails to form, rollback will remove the stack
type: bool
default: 'no'
+ on_create_failure:
+ description:
+ - Action to take upon failure of stack creation. Incompatible with the disable_rollback option.
+ choices:
+ - DO_NOTHING
+ - ROLLBACK
+ - DELETE
+ version_added: "2.8"
create_timeout:
description:
- The amount of time (in minutes) that can pass before the stack status becomes CREATE_FAILED
@@ -259,6 +267,17 @@ EXAMPLES = '''
template_url: https://s3.amazonaws.com/my-bucket/cloudformation.template
create_timeout: 5
+# Configure rollback behaviour on the unsuccessful creation of a stack allowing
+# CloudFormation to clean up, or do nothing in the event of an unsuccessful
+# deployment
+# In this case, if on_create_failure is set to "DELETE", it will clean up the stack if
+# it fails to create
+- name: create stack which will delete on creation failure
+ cloudformation:
+ stack_name: my_stack
+ state: present
+ template_url: https://s3.amazonaws.com/my-bucket/cloudformation.template
+ on_create_failure: DELETE
'''
RETURN = '''
@@ -354,9 +373,17 @@ def create_stack(module, stack_params, cfn, events_limit):
if 'TemplateBody' not in stack_params and 'TemplateURL' not in stack_params:
module.fail_json(msg="Either 'template', 'template_body' or 'template_url' is required when the stack does not exist.")
- # 'DisableRollback', 'TimeoutInMinutes' and 'EnableTerminationProtection'
- # only apply on creation, not update.
- stack_params['DisableRollback'] = module.params['disable_rollback']
+ # 'DisableRollback', 'TimeoutInMinutes', 'EnableTerminationProtection' and
+ # 'OnFailure' only apply on creation, not update.
+ #
+ # 'OnFailure' and 'DisableRollback' are incompatible with each other, so
+ # throw error if both are defined
+ if module.params.get('on_create_failure') is None:
+ stack_params['DisableRollback'] = module.params['disable_rollback']
+ else:
+ if module.params['disable_rollback']:
+ module.fail_json(msg="You can specify either 'on_create_failure' or 'disable_rollback', but not both.")
+ stack_params['OnFailure'] = module.params['on_create_failure']
if module.params.get('create_timeout') is not None:
stack_params['TimeoutInMinutes'] = module.params['create_timeout']
if module.params.get('termination_protection') is not None:
@@ -366,8 +393,9 @@ def create_stack(module, stack_params, cfn, events_limit):
module.fail_json(msg="termination_protection parameter requires botocore >= 1.7.18")
try:
- cfn.create_stack(**stack_params)
- result = stack_operation(cfn, stack_params['StackName'], 'CREATE', events_limit, stack_params.get('ClientRequestToken', None))
+ response = cfn.create_stack(**stack_params)
+ # Use stack ID to follow stack state in case of on_create_failure = DELETE
+ result = stack_operation(cfn, response['StackId'], 'CREATE', events_limit, stack_params.get('ClientRequestToken', None))
except Exception as err:
error_msg = boto_exception(err)
module.fail_json(msg="Failed to create stack {0}: {1}.".format(stack_params.get('StackName'), error_msg), exception=traceback.format_exc())
@@ -509,7 +537,10 @@ def stack_operation(cfn, stack_name, operation, events_limit, op_token=None):
elif stack['StackStatus'].endswith('ROLLBACK_COMPLETE') and operation != 'CREATE_CHANGESET':
ret.update({'changed': True, 'failed': True, 'output': 'Problem with %s. Rollback complete' % operation})
return ret
- # note the ordering of ROLLBACK_COMPLETE and COMPLETE, because otherwise COMPLETE will match both cases.
+ elif stack['StackStatus'] == 'DELETE_COMPLETE' and operation == 'CREATE':
+ ret.update({'changed': True, 'failed': True, 'output': 'Stack create failed. Delete complete.'})
+ return ret
+ # note the ordering of ROLLBACK_COMPLETE, DELETE_COMPLETE, and COMPLETE, because otherwise COMPLETE will match all cases.
elif stack['StackStatus'].endswith('_COMPLETE'):
ret.update({'changed': True, 'output': 'Stack %s complete' % operation})
return ret
@@ -599,6 +630,7 @@ def main():
notification_arns=dict(default=None, required=False),
stack_policy=dict(default=None, required=False),
disable_rollback=dict(default=False, type='bool'),
+ on_create_failure=dict(default=None, required=False, choices=['DO_NOTHING', 'ROLLBACK', 'DELETE']),
create_timeout=dict(default=None, type='int'),
template_url=dict(default=None, required=False),
template_body=dict(default=None, require=False),
@@ -738,23 +770,24 @@ def main():
# format the stack output
stack = get_stack_facts(cfn, stack_params['StackName'])
- if result.get('stack_outputs') is None:
- # always define stack_outputs, but it may be empty
- result['stack_outputs'] = {}
- for output in stack.get('Outputs', []):
- result['stack_outputs'][output['OutputKey']] = output['OutputValue']
- stack_resources = []
- reslist = cfn.list_stack_resources(StackName=stack_params['StackName'])
- for res in reslist.get('StackResourceSummaries', []):
- stack_resources.append({
- "logical_resource_id": res['LogicalResourceId'],
- "physical_resource_id": res.get('PhysicalResourceId', ''),
- "resource_type": res['ResourceType'],
- "last_updated_time": res['LastUpdatedTimestamp'],
- "status": res['ResourceStatus'],
- "status_reason": res.get('ResourceStatusReason') # can be blank, apparently
- })
- result['stack_resources'] = stack_resources
+ if stack is not None:
+ if result.get('stack_outputs') is None:
+ # always define stack_outputs, but it may be empty
+ result['stack_outputs'] = {}
+ for output in stack.get('Outputs', []):
+ result['stack_outputs'][output['OutputKey']] = output['OutputValue']
+ stack_resources = []
+ reslist = cfn.list_stack_resources(StackName=stack_params['StackName'])
+ for res in reslist.get('StackResourceSummaries', []):
+ stack_resources.append({
+ "logical_resource_id": res['LogicalResourceId'],
+ "physical_resource_id": res.get('PhysicalResourceId', ''),
+ "resource_type": res['ResourceType'],
+ "last_updated_time": res['LastUpdatedTimestamp'],
+ "status": res['ResourceStatus'],
+ "status_reason": res.get('ResourceStatusReason') # can be blank, apparently
+ })
+ result['stack_resources'] = stack_resources
elif state == 'absent':
# absent state is different because of the way delete_stack works.
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.CreateStack_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.CreateStack_1.json
new file mode 100644
index 0000000000..64c8e1f23b
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.CreateStack_1.json
@@ -0,0 +1,17 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResponseMetadata": {
+ "RequestId": "c741ebcd-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "c741ebcd-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "407",
+ "date": "Tue, 26 Feb 2019 21:37:55 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_1.json
new file mode 100644
index 0000000000..7a6a496440
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_1.json
@@ -0,0 +1,38 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "c74b1310-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "c7b0b337-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "c7b0b337-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "1153",
+ "date": "Tue, 26 Feb 2019 21:37:56 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_2.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_2.json
new file mode 100644
index 0000000000..6218ed8b86
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_2.json
@@ -0,0 +1,101 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_FAILED-2019-02-26T21:38:01.107Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 1,
+ "microsecond": 107000
+ },
+ "ResourceStatus": "CREATE_FAILED",
+ "ResourceStatusReason": "Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided' (Service: AmazonECR; Status Code: 400; Error Code: InvalidParameterException; Request ID: ca5769ae-3a0e-11e9-a183-3f277586a4cb)",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:38:00.657Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 0,
+ "microsecond": 657000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "Resource creation Initiated",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:38:00.221Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 0,
+ "microsecond": 221000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "c74b1310-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "caf667e9-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "caf667e9-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "4312",
+ "vary": "Accept-Encoding",
+ "date": "Tue, 26 Feb 2019 21:38:01 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_3.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_3.json
new file mode 100644
index 0000000000..cde6beb8ee
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_3.json
@@ -0,0 +1,121 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "cafc8250-3a0e-11e9-86c5-02035744c0fa",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 2,
+ "microsecond": 76000
+ },
+ "ResourceStatus": "DELETE_IN_PROGRESS",
+ "ResourceStatusReason": "The following resource(s) failed to create: [ECRRepo]. . Delete requested by user."
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_FAILED-2019-02-26T21:38:01.107Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 1,
+ "microsecond": 107000
+ },
+ "ResourceStatus": "CREATE_FAILED",
+ "ResourceStatusReason": "Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided' (Service: AmazonECR; Status Code: 400; Error Code: InvalidParameterException; Request ID: ca5769ae-3a0e-11e9-a183-3f277586a4cb)",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:38:00.657Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 0,
+ "microsecond": 657000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "Resource creation Initiated",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:38:00.221Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 0,
+ "microsecond": 221000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "c74b1310-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "ce498af1-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "ce498af1-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "5207",
+ "vary": "Accept-Encoding",
+ "date": "Tue, 26 Feb 2019 21:38:06 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_4.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_4.json
new file mode 100644
index 0000000000..4f35d6ddc9
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_4.json
@@ -0,0 +1,180 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "d19c8600-3a0e-11e9-a4ba-0a3524ef8042",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 13,
+ "microsecond": 177000
+ },
+ "ResourceStatus": "DELETE_COMPLETE"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-DELETE_COMPLETE-2019-02-26T21:38:12.486Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 12,
+ "microsecond": 486000
+ },
+ "ResourceStatus": "DELETE_COMPLETE",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-DELETE_IN_PROGRESS-2019-02-26T21:38:12.139Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 12,
+ "microsecond": 139000
+ },
+ "ResourceStatus": "DELETE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "cafc8250-3a0e-11e9-86c5-02035744c0fa",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 2,
+ "microsecond": 76000
+ },
+ "ResourceStatus": "DELETE_IN_PROGRESS",
+ "ResourceStatusReason": "The following resource(s) failed to create: [ECRRepo]. . Delete requested by user."
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_FAILED-2019-02-26T21:38:01.107Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 1,
+ "microsecond": 107000
+ },
+ "ResourceStatus": "CREATE_FAILED",
+ "ResourceStatusReason": "Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided' (Service: AmazonECR; Status Code: 400; Error Code: InvalidParameterException; Request ID: ca5769ae-3a0e-11e9-a183-3f277586a4cb)",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:38:00.657Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 0,
+ "microsecond": 657000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "Resource creation Initiated",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:38:00.221Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 0,
+ "microsecond": 221000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "c74b1310-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "d19fbb1b-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "d19fbb1b-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "7857",
+ "vary": "Accept-Encoding",
+ "date": "Tue, 26 Feb 2019 21:38:12 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_5.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_5.json
new file mode 100644
index 0000000000..68a743f89e
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStackEvents_5.json
@@ -0,0 +1,180 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "d19c8600-3a0e-11e9-a4ba-0a3524ef8042",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 13,
+ "microsecond": 177000
+ },
+ "ResourceStatus": "DELETE_COMPLETE"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-DELETE_COMPLETE-2019-02-26T21:38:12.486Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 12,
+ "microsecond": 486000
+ },
+ "ResourceStatus": "DELETE_COMPLETE",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-DELETE_IN_PROGRESS-2019-02-26T21:38:12.139Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 12,
+ "microsecond": 139000
+ },
+ "ResourceStatus": "DELETE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "cafc8250-3a0e-11e9-86c5-02035744c0fa",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 2,
+ "microsecond": 76000
+ },
+ "ResourceStatus": "DELETE_IN_PROGRESS",
+ "ResourceStatusReason": "The following resource(s) failed to create: [ECRRepo]. . Delete requested by user."
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_FAILED-2019-02-26T21:38:01.107Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 1,
+ "microsecond": 107000
+ },
+ "ResourceStatus": "CREATE_FAILED",
+ "ResourceStatusReason": "Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided' (Service: AmazonECR; Status Code: 400; Error Code: InvalidParameterException; Request ID: ca5769ae-3a0e-11e9-a183-3f277586a4cb)",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:38:00.657Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-8jlpw72yz5x8",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 0,
+ "microsecond": 657000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "Resource creation Initiated",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:38:00.221Z",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 0,
+ "microsecond": 221000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "EventId": "c74b1310-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "LogicalResourceId": "ansible-test-on-create-failure-delete",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "d4fbddab-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "d4fbddab-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "7857",
+ "vary": "Accept-Encoding",
+ "date": "Tue, 26 Feb 2019 21:38:18 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_1.json
new file mode 100644
index 0000000000..cf5f86acbd
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_1.json
@@ -0,0 +1,42 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "CREATE_IN_PROGRESS",
+ "StackStatusReason": "User Initiated",
+ "DisableRollback": false,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "c77fb823-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "c77fb823-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "1041",
+ "date": "Tue, 26 Feb 2019 21:37:56 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_2.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_2.json
new file mode 100644
index 0000000000..71a9f54b68
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_2.json
@@ -0,0 +1,41 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "CREATE_IN_PROGRESS",
+ "DisableRollback": false,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "cad153b2-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "cad153b2-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "979",
+ "date": "Tue, 26 Feb 2019 21:38:01 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_3.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_3.json
new file mode 100644
index 0000000000..c2028183bd
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_3.json
@@ -0,0 +1,52 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "DeletionTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 2,
+ "microsecond": 76000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "DELETE_IN_PROGRESS",
+ "StackStatusReason": "The following resource(s) failed to create: [ECRRepo]. . Delete requested by user.",
+ "DisableRollback": false,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "ce24289a-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "ce24289a-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "1171",
+ "date": "Tue, 26 Feb 2019 21:38:06 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_4.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_4.json
new file mode 100644
index 0000000000..89f8355319
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_4.json
@@ -0,0 +1,51 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "DeletionTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 2,
+ "microsecond": 76000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "DELETE_IN_PROGRESS",
+ "DisableRollback": false,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "d16c27f2-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "d16c27f2-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "1041",
+ "date": "Tue, 26 Feb 2019 21:38:12 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_5.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_5.json
new file mode 100644
index 0000000000..739c829376
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_delete/cloudformation.DescribeStacks_5.json
@@ -0,0 +1,50 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-delete/c74a4fc0-3a0e-11e9-9a48-067794494828",
+ "StackName": "ansible-test-on-create-failure-delete",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 37,
+ "second": 55,
+ "microsecond": 909000
+ },
+ "DeletionTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 38,
+ "second": 2,
+ "microsecond": 76000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "DELETE_COMPLETE",
+ "DisableRollback": false,
+ "NotificationARNs": [],
+ "Tags": [],
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "d4c90dd6-3a0e-11e9-b25f-d1217e6893bf",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "d4c90dd6-3a0e-11e9-b25f-d1217e6893bf",
+ "content-type": "text/xml",
+ "content-length": "965",
+ "date": "Tue, 26 Feb 2019 21:38:18 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.CreateStack_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.CreateStack_1.json
new file mode 100644
index 0000000000..86f1945fd6
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.CreateStack_1.json
@@ -0,0 +1,17 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "ResponseMetadata": {
+ "RequestId": "a396a58a-3a0f-11e9-b7db-3fe3824c73cb",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "a396a58a-3a0f-11e9-b7db-3fe3824c73cb",
+ "content-type": "text/xml",
+ "content-length": "411",
+ "date": "Tue, 26 Feb 2019 21:44:05 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DeleteStack_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DeleteStack_1.json
new file mode 100644
index 0000000000..1a3a67c640
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DeleteStack_1.json
@@ -0,0 +1,16 @@
+{
+ "status_code": 200,
+ "data": {
+ "ResponseMetadata": {
+ "RequestId": "a78f0832-3a0f-11e9-b7db-3fe3824c73cb",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "a78f0832-3a0f-11e9-b7db-3fe3824c73cb",
+ "content-type": "text/xml",
+ "content-length": "212",
+ "date": "Tue, 26 Feb 2019 21:44:11 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+} \ No newline at end of file
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStackEvents_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStackEvents_1.json
new file mode 100644
index 0000000000..58d7a89e41
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStackEvents_1.json
@@ -0,0 +1,38 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "EventId": "a39e6ce0-3a0f-11e9-96ca-02f46dd00950",
+ "StackName": "ansible-test-on-create-failure-do-nothing",
+ "LogicalResourceId": "ansible-test-on-create-failure-do-nothing",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 44,
+ "second": 5,
+ "microsecond": 553000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "a406cc84-3a0f-11e9-b7db-3fe3824c73cb",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "a406cc84-3a0f-11e9-b7db-3fe3824c73cb",
+ "content-type": "text/xml",
+ "content-length": "1169",
+ "date": "Tue, 26 Feb 2019 21:44:06 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStackEvents_2.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStackEvents_2.json
new file mode 100644
index 0000000000..0a7e32e468
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStackEvents_2.json
@@ -0,0 +1,121 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "EventId": "a6c32c80-3a0f-11e9-ac5e-06deb474fa52",
+ "StackName": "ansible-test-on-create-failure-do-nothing",
+ "LogicalResourceId": "ansible-test-on-create-failure-do-nothing",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 44,
+ "second": 10,
+ "microsecond": 804000
+ },
+ "ResourceStatus": "CREATE_FAILED",
+ "ResourceStatusReason": "The following resource(s) failed to create: [ECRRepo]. "
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "EventId": "ECRRepo-CREATE_FAILED-2019-02-26T21:44:09.905Z",
+ "StackName": "ansible-test-on-create-failure-do-nothing",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-a8g0mh5il4t5",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 44,
+ "second": 9,
+ "microsecond": 905000
+ },
+ "ResourceStatus": "CREATE_FAILED",
+ "ResourceStatusReason": "Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided' (Service: AmazonECR; Status Code: 400; Error Code: InvalidParameterException; Request ID: a62a6f71-3a0f-11e9-9164-457e0a3a5e1b)",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:44:09.497Z",
+ "StackName": "ansible-test-on-create-failure-do-nothing",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-a8g0mh5il4t5",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 44,
+ "second": 9,
+ "microsecond": 497000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "Resource creation Initiated",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:44:09.076Z",
+ "StackName": "ansible-test-on-create-failure-do-nothing",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 44,
+ "second": 9,
+ "microsecond": 76000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "EventId": "a39e6ce0-3a0f-11e9-96ca-02f46dd00950",
+ "StackName": "ansible-test-on-create-failure-do-nothing",
+ "LogicalResourceId": "ansible-test-on-create-failure-do-nothing",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 44,
+ "second": 5,
+ "microsecond": 553000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "a75fbad0-3a0f-11e9-b7db-3fe3824c73cb",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "a75fbad0-3a0f-11e9-b7db-3fe3824c73cb",
+ "content-type": "text/xml",
+ "content-length": "5231",
+ "vary": "Accept-Encoding",
+ "date": "Tue, 26 Feb 2019 21:44:11 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStacks_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStacks_1.json
new file mode 100644
index 0000000000..532143313b
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStacks_1.json
@@ -0,0 +1,42 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "StackName": "ansible-test-on-create-failure-do-nothing",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 44,
+ "second": 5,
+ "microsecond": 553000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "CREATE_IN_PROGRESS",
+ "StackStatusReason": "User Initiated",
+ "DisableRollback": true,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "a3d44acf-3a0f-11e9-b7db-3fe3824c73cb",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "a3d44acf-3a0f-11e9-b7db-3fe3824c73cb",
+ "content-type": "text/xml",
+ "content-length": "1048",
+ "date": "Tue, 26 Feb 2019 21:44:05 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStacks_2.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStacks_2.json
new file mode 100644
index 0000000000..df17f5a730
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_do_nothing/cloudformation.DescribeStacks_2.json
@@ -0,0 +1,42 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-do-nothing/a39dd0a0-3a0f-11e9-96ca-02f46dd00950",
+ "StackName": "ansible-test-on-create-failure-do-nothing",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 44,
+ "second": 5,
+ "microsecond": 553000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "CREATE_FAILED",
+ "StackStatusReason": "The following resource(s) failed to create: [ECRRepo]. ",
+ "DisableRollback": true,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "a7301f4a-3a0f-11e9-b7db-3fe3824c73cb",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "a7301f4a-3a0f-11e9-b7db-3fe3824c73cb",
+ "content-type": "text/xml",
+ "content-length": "1084",
+ "date": "Tue, 26 Feb 2019 21:44:11 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.CreateStack_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.CreateStack_1.json
new file mode 100644
index 0000000000..f71422b92a
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.CreateStack_1.json
@@ -0,0 +1,17 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "ResponseMetadata": {
+ "RequestId": "9139de54-3a0f-11e9-b938-97983b40cabe",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "9139de54-3a0f-11e9-b938-97983b40cabe",
+ "content-type": "text/xml",
+ "content-length": "409",
+ "date": "Tue, 26 Feb 2019 21:43:34 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DeleteStack_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DeleteStack_1.json
new file mode 100644
index 0000000000..111dc90d81
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DeleteStack_1.json
@@ -0,0 +1,16 @@
+{
+ "status_code": 200,
+ "data": {
+ "ResponseMetadata": {
+ "RequestId": "988b3097-3a0f-11e9-b938-97983b40cabe",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "988b3097-3a0f-11e9-b938-97983b40cabe",
+ "content-type": "text/xml",
+ "content-length": "212",
+ "date": "Tue, 26 Feb 2019 21:43:46 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+} \ No newline at end of file
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_1.json
new file mode 100644
index 0000000000..2bcac7f0e1
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_1.json
@@ -0,0 +1,38 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "9140bc10-3a0f-11e9-94bf-0a9edf17d014",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ansible-test-on-create-failure-rollback",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 34,
+ "microsecond": 740000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "9199b1a7-3a0f-11e9-b938-97983b40cabe",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "9199b1a7-3a0f-11e9-b938-97983b40cabe",
+ "content-type": "text/xml",
+ "content-length": "1161",
+ "date": "Tue, 26 Feb 2019 21:43:35 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_2.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_2.json
new file mode 100644
index 0000000000..3992fd3973
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_2.json
@@ -0,0 +1,121 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "945b90a0-3a0f-11e9-adaf-0211d8bec7e2",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ansible-test-on-create-failure-rollback",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 39,
+ "microsecond": 920000
+ },
+ "ResourceStatus": "ROLLBACK_IN_PROGRESS",
+ "ResourceStatusReason": "The following resource(s) failed to create: [ECRRepo]. . Rollback requested by user."
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "ECRRepo-CREATE_FAILED-2019-02-26T21:43:39.210Z",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-1lsnxu2zpb20l",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 39,
+ "microsecond": 210000
+ },
+ "ResourceStatus": "CREATE_FAILED",
+ "ResourceStatusReason": "Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided' (Service: AmazonECR; Status Code: 400; Error Code: InvalidParameterException; Request ID: 93e0bb60-3a0f-11e9-a53c-7162bb423e4d)",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:43:38.793Z",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-1lsnxu2zpb20l",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 38,
+ "microsecond": 793000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "Resource creation Initiated",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:43:38.266Z",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 38,
+ "microsecond": 266000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "9140bc10-3a0f-11e9-94bf-0a9edf17d014",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ansible-test-on-create-failure-rollback",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 34,
+ "microsecond": 740000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "94e16307-3a0f-11e9-b938-97983b40cabe",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "94e16307-3a0f-11e9-b938-97983b40cabe",
+ "content-type": "text/xml",
+ "content-length": "5241",
+ "vary": "Accept-Encoding",
+ "date": "Tue, 26 Feb 2019 21:43:40 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_3.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_3.json
new file mode 100644
index 0000000000..e272c734b7
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStackEvents_3.json
@@ -0,0 +1,180 @@
+{
+ "status_code": 200,
+ "data": {
+ "StackEvents": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "9743bc70-3a0f-11e9-b335-0ade61d04ee6",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ansible-test-on-create-failure-rollback",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 44,
+ "microsecond": 797000
+ },
+ "ResourceStatus": "ROLLBACK_COMPLETE"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "ECRRepo-DELETE_COMPLETE-2019-02-26T21:43:43.908Z",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-1lsnxu2zpb20l",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 43,
+ "microsecond": 908000
+ },
+ "ResourceStatus": "DELETE_COMPLETE",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "ECRRepo-DELETE_IN_PROGRESS-2019-02-26T21:43:43.478Z",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-1lsnxu2zpb20l",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 43,
+ "microsecond": 478000
+ },
+ "ResourceStatus": "DELETE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "945b90a0-3a0f-11e9-adaf-0211d8bec7e2",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ansible-test-on-create-failure-rollback",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 39,
+ "microsecond": 920000
+ },
+ "ResourceStatus": "ROLLBACK_IN_PROGRESS",
+ "ResourceStatusReason": "The following resource(s) failed to create: [ECRRepo]. . Rollback requested by user."
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "ECRRepo-CREATE_FAILED-2019-02-26T21:43:39.210Z",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-1lsnxu2zpb20l",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 39,
+ "microsecond": 210000
+ },
+ "ResourceStatus": "CREATE_FAILED",
+ "ResourceStatusReason": "Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided' (Service: AmazonECR; Status Code: 400; Error Code: InvalidParameterException; Request ID: 93e0bb60-3a0f-11e9-a53c-7162bb423e4d)",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:43:38.793Z",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "ansib-ecrre-1lsnxu2zpb20l",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 38,
+ "microsecond": 793000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "Resource creation Initiated",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "ECRRepo-CREATE_IN_PROGRESS-2019-02-26T21:43:38.266Z",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ECRRepo",
+ "PhysicalResourceId": "",
+ "ResourceType": "AWS::ECR::Repository",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 38,
+ "microsecond": 266000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceProperties": "{\"RepositoryPolicyText\":{\"Version\":\"3000-10-17\",\"Statement\":[{\"Action\":[\"ecr:*\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam::123456789012:root\"}}]}}"
+ },
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "EventId": "9140bc10-3a0f-11e9-94bf-0a9edf17d014",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "LogicalResourceId": "ansible-test-on-create-failure-rollback",
+ "PhysicalResourceId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "ResourceType": "AWS::CloudFormation::Stack",
+ "Timestamp": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 34,
+ "microsecond": 740000
+ },
+ "ResourceStatus": "CREATE_IN_PROGRESS",
+ "ResourceStatusReason": "User Initiated"
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "982d0bff-3a0f-11e9-b938-97983b40cabe",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "982d0bff-3a0f-11e9-b938-97983b40cabe",
+ "content-type": "text/xml",
+ "content-length": "7911",
+ "vary": "Accept-Encoding",
+ "date": "Tue, 26 Feb 2019 21:43:45 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_1.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_1.json
new file mode 100644
index 0000000000..25facea18d
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_1.json
@@ -0,0 +1,42 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 34,
+ "microsecond": 740000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "CREATE_IN_PROGRESS",
+ "StackStatusReason": "User Initiated",
+ "DisableRollback": false,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "91725383-3a0f-11e9-b938-97983b40cabe",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "91725383-3a0f-11e9-b938-97983b40cabe",
+ "content-type": "text/xml",
+ "content-length": "1045",
+ "date": "Tue, 26 Feb 2019 21:43:35 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_2.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_2.json
new file mode 100644
index 0000000000..55a80d8afe
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_2.json
@@ -0,0 +1,52 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 34,
+ "microsecond": 740000
+ },
+ "DeletionTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 39,
+ "microsecond": 920000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "ROLLBACK_IN_PROGRESS",
+ "StackStatusReason": "The following resource(s) failed to create: [ECRRepo]. . Rollback requested by user.",
+ "DisableRollback": false,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "94bb1651-3a0f-11e9-b938-97983b40cabe",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "94bb1651-3a0f-11e9-b938-97983b40cabe",
+ "content-type": "text/xml",
+ "content-length": "1179",
+ "date": "Tue, 26 Feb 2019 21:43:40 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_3.json b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_3.json
new file mode 100644
index 0000000000..7c00a83644
--- /dev/null
+++ b/test/units/modules/cloud/amazon/placebo_recordings/cloudformation/on_create_failure_rollback/cloudformation.DescribeStacks_3.json
@@ -0,0 +1,51 @@
+{
+ "status_code": 200,
+ "data": {
+ "Stacks": [
+ {
+ "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/ansible-test-on-create-failure-rollback/914046e0-3a0f-11e9-94bf-0a9edf17d014",
+ "StackName": "ansible-test-on-create-failure-rollback",
+ "CreationTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 34,
+ "microsecond": 740000
+ },
+ "DeletionTime": {
+ "__class__": "datetime",
+ "year": 2019,
+ "month": 2,
+ "day": 26,
+ "hour": 21,
+ "minute": 43,
+ "second": 39,
+ "microsecond": 920000
+ },
+ "RollbackConfiguration": {},
+ "StackStatus": "ROLLBACK_COMPLETE",
+ "DisableRollback": false,
+ "NotificationARNs": [],
+ "Tags": [],
+ "EnableTerminationProtection": false,
+ "DriftInformation": {
+ "StackDriftStatus": "NOT_CHECKED"
+ }
+ }
+ ],
+ "ResponseMetadata": {
+ "RequestId": "98016814-3a0f-11e9-b938-97983b40cabe",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {
+ "x-amzn-requestid": "98016814-3a0f-11e9-b938-97983b40cabe",
+ "content-type": "text/xml",
+ "content-length": "1044",
+ "date": "Tue, 26 Feb 2019 21:43:45 GMT"
+ },
+ "RetryAttempts": 0
+ }
+ }
+}
diff --git a/test/units/modules/cloud/amazon/test_cloudformation.py b/test/units/modules/cloud/amazon/test_cloudformation.py
index e0c810e652..6c1e658866 100644
--- a/test/units/modules/cloud/amazon/test_cloudformation.py
+++ b/test/units/modules/cloud/amazon/test_cloudformation.py
@@ -44,6 +44,23 @@ bad_json_tpl = """{
}
}"""
+failing_yaml_tpl = """
+---
+AWSTemplateFormatVersion: 2010-09-09
+Resources:
+ ECRRepo:
+ Type: AWS::ECR::Repository
+ Properties:
+ RepositoryPolicyText:
+ Version: 3000-10-17 # <--- invalid version
+ Statement:
+ - Effect: Allow
+ Action:
+ - 'ecr:*'
+ Principal:
+ AWS: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:root
+"""
+
default_events_limit = 10
@@ -132,3 +149,79 @@ def test_missing_template_body():
assert exc_info.match('FAIL')
assert not m.exit_args
assert "Either 'template', 'template_body' or 'template_url' is required when the stack does not exist." == m.exit_kwargs['msg']
+
+
+def test_disable_rollback_and_on_failure_defined():
+ m = FakeModule(
+ on_create_failure='DELETE',
+ disable_rollback=True,
+ )
+ with pytest.raises(Exception, message='Expected module to fail with both on_create_failure and disable_rollback defined') as exc_info:
+ cfn_module.create_stack(
+ module=m,
+ stack_params={'TemplateBody': ''},
+ cfn=None,
+ events_limit=default_events_limit
+ )
+ assert exc_info.match('FAIL')
+ assert not m.exit_args
+ assert "You can specify either 'on_create_failure' or 'disable_rollback', but not both." == m.exit_kwargs['msg']
+
+
+def test_on_create_failure_delete(maybe_sleep, placeboify):
+ m = FakeModule(
+ on_create_failure='DELETE',
+ disable_rollback=False,
+ )
+ connection = placeboify.client('cloudformation')
+ params = {
+ 'StackName': 'ansible-test-on-create-failure-delete',
+ 'TemplateBody': failing_yaml_tpl
+ }
+ result = cfn_module.create_stack(m, params, connection, default_events_limit)
+ assert result['changed']
+ assert result['failed']
+ assert len(result['events']) > 1
+ # require that the final recorded stack state was DELETE_COMPLETE
+ # events are retrieved newest-first, so 0 is the latest
+ assert 'DELETE_COMPLETE' in result['events'][0]
+
+
+def test_on_create_failure_rollback(maybe_sleep, placeboify):
+ m = FakeModule(
+ on_create_failure='ROLLBACK',
+ disable_rollback=False,
+ )
+ connection = placeboify.client('cloudformation')
+ params = {
+ 'StackName': 'ansible-test-on-create-failure-rollback',
+ 'TemplateBody': failing_yaml_tpl
+ }
+ result = cfn_module.create_stack(m, params, connection, default_events_limit)
+ assert result['changed']
+ assert result['failed']
+ assert len(result['events']) > 1
+ # require that the final recorded stack state was ROLLBACK_COMPLETE
+ # events are retrieved newest-first, so 0 is the latest
+ assert 'ROLLBACK_COMPLETE' in result['events'][0]
+ connection.delete_stack(StackName=params['StackName'])
+
+
+def test_on_create_failure_do_nothing(maybe_sleep, placeboify):
+ m = FakeModule(
+ on_create_failure='DO_NOTHING',
+ disable_rollback=False,
+ )
+ connection = placeboify.client('cloudformation')
+ params = {
+ 'StackName': 'ansible-test-on-create-failure-do-nothing',
+ 'TemplateBody': failing_yaml_tpl
+ }
+ result = cfn_module.create_stack(m, params, connection, default_events_limit)
+ assert result['changed']
+ assert result['failed']
+ assert len(result['events']) > 1
+ # require that the final recorded stack state was CREATE_FAILED
+ # events are retrieved newest-first, so 0 is the latest
+ assert 'CREATE_FAILED' in result['events'][0]
+ connection.delete_stack(StackName=params['StackName'])