Terraform testing thoughts
As your terraform code grows in both size and complexity you should invest in tests and other ways to ensure everything is doing exactly what you intended. Although there are existing ways to exercise parts of your code I think Terraform is currently missing an important part of testing functionality, and I hope by the end of this post you’ll agree.
<tl;dr>I want puppet catalog compile testing in terraform</tl;dr>
Our current terraform testing process looks a lot like this:
- precommit hooks to ensure the code is formatted and valid before it’s checked in
- run
terraform plan
andapply
to ensure the code actually works - execute a sparse collection of AWSSpec / InSpec tests against the created resources
- Visually check the AWS Console to ensure everything “looks correct”
We ensure the code is all syntactically validate (and pretty)
before it’s checked in. We then run a plan
, which often finds
issues with module paths, names and such, and then the slow, all
encompassing, and cost increasing apply
happens. And then you
spot an unexpanded variable. Or that something didn’t get included
correctly with a count
.
I think there is a missed opportunity to add a separate phase, between
plan
and apply
above, to expose the compiled plan in a easy to
integrate format such as JSON or YAML. This would allow existing testing
tools, and things like custom rspec matchers and cucumber test cases, to
verify your code before progressing to the often slow, and cash
consuming, apply
phase. There are a number of things you could
usefully test in a serialised plan output. Are your “fake if” count
s
doing what you expect? Are those nested data structures translating to
all the tags you expect? How about the stringified splats and local
composite variables? And what are the actual values hidden behind those
computed
properties? All of this would be visible at this stage. Having these
tests would allow you to catch a lot of more subtle logic issues before you
invoke the big hammer of actually creating resources.
I’m far from the first person to request this and upstream have been
fair and considerate
but it’s not something that’s on the short term road map. Work arounds do exist
but they all have expensive limitations. The current plan file is in a
binary format that isn’t guaranteed to be backwards compatible to external
clients. Writing a plan output parser is possible but “a tool like this is very
likely to be broken by future Terraform releases, since we don’t consider the
human-oriented plan output to be a compatibility constraint” and hooking the
plan
generation code, an approach taken by palantir/tfjson
will be a constant re-investment as terraforms core rapidly changes.
Adding a way to publish the plan in an easy to process way would allow many other testing tools and approaches to bloom and I hope I’ve managed to convince you that it’d be a great addition to terraform.