Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

New module cloudformation_facts #2329

Merged
merged 11 commits into from
Sep 6, 2016
Merged

Conversation

jmenga
Copy link
Contributor

@jmenga jmenga commented May 27, 2016

ISSUE TYPE
  • New Module Pull Request
COMPONENT NAME

cloudformation_facts

ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes -->
ansible 2.1.0.0
  config file =
  configured module search path = Default w/o overrides
SUMMARY

Provides facts about AWS CloudFormation stacks. Note there is another open pull request #1230 however my module has much more functionality.

In its most basic form, it will return stack description and also provides some useful transformations (stack_outputs and stack_parameters in the example below) to make stack outputs and stack parameters easier to work with:

{
        "changed": false,
        "stack_description": {
            "CreationTime": "2016-05-27T02:02:23.997000+00:00",
            "DisableRollback": false,
            "NotificationARNs": [],
            "Parameters": [
                {
                    "ParameterKey": "SomeParameter",
                    "ParameterValue": "sg-abcd1234"
                },
                {
                    "ParameterKey": "DBInstanceClass",
                    "ParameterValue": "db.t2.medium"
                },
                {
                    "ParameterKey": "myVPC",
                    "ParameterValue": "vpc-abcd1234"
                }
            ],
            "Outputs": [
                {
                    "Description": "Stack Name",
                    "OutputKey": "StackName",
                    "OutputValue": "demo-stack"
                },
                {
                    "Description": "Some Output",
                    "OutputKey": "SomeOutput",
                    "OutputValue": "some-output-here"
                }
            ],
            "StackId": "arn:aws:cloudformation:ap-southeast-2:12345678:stack/demo-stack/0dcd0dd0-23af-11e6-bb66-50fae957fce6",
            "StackName": "demo-stack",
            "StackStatus": "CREATE_COMPLETE",
            "Tags": []
        },
        "stack_outputs": {
            "StackName": "demo-stack",
            "SomeOutput": "some-output-here",
        },
        "stack_parameters": {
            "SomeParameter": "sg-abcd1234",
            "DBInstanceClass": "db.t2.medium",
            "myVPC": "vpc-abcd1234"
        }
    }
}

A number of optional parameters can be specified to include the following additional stack information:

  • Stack Policy
  • Stack Template
  • Stack Events
  • Stack Resources

Example Usage:

# Output basic facts
- cloudformation_facts:
    stack_name: demo-stack

# Output all facts
- cloudformation_facts:
    stack_name: demo-stack
    all_facts: true

# Output basic facts + stack resources + stack template
- cloudformation_facts:
    stack_name: demo-stack
    stack_resources: true
    stack_template: true

Example expanded outputs:

{
        "changed": false,
        "stack_description": {
            "CreationTime": "2016-05-27T02:02:23.997000+00:00",
            "DisableRollback": false,
            "NotificationARNs": [],
            "Parameters": [
                {
                    "ParameterKey": "SomeParameter",
                    "ParameterValue": "sg-abcd1234"
                },
                {
                    "ParameterKey": "DBInstanceClass",
                    "ParameterValue": "db.t2.medium"
                },
                {
                    "ParameterKey": "myVPC",
                    "ParameterValue": "vpc-abcd1234"
                }
            ],
            "Outputs": [
                {
                    "Description": "Stack Name",
                    "OutputKey": "StackName",
                    "OutputValue": "demo-stack"
                },
                {
                    "Description": "Some Output",
                    "OutputKey": "SomeOutput",
                    "OutputValue": "some-output-here"
                }
            ],
            "StackId": "arn:aws:cloudformation:ap-southeast-2:12345678:stack/demo-stack/0dcd0dd0-23af-11e6-bb66-50fae957fce6",
            "StackName": "demo-stack",
            "StackStatus": "CREATE_COMPLETE",
            "Tags": []
        },
        # This is a dictionary mapping OutputKey values to OutputValue values
        "stack_outputs": {
            "StackName": "demo-stack",
            "SomeOutput": "some-output-here",
        },
        # This is a dictionary mapping ParameterKey values to ParameterValue values
        "stack_parameters": {
            "SomeParameter": "sg-abcd1234",
            "DBInstanceClass": "db.t2.medium",
            "myVPC": "vpc-abcd1234"
        },
       "stack_events": [
            {
                "EventId": "cef9c330-23b0-11e6-9836-50fae957fc4a",
                "LogicalResourceId": "my-rds",
                "PhysicalResourceId": "arn:aws:cloudformation:ap-southeast-2:12345678:stack/demo-stack/0dcd0dd0-23af-11e6-bb66-50fae957fce6",
                "ResourceStatus": "CREATE_COMPLETE",
                "ResourceType": "AWS::CloudFormation::Stack",
                "StackId": "arn:aws:cloudformation:ap-southeast-2:12345678:stack/demo-stack/0dcd0dd0-23af-11e6-bb66-50fae957fce6",
                "StackName": "demo-stack",
                "Timestamp": "2016-05-27T02:14:57.439000+00:00"
            },
           ....
        ],
       "stack_policy": {},
       "stack_resource_list": [
            {
                "LogicalResourceId": "DBinstance",
                "PhysicalResourceId": "my-rds",
                "ResourceStatus": "CREATE_COMPLETE",
                "ResourceType": "AWS::RDS::DBInstance",
                "StackId": "arn:aws:cloudformation:ap-southeast-2:12345678:stack/demo-stack/0dcd0dd0-23af-11e6-bb66-50fae957fce6",
                "StackName": "demo-stack",
                "Timestamp": "2016-05-27T02:14:55.879000+00:00"
            },
            ...
       ],
       # This is a dictionary mapping LogicalResourceID values to PhysicalResourceID values
       "stack_resources": {
            "DBinstance": "my-rds",
            ...
       },
       "stack_template": {
            "AWSTemplateFormatVersion": "2010-09-09",
            "Parameters": {
                ....
            },
            "Resources": {
                ....
            },
           ...  
     }
}

@gregdek gregdek added the cloud label May 27, 2016
@gregdek
Copy link
Contributor

gregdek commented May 27, 2016

Thanks @jmenga for this PR. This PR requires revisions, either because it fails to build or by reviewer request. Please make the suggested revisions. When you are done, please comment with text 'ready_for_review' and we will put this PR back into review.

[This message brought to you by your friendly Ansibull-bot.]

@jmenga
Copy link
Contributor Author

jmenga commented May 27, 2016

ready_for_review

@gregdek
Copy link
Contributor

gregdek commented May 27, 2016

Thanks @jmenga for this new module. When this module receives 'shipit' comments from two community members and any 'needs_revision' comments have been resolved, we will mark for inclusion.

[This message brought to you by your friendly Ansibull-bot.]

@viper233
Copy link
Contributor

@mixja I don't have ~/.boto set up, only AWS_REGION set in my environment.

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: botocore.exceptions.NoRegionError: You must specify a region.
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_K7IZmy/ansible_module_cloudformation_facts.py\", line 264, in <module>\n    main()\n  File \"/tmp/ansible_K7IZmy/ansible_module_cloudformation_facts.py\", line 234, in main\n    service_mgr = CloudFormationServiceManager(module)\n  File \"/tmp/ansible_K7IZmy/ansible_module_cloudformation_facts.py\", line 150, in __init__\n    self.client = boto3.client('cloudformation')\n  File \"/home/stephen/.local/lib/python2.7/site-packages/boto3/__init__.py\", line 79, in client\n    return _get_default_session().client(*args, **kwargs)\n  File \"/home/stephen/.local/lib/python2.7/site-packages/boto3/session.py\", line 200, in client\n    aws_session_token=aws_session_token, config=config)\n  File \"/usr/local/lib/python2.7/dist-packages/botocore/session.py\", line 796, in create_client\n    client_config=config, api_version=api_version)\n  File \"/usr/local/lib/python2.7/dist-packages/botocore/client.py\", line 62, in create_client\n    verify, credentials, scoped_config, client_config)\n  File \"/usr/local/lib/python2.7/dist-packages/botocore/client.py\", line 227, in _get_client_args\n    endpoint_url)\n  File \"/usr/local/lib/python2.7/dist-packages/botocore/client.py\", line 117, in _get_signature_version_and_region\n    service_model.endpoint_prefix, region_name, scheme=scheme)\n  File \"/usr/local/lib/python2.7/dist-packages/botocore/regions.py\", line 70, in construct_endpoint\n    raise NoRegionError()\nbotocore.exceptions.NoRegionError: You must specify a region.\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}

I had to add the region to the client call

self.client = boto3.client('cloudformation', region_name='us-west-2')

I saw a commit with these details was removed. I noticed these modules were set up the same way

  • ansible/modules/extras/cloud/amazon/ecs_cluster.py
  • ansible/modules/extras/cloud/amazon/ecs_service_facts.py
  • ansible/modules/extras/cloud/amazon/ecs_service.py

though I haven't tried using them.

$ ansible --version
ansible 2.2.0 (devel 844b415066) last updated 2016/05/31 14:35:26 (GMT -700)

@mixja
Copy link

mixja commented May 31, 2016

@viper233 - as per Boto3 docs you can use AWS_DEFAULT_REGION (AWS_REGION is not listed as a support variable) to set the region.

I will update the documentation of the module to reflect this needs to be set.

EDIT: updated incorrect Boto3 link above

@viper233
Copy link
Contributor

I pass the region in as a parameter.

# testing.yml
---
- hosts: localhost
  connection: local
  name: get a cloudformation stack facts
  gather_facts: False

  vars:
    - aws_region: "{{ lookup('env', 'AWS_REGION') }}"
    - aws_access_key: "{{ lookup('env', 'AWS_ACCESS_KEY_ID') }}"
    - aws_secret_key: "{{ lookup('env', 'AWS_SECRET_ACCESS_KEY') }}"

  tasks:
    - name: Print AWS region
      debug:
        var: aws_region

    - name: Get the cloudstack facts
      cloudformation_facts:
        stack_name: my_stack
        aws_access_key: "{{ aws_access_key }}"
        aws_secret_key: "{{ aws_secret_key }}"
        region: "{{ aws_region }}"
        stack_resources: true
      register: vpc

@mixja
Copy link

mixja commented May 31, 2016

@viper233 - OK I see the problem, I will revise the module to support this style of configuration

@viper233
Copy link
Contributor

Is this also the case for the other modules too? I can try and test them later today and submit a PR

@mixja
Copy link

mixja commented Jun 9, 2016

@viper233 - sorry not sure which other modules you are referring to. I have added support for specifying AWS connection/region parameters explicitly.

@viper233
Copy link
Contributor

viper233 commented Jun 9, 2016

I did a grep on the modules directories to see if there were any other modules using the boto3.client call, these were the others that I came up with.

  • ansible/modules/extras/cloud/amazon/ecs_cluster.py
  • ansible/modules/extras/cloud/amazon/ecs_service_facts.py
  • ansible/modules/extras/cloud/amazon/ecs_service.py

I haven't tested these modules yet. It's something I should do in my spare time.

@Fluro
Copy link

Fluro commented Jul 5, 2016

shipit

1 similar comment
@simonbrady
Copy link

shipit

@mixja
Copy link

mixja commented Aug 19, 2016

@gregdek - can you reattempt the Travis CI build as from the logs it looks like a build issue unrelated to the module code.

@gregdek
Copy link
Contributor

gregdek commented Aug 19, 2016

@jmenga this is likely due to the age of the PR; please rebase against the latest devel. When you've done so, ping me and we'll put this module into the new module review meeting, since it has the necessary shipits.

@mixja
Copy link

mixja commented Aug 19, 2016

Thanks @gregdek - rebased the PR and all checks pass

description:
- Gets information about an AWS CloudFormation stack
dependencies:
- boto3>=1.0.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This documentation field needs to be requirements, not dependencies.

I think that boto3 requires python >= 2.6? If so, need to mention python >= 2.6 as a requirement as well.


# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.ec2 import *
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note -- we aren't requiring it yet but you don't have to treat these specially anymore. They can go at the top of the file with the other imports and you can import the specific things you need instead of doing a wildcard import.

@abadger
Copy link
Contributor

abadger commented Aug 24, 2016

needs_revision

@gregdek
Copy link
Contributor

gregdek commented Aug 24, 2016

Thanks @jmenga for this PR. This PR requires revisions, either because it fails to build or by reviewer request. Please make the suggested revisions. When you are done, please comment with text 'ready_for_review' and we will put this PR back into review.

[This message brought to you by your friendly Ansibull-bot.]

@mixja
Copy link

mixja commented Aug 26, 2016

ready_for_review

response = self.client.get_template(StackName=stack_name)
return response.get('TemplateBody')
except Exception as e:
self.module.fail_json(msg="Error getting stack template - " + str(e))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For all these fails, can you include the traceback like so:

try:
    # some stuff
except Exception as e:
    self.module.fail_json(msg="Error getting stack template - " + str(e), exception=traceback.format_exc(e))

And import traceback at the top of the file?

@ryansb
Copy link
Contributor

ryansb commented Aug 30, 2016

Other than the exception handling, this looks good.

@jmenga
Copy link
Contributor Author

jmenga commented Sep 6, 2016

ready_for_review

@gregdek
Copy link
Contributor

gregdek commented Sep 6, 2016

Thanks @jmenga for this new module. When this module receives 'shipit' comments from two community members and any 'needs_revision' comments have been resolved, we will mark for inclusion.

[This message brought to you by your friendly Ansibull-bot.]

@ryansb
Copy link
Contributor

ryansb commented Sep 6, 2016

Looks great - I'm going to commit a fix to one of the boto3 connection creation manually. There is a problem with using this module with profiles.

@ryansb ryansb merged commit 1f79c35 into ansible:devel Sep 6, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants