Now that we have a problem to solve and a list of requirements the tool that should solve the problem, we can go into the specifics of the different existing tools.
Which tools exist for infrastructure provisioning?
Scripting
Almost every cloud provider has an API, and if there is an API, you can script it. You could also go beyond a single script and develop a small-focused tool just for your company to create environments. The disadvantages are: more software to develop and support in-house.
Configuration management
Most configuration management tools already have a way to create cloud resources. Chef has Chef provisioning, which allows you to write recipes that define, not entities on a single server, but multiple servers and components, such as security groups of AWS and networking parts. There are also Puppet modules which wrap cloud APIs into Puppet resources. Ansible also has modules to support providers, such as AWS, OpenStack, and others.
While the idea of using a single tool for both levels: high complete infrastructure definition and inside-a-server configuration, is tempting, it has some drawbacks. One of them is lack of support for many required services and the immaturity of these solutions in general.
Also, the ways to use these tools for this purpose are kind of ambiguous. There are no well-defined workflows. Let's take AWS as an example. The recommended way to set up a firewall in AWS environment is to use security groups (SGs). SGs are a separate entity, which are available via web interface or API.
What should you do if you want to create an AWS security group that allows connections from an app server to a database server? Should you put this code a database package or an application package? An AWS security group clearly doesn't belong to either of them.
The only meaningful solution is to create a separate package which is dedicated to creating the security groups and performs searches against the nodes API to define inbound and outbound rules for these groups.
It's also unclear from where to execute this kind of code. From a workstation? From a separate AWS-resources node that has permissions to do this sort of thing? How do you secure it? How do you distribute keys? And, more importantly, how do you make this process reproducible and ready to be used in CI/CD pipelines? There is no clear answer to these questions from the configuration management tools' point of view.
The other downside is that you might not even have, or want to have, a complete configuration management in your organization. Implementing them gives huge benefits, but a steep learning curve and lack of in-house expertise can be significant blockers in their adaption.
CloudFormation/Heat
Both AWS and OpenStack have a built-in way to define all of their resources in one template. Often, it works nicely in environments that are only AWS or only OpenStack. But, as soon as you want to add another provider to the mix, you need another tool.
Terraform
Finally, there is Terraform, the tool this book is about, and the one we will use to codify a complete infrastructure, or at least the top layer of it.