Repository: ansible/ansible

Issue:
cloudformation template_parameters not working
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
cloudformation module

##### ANSIBLE VERSION
```
ansible 2.3.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.13 (default, Feb 11 2017, 12:22:40) [GCC 6.3.1 20170109]
```

##### CONFIGURATION
No changes to default ansible.cfg

##### OS / ENVIRONMENT
Arch Linux

##### SUMMARY
When running a playbook with the cloudformation module and specifying template_parameters, an error is thrown.

##### STEPS TO REPRODUCE
Add template_parameters section to cloudformation task like so:
```
- name: Run CloudFormation stack
      cloudformation:
        stack_name: "{{ project }}"
        region: "{{ region }}"
        state: "present"
        template: "../templates/stack.yaml"
        template_parameters:
          VpcdId: "{{ VpcId }}"
        tags:
          CostCentre: "{{ cost_centre }}"
      register: "{{ project }}"
```

##### EXPECTED RESULTS
Expect the template_parameters to be passed to the template file.

##### ACTUAL RESULTS
```
"msg": "<class 'Exception'>: An error occurred (ValidationError) when calling the CreateStack operation: Parameter values specified for a template which does not require them."
```

cloudformation template_parameters not working
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
cloudformation module

##### ANSIBLE VERSION
```
ansible 2.3.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.13 (default, Feb 11 2017, 12:22:40) [GCC 6.3.1 20170109]
```

##### CONFIGURATION
No changes to default ansible.cfg

##### OS / ENVIRONMENT
Arch Linux

##### SUMMARY
When running a playbook with the cloudformation module and specifying template_parameters, an error is thrown.

##### STEPS TO REPRODUCE
Add template_parameters section to cloudformation task like so:
```
- name: Run CloudFormation stack
      cloudformation:
        stack_name: "{{ project }}"
        region: "{{ region }}"
        state: "present"
        template: "../templates/stack.yaml"
        template_parameters:
          VpcdId: "{{ VpcId }}"
        tags:
          CostCentre: "{{ cost_centre }}"
      register: "{{ project }}"
```

##### EXPECTED RESULTS
Expect the template_parameters to be passed to the template file.

##### ACTUAL RESULTS
```
"msg": "<class 'Exception'>: An error occurred (ValidationError) when calling the CreateStack operation: Parameter values specified for a template which does not require them."
```



Discussion:
cc @tedder @ryansb
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Can you share your template? needs_info
Hi s-hertel, thanks for getting back. The template is below.

```
#jinja2:lstrip_blocks:False,trim_blocks:False
---
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: '{{ project }}-sg'
      GroupDescription: 'Allow http to client host'
      VpcId: '{{ VpcId }}'
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
```
You need a `Parameters` section.

Leaving this ticket open so I can catch the exception.
Ah. Thanks for that tedder! Everything works with the following update:
```
#jinja2:lstrip_blocks:False,trim_blocks:False
---
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  VpcId:
    Type: String

Resources:
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: 'multi-az-vpc-sg'
      GroupDescription: 'Allow http to client host'
      VpcId:
        Ref: VpcId
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
```
cc @jsmartin
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
cc @tedder @ryansb
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Can you share your template? needs_info
Hi s-hertel, thanks for getting back. The template is below.

```
#jinja2:lstrip_blocks:False,trim_blocks:False
---
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: '{{ project }}-sg'
      GroupDescription: 'Allow http to client host'
      VpcId: '{{ VpcId }}'
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
```
You need a `Parameters` section.

Leaving this ticket open so I can catch the exception.
Ah. Thanks for that tedder! Everything works with the following update:
```
#jinja2:lstrip_blocks:False,trim_blocks:False
---
AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  VpcId:
    Type: String

Resources:
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: 'multi-az-vpc-sg'
      GroupDescription: 'Allow http to client host'
      VpcId:
        Ref: VpcId
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
```
cc @jsmartin
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/cloud/amazon/cloudformation.py b/lib/ansible/modules/cloud/amazon/cloudformation.py
--- a/lib/ansible/modules/cloud/amazon/cloudformation.py
+++ b/lib/ansible/modules/cloud/amazon/cloudformation.py
@@ -309,7 +309,7 @@ def create_stack(module, stack_params, cfn):
         result = stack_operation(cfn, stack_params['StackName'], 'CREATE')
     except Exception as err:
         error_msg = boto_exception(err)
-        module.fail_json(msg=error_msg)
+        module.fail_json(msg="Failed to create stack {0}: {1}.".format(stack_params.get('StackName'), error_msg), exception=traceback.format_exc())
     if not result:
         module.fail_json(msg="empty result")
     return result
@@ -349,7 +349,7 @@ def create_changeset(module, stack_params, cfn):
         if 'No updates are to be performed.' in error_msg:
             result = dict(changed=False, output='Stack is already up-to-date.')
         else:
-            module.fail_json(msg=error_msg)
+            module.fail_json(msg="Failed to create change set: {0}".format(error_msg), exception=traceback.format_exc())
 
     if not result:
         module.fail_json(msg="empty result")
@@ -371,7 +371,7 @@ def update_stack(module, stack_params, cfn):
         if 'No updates are to be performed.' in error_msg:
             result = dict(changed=False, output='Stack is already up-to-date.')
         else:
-            module.fail_json(msg=error_msg)
+            module.fail_json(msg="Failed to update stack {0}: {1}".format(stack_params.get('StackName'), error_msg), exception=traceback.format_exc())
     if not result:
         module.fail_json(msg="empty result")
     return result


Test patch: