A couple of months ago, the excellent post “Infrastructure as Code can prevent technical debt” has been published. More recently Tom Howarth wrote about the principles and success of DevOps and CI/CD. A very popular tool to provision resources especially in a multi-cloud environment is Terraform. And new features of Terraform 0.12 continue to increase the developers productivity. In this article we will look at some great new features and explain why it will help developers in their daily work.
Context rich error messages
Let’s start with something which is not so obvious: Context-rich error messages. As with all developer tools, they need to learn the principles and syntax of the programming language. Practice makes perfect and trial and error is often the way of learning. It’s very helpful to have meaningful error messages to get direct feedback.
In release 0.12 of Terraform, errors are presented with much more context than before. With the new version, error messages presents the line number of the code causing the problem, shows variables that are related to the error and shows potential solutions. In previous versions, the way errors lacked contextual information and meaning, so developers were in the dark as to the cause of the error and possible solutions.
As seen in the screenshot above Terraform 0.12 improves the levels of feedback in case of (human) mistake. It’s much less frustrating for developers: no need to dig into a big chunk of logs to find the problem. Developers get clear, quick and proper feedback so they can fix their issues without leaving the console.
Better support for operators & reduce repeated code
When writing Terraform scripts, developers want to do it in an easy and constructive way. Every programming language has “common patterns” to write code like variables, operators, loops, lists, maps and more. Terraform versions prior to version 0.12 did not support these common patterns. Release 0.12 does support them and aligns with other scripting and programming languages. So developers who, for example, also write Python scripts, can benefit from these improvements immediately.
A simple piece of code to clarify the new feature.
The first code snippet is based on Terraform version 0.11 and the second one is supported by Terraform version 0.12.
If you want to output a “dynamic value” (a value which is not hardcoded in your scripts), you had to use a “wildcard” character (the * sign). In this case, it produces a list of values which are all included in the output.
Using this notation (syntax) it acts like a “filter” to select which items should be included in the output. Terraform 0.12 improves the readability of this piece of code like the following:
It now uses a decent “for loop” to fetch and select the values for the output variable. The code is much cleaner and easier to understand. It immediately shows that the output consists of a list of items and not a single value. In the previous versions of Terraform, the * sign is easy to overlook. In case you missed it, the value of the output would be completely different. Most of the time, these kind of “output variables” are being used in different places (scripts) so the easier to write this, the better.
Re-usability of the code by other developers is improved since the Terraform scripts are structured in a better way. Write less code and do more. Most developers are familiar with the principles of DRY: Do Not Repeat Yourself. From a programming perspective, it means: do not repeat code. It’s more likely to have errors in code that is repeated. Also, more code to maintain takes more time. Developers can also be confused about similar blocks of code since it is difficult to find the correct version of it. Terraform 0.12 follows this principle now better than before, increasing re-usability of code and common functions across teams.
A lot of popular programming languages support linting of the source code. So does Terraform. Linting helps you quickly find any syntax errors and other code validation errors in your Terraform scripts. Lint is available as a plugin for a lot of source code editors. For example, the Linter Terraform Syntax plugin for Atom. It works very well with the latest version of Terraform.
One great improvement of recent implementations of Terraform Lint compared to older version is the possibility to catch errors before the Terraform scripts are put into action (e.g fired the script to create the desired resources). It can just scan and check source code as soon as a developer saves the Terraform script.
Consider the following example: Terraform Lint can check if a specific version of a Virtual Machine in AWS exists or not. Terraform Lint can detect it based upon the script itself, even before applying the scripts. This way, a lot of time is saved since applying a plan can take several minutes.
One other big advantage is the saving of costs: when the desired resources are not actually created in the Cloud, no costs occur. Even if it’s just a matter of minutes, when considering a large number of developers, testing out the scripts multiple times a day incurs some costs. Also, sometime people forget to clean up their unused Cloud resources. For example: a lot of people forget to clean up load balancers, while still being charged for them. The costs for unused resources do not contribute in any way to a business feature. From this perspective, again a good reason to use Terraform Lint.
Developers hate to test things manually, especially if that has to be done multiple times. Once you have to do something twice, it’s time to automate it. Luckily Terraform also provides a way to write unit tests. Terraform utilizes a testing framework for unit tests. Developers can use their existing unit testing skills to write unit tests for Terraform.
Unit tests are written in great isolation since those unit tests do not require any network connection. In fact, they can quickly be fired on a local developer machine after each piece of business logic is finished.
The procedure for writing unit tests for Terraform follows the same setup and conventions of writing any Go unit tests. Any developer familiar with the Go programming language can easily write unit tests for Terraform. Again this improves the productivity of developers with Terraform.
Rendering of plans and state
Another great feature of the most recent release is the structured rendering of plans and state. Plans show the intended resources which are to be created. As soon as a plan is executed (called applied), the resources are created. Terraform keeps the current state of the resources. The state is saved in a plain text file called a Terraform state file.
Since release 0.12 the output can also be displayed and saved in a JSON formatted file. JSON files can be read and interpreted better than plain text files since JSON follows a standard format. See the following screenshots for the “plain text” version of a state file and the JSON formatted version.
Developers can easily read it and decide to proceed or not. Computers and other tools can also interpret the JSON output to validate it and do more checks. For example the Compliance as Code tool Open Policy Agent (OPA) can check the intended resources to verify if those are all compliant. Checks done at a very early stage really helps catching errors and other problems before the scripts are being used to bring stuff in production. Don’t go live with unforeseen errors. It all contributes to the “shift left” principle.
Hashicorp is well on its way to continuously improve Terraform to help developers speed up the delivery of their applications.
In my opinion it really lowers the barrier to effectively practice IaC tools and the new features greatly improve the adoption of this way of working. In the end release cycles will be shorter and thus business features delivered faster and in a more controlled and consistent way. All of this makes the journey to the Cloud a lot easier.
Summarized: developer productivity got a big boost since version Terraform 0.12. Can’t wait to see what’s next.