Ansible and the AWS CLI: No module, no problem
Tips on integrating the AWS CLI when Ansible modules are letting you down
If you have picked up Ansible as a tool for managing your AWS cloud environments, then I know how it’s going. Things are going great. Ansible’s rich library of modules for AWS (159 at last count) is enabling you to bash out playbooks for bits of your stack at an alarming rate: EC2, DynamoDB, S3, Route 53, you’ve got it all. You are swimming in idempotent automation that makes your job a breeze. Life is good.
The cracks start to show
That is, until you need to build something you don’t have a module for. For example: your team is building a new service that leverages Aurora clusters. Time for some more automation. You pull up your trusty list of Ansible modules… Hmm. Nothing.
(disclaimer: the rds
module does support creating instances on the Aurora engine, but it is a bit spotty and there isn’t a module for the clusters themselves yet is the point here)
This doesn’t have to be a showstopper. One of the great strengths of AWS is being able to control things through the AWS CLI, and one of the great things about Ansible is how flexible you can be with things like command
to execute shell commands. So we’ll just invoke the AWS CLI from Ansible and create an Aurora cluster that way:
It’s nice — it means we can still leverage Ansible’s configuration management and templating to keep things neat. But, it doesn’t end up quite as nice as usual. I mean, it does crash if the cluster already exists, because it isn’t idempotent. 🙅
We can, however, write a little more Ansible code around the edges of our usage of the AWS CLI to make it more robust and more idempotent.
Filling in the gaps
Here’s what we can to do to soup it up a little:
- first, list all our Aurora clusters with the AWS CLI, storing the result using
register
- take advantage of the fact AWS CLI communicates in JSON to use Ansible’s
from_json
andjson_query
filters to check out the result and work out if the Aurora cluster already exists - use Ansible’s
when
to conditionally run the AWS CLI usingcommand
to create the cluster if it doesn’t exist
Nice, things are looking much better and our Aurora cluster creation is idempotent like the rest of our Ansible.
A note on filtering
This list-parse-create logic works great, but it is important to understand the differences in filtering between some AWS APIs, as it affects whether your Ansible can just ask AWS specifically about the object you want, or if you’ll need to list them all and filter yourself. This solution is not one size fits all! Some APIs have no filtering implemented, some APIs will happily return an empty set when filtering, some will throw an error when filtered if nothing can be found!
I think it is easiest to just illustrate with some examples, see below :)
Happy automating!
Tom
I love automation. This series of articles, Automation with Ansible, is the documenting of some of the Ansible bits ‘n bobs that make my professional life easier when managing software infrastructure.
Check it all out on GitHub, or the other entries in the series: