As an example of how to use this tool to manage infrastructure through configuration files this directory contains a small example with two stacks.
The first stack is named templates
and contains only one resource: an S3 bucket used to backup the CloudFormation templates generated by humidifier
.
The second stack is named vpc
and contains resources necessary to the creation of VPC, the assignment of the various IPs to subnets, the route table and associations, the NAT gateway for the internal subnets, as well as a VPC endpoint for hitting S3 without going through the NATs. The VPC design itself is taken from this article.
To see this example in action, you can run the ./humidifer
script in this directory. Here are a couple of commands to get you started:
- Running the usage command
$ ./humidifier
Commands:
humidifier change [?stack] # Create changesets for one or all stacks
humidifier deploy [?stack] [*parameters] # Update one or all stacks
humidifier display [stack] [?pattern] # Display the CloudFormation JSON for a given stack
humidifier help [COMMAND] # Describe available commands or one specific command
humidifier stacks # List the stacks known to Humidifier
humidifier upload [?stack] # Upload one or all stacks to S3
humidifier validate [?stack] # Validate that one or all stacks are valid with CloudFormation
Options:
-p, [--aws-profile=AWS_PROFILE] # The AWS profile to authenticate with
-d, [--debug=DEBUG] # Sets up debug mode
- Running the display command
$ ./humidifier display templates
humidifier display v3.2.0
📄 Displaying templates
{
"Description": "Resources for templates",
"Resources": {
"TemplateBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "[mycompany]-templates",
"VersioningConfiguration": {
"Status": "Enabled"
}
}
}
}
}
✨ Done in 0.00s.
- Using the
*_id
shorthand
A lot of resources within AWS accept *_id
properties which should be direct references to other resources. humidifier
handles that for you if you pass whatever is in place of *
as the key, with the logical resource name as the value. For example, looking at network_acl_entries.yml, you'll notice that we're passing a network_acl
property for each entry that is just the name of the associated Network ACL. In reality NetworkAclEntry resources accept a network_acl_id
property. Internally, humidifier
handles this by automatically converting those into { "Ref" => * }
objects in the JSON. You can verify by viewing the output from the ./humidifier display vpc
command.
- Referencing attributes of other resources
Looking at nat_gateways.yml, you'll notice that we're passing an eip
property for each NAT that is just the name of the associated EIP resource. In reality, NatGateway resources accept an allocation_id
property, so in the mapping for NATs in the humidifier script, we map that eip
property to a valid allocation_id
property like so:
Humidifier.configure do |config|
config.map :nat_gateways, to: 'EC2::NatGateway' do
attribute :eip do |eip_name|
{ allocation_id: Humidifier.fn.get_att([eip_name, 'AllocationId']) }
end
end
end
- Reusing shared mappers
In the humidifier script, you'll notice that we're using the NameToTag
mapper in a couple of places. The logic that it implements if effectively to add a Name
tag to resources based on their logical resource name from within the CloudFormation stack. This makes the developer experience a bit easier when viewing from the UI or CLI output. Since all of the resources will have a logical resource name and most of them have the ability to add tags, this logic doesn't have to be duplicated across multiple mappers.