Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add macro deploy #1701

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions macro/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
BUCKET=macro-template-default-831650818513-us-east-1

macro:
pip install -r source/requirements.txt -t source
aws cloudformation package --template-file template.yaml --s3-bucket $(BUCKET) --output-template-file template.output
aws cloudformation deploy --template-file template.output --stack-name TroposphereMacro --capabilities CAPABILITY_IAM
rm -rf template.output

sample:
aws cloudformation deploy --stack-name template-macro-example --template-file example.py --parameter-overrides InstanceName=NewName
76 changes: 76 additions & 0 deletions macro/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Troposphere Macro

The `Troposphere` macro adds the ability to create CloudFormation resources from troposphere stacks.

# How to install and use the Macro in your AWS account

## Deploying

1. You will need an S3 bucket to store the CloudFormation artifacts:
* If you don't have one already, create one with `aws s3 mb s3://<bucket name>`

2. Install all python requirements

```shell
pip install -r source/requirements.txt -t source
```

3. Package the CloudFormation template. The provided template uses [the AWS Serverless Application Model](https://aws.amazon.com/about-aws/whats-new/2016/11/introducing-the-aws-serverless-application-model/) so must be transformed before you can deploy it.

```shell
aws cloudformation package \
--template-file template.yaml \
--s3-bucket <your bucket name here> \
--output-template-file template.output
```

4. Deploy the packaged CloudFormation template to a CloudFormation stack:

```shell
aws cloudformation deploy \
--stack-name troposphere-macro \
--template-file template.output \
--capabilities CAPABILITY_IAM
```

5. To test out the macro's capabilities, try launching the provided example template:

```shell
aws cloudformation deploy \
--stack-name template-macro-example \
--template-file example.py
```

## Usage

Just add your resources to macro_template object, the template object is created by macro itself.
You can provide your troposphere code in Troposphere tag.

```
Transform: [Troposhere]
Description: Example Macro Troposhere.

Parameters:
InstanceName:
Type: String
Default: "MyInstance"
ImageId:
Type: String
Default: "ami-951945d0"
InstanceType:
Type: String
Default: "t1.micro"

Troposhere: |
from troposphere import Ref
import troposphere.ec2 as ec2

instance = ec2.Instance('MyInstance')

instance.ImageId = Ref('ImageId')
instance.InstanceType = Ref('InstanceType')
instance.Tags = ec2.Tags(Name = Ref('InstanceName'))

macro_template.add_resource(instance)
```

30 changes: 30 additions & 0 deletions macro/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Transform: [Troposhere]
Description: Example Macro Troposhere.

Parameters:
InstanceName:
Type: String
Default: "MyInstance"
ImageId:
Type: String
Default: "ami-eb0c7791"
InstanceType:
Type: String
Default: "t1.micro"

Troposhere: |
from troposphere import Ref
import troposphere.ec2 as ec2

list_instances = ["One", "Two", "Three", "Four"]

instance_name = macro_parameters["InstanceName"]

for el in list_instances:
instance = ec2.Instance('MyInstance{}'.format(el))

instance.ImageId = Ref('ImageId')
instance.InstanceType = Ref('InstanceType')
instance.Tags = ec2.Tags(Name = instance_name + el)

macro_template.add_resource(instance)
33 changes: 33 additions & 0 deletions macro/source/macro.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from troposphere.template_generator import TemplateGenerator
import traceback

def handle_template(event):
template = event['fragment']
macro_parameters = event['templateParameterValues']

troposphere_code = template["Troposhere"]
del template["Troposhere"]

macro_template = TemplateGenerator(template)
exec(troposphere_code)

return macro_template.to_dict()

def handler(event, context):
request_id = event['requestId']

macro_response = {
'status': 'success',
'requestId': request_id
}

try:
macro_response['fragment'] = handle_template(event)
except Exception as e:
traceback.print_exc()
macro_response['status'] = 'failure'
macro_response['errorMessage'] = str(e)

return macro_response


1 change: 1 addition & 0 deletions macro/source/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
troposphere[policy]
40 changes: 40 additions & 0 deletions macro/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Transform: AWS::Serverless-2016-10-31

Resources:
TransformExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'logs:*'
Resource: 'arn:aws:logs:*:*:*'

MacroFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: python3.6
CodeUri: source/
Handler: macro.handler
Role: !GetAtt TransformExecutionRole.Arn
Timeout: 300

Macro:
Type: AWS::CloudFormation::Macro
Properties:
Name: Troposhere
FunctionName: !GetAtt MacroFunction.Arn