CLI/workflow lib around for management of CloudFormation stacks
Project description
.. image:: https://img.shields.io/pypi/v/tropostack.svg :target: https://pypi.org/project/tropostack/ :alt: pypi version
.. image:: https://img.shields.io/travis/gtie/tropostack/master.svg?label=Build :target: https://travis-ci.org/gtie/tropostack :alt: travis build status
About
Tropostack is a CLI/workflow library that simplifies the creation and management
of CloudFormation <https://aws.amazon.com/cloudformation/>
_ stacks, based on
the excellent Troposphere Project <https://github.com/cloudtools/troposphere>
_.
Tropostack features:
- Single stack template = single executable Python file = single CLI
- Support for different configuration and CLI plugins
- A collection of generic commands available to each stack (e.g.
create
) - Support for user-defined CLI commands (e.g.
upscale
) - Helper routines (e.g. locate the newest matching AMI)
Docs
Full docs are at https://tropostack.readthedocs.io/en/latest/
Installation
.. code:: sh
$ pip install tropostack
Or, you can use setup.py to install from a cloned repository:
.. code:: sh
$ python setup.py install
First stack
You use tropostack
as a library to:
- Consisteny define CloudFormation templates in Python code
- Have a CLI around each stack definition, enabling it to live as a standalone executable
Here is a minimalistic example of a stack that creates an S3 bucket, and exports the ARN as an Output:
.. code-block:: python
#!/usr/bin/env python3
from troposphere import s3
from troposphere import Output, Export, Sub, GetAtt
from tropostack.base import InlineConfStack
from tropostack.cli import InlineConfCLI
class MyS3BucketStack(InlineConfStack):
# Name of the stack
BASE_NAME = 'my-s3-bucket-stack'
# Define configuration values for the stack
CONF = {
# Region is always explicitly required
'region': 'eu-west-1',
# Prefix the bucket name with the account ID
'bucket_name': Sub('${AWS::AccountId}-my-first-tropostack-bucket')
}
# Stack Resources are defined as class properties prefixed with 'r_'
@property
def r_bucket(self):
return s3.Bucket(
'MyBucketResource',
BucketName=self.conf['bucket_name']
)
# Stack Outputs are defined as class properties prefixed with 'o_'
@property
def o_bucket_arn(self):
_id = 'BucketArn'
return Output(
_id,
Description='The ARN of the S3 bucket',
Value=GetAtt(self.r_bucket, 'Arn'),
# We're exporting the output as <StackName>-<OutputId>
# Other stacks can read the output relying on the same convention
Export=Export(Sub("${AWS::StackName}-%s" % _id))
)
if __name__ == '__main__':
# Wrap the stack in a CLI and run it
cli = InlineConfCLI(MyS3BucketStack)
cli.run()
The above already gives you a usable CLI around your stack definition.
Assuming you put it inside an executable file called s3_minimal.py
, you'd be able to call it already:
.. code-block:: bash
$ ./s3_minimal.py -h usage: s3_minimal.py [-h] {apply,create,delete,outputs,print,update,validate}
positional arguments: {apply,create,delete,outputs,print,update,validate}
optional arguments: -h, --help show this help message and exit
You can now inspect the "raw" CloudFormation code generated by the stack:
.. code-block:: yaml
$ ./s3_minimal.py print Outputs: BucketArn: Description: The ARN of the S3 bucket Export: Name: !Sub '${AWS::StackName}-BucketArn' Value: !GetAtt 'MyBucketResource.Arn' Resources: MyBucketResource: Properties: BucketName: !Sub '${AWS::AccountId}-my-first-tropostack-bucket' Type: AWS::S3::Bucket
Assuming
AWS credentials are present <https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#configuring-credentials>
_
in the environment, we can now fire up stack that would create our S3 bucket:
.. code-block:: bash
$ ./s3_minimal.py create Stack creation initiated for: arn:aws:cloudformation:eu-west-1:472799024263:stack/my-s3-bucket-stack/dd5e93c0-225c-11ea-93d8-0641c159a77a TIMESTAMP (UTC) RESOURCE TYPE RESOURCE ID STATUS REASON 2019-12-19 12:41:23 AWS::CloudFormation::Stack my-s3-bucket-stack CREATE_IN_PROGRESS User Initiated 2019-12-19 12:41:26 AWS::S3::Bucket MyBucketResource CREATE_IN_PROGRESS 2019-12-19 12:41:27 AWS::S3::Bucket MyBucketResource CREATE_IN_PROGRESS Resource creation Initiated 2019-12-19 12:41:48 AWS::S3::Bucket MyBucketResource CREATE_COMPLETE 2019-12-19 12:41:50 AWS::CloudFormation::Stack my-s3-bucket-stack CREATE_COMPLETE
We can also inspect the stack Outputs - in this case, the ARN of the bucket:
.. code-block:: bash
$ ./s3_minimal.py outputs Stack is in status: CREATE_COMPLETE OutputKey OutputValue Description ExportName
BucketArn arn:aws:s3:::472799024263-my-first-tropostack-bucket The ARN of the S3 bucket my-s3-bucket-stack-BucketArn
Finally, we can clean up and have our stack deleted:
.. code-block:: bash
$ ./s3_minimal.py delete Destroy initiated for stack: my-s3-bucket-stack TIMESTAMP (UTC) RESOURCE TYPE RESOURCE ID STATUS REASON 2019-12-19 12:44:59 AWS::CloudFormation::Stack my-s3-bucket-stack DELETE_IN_PROGRESS User Initiated Stack is gone: my-s3-bucket-stack (An error occurred (ValidationError) when calling the DescribeStackEvents operation: Stack [my-s3-bucket-stack] does not exist)
Stock commands
While the CLI can be expanded/customized for each individual tropostack, there are several subcommands that come out of the box:
print
- prints the resulting CloudFormation YAML to the screenvalidate
- Sends the CloudFormation template to the AWS API for validation, and reports back resultcreate
- Initiates the stack creation (should only be used if the stack does not exist yet)update
- Updates an existing stack (should only be used if the stack exists)apply
- Idempotently updates or creates a stack, based on whether it exists or notoutputs
- Shows the outputs of an existing stackdelete
- Deletes an existing stack
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.