Installing
Terraform is available from the popular platform package managers for Macs and Windows.
brew install terraform
cinst Terraform
export TERRAFORM_VERSION=$(curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current_version')
curl --silent --output terraform.zip "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip"
unzip terraform.zip ; rm -f terraform.zip; chmod +x terraform
mkdir -p ${HOME}/bin ; export PATH=${PATH}:${HOME}/bin; mv terraform ${HOME}/bin/
terraform -v
You'll need to update your path to pick up the exe on Windows.
There's still no official package manager support on Linux https://github.com/hashicorp/terraform/issues/17794, so it's just the binaries and getting them in your path.
Verify you have Terraform set-up with:
$ terraform --version
Terraform v0.12.20
Now we have Terraform now installed, the next step is to try running it. To do any useful work, this would be against and using a Cloud provider, [e.g. AWS] and for that we require Authentication.
Authentication
Basic Authentication with the AWS Provider
Install the AWS Cli and add your Key and Secret.You can also use the new Cli too https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html.
```mac fct_label="mac" brew install aws-cli
```powershell fct_label="Powershell"
cinst aws-cli
Verify that with:
$ aws --version
aws-cli/1.16.303 Python/3.6.0 Windows/10 botocore/1.13.39
You will either be supplied you Cli credentials by your AWS administrator or you can obtain your own from your own user IAM section.
$ aws configure
AWS Access Key ID [********************]:
AWS Secret Access Key [********************]:
Default region name [eu-west-1]:
Default output format [json]:
There are many more way to provide AWS Authentication than just this. Old examples may show the hard-coding of secrets or the use of vars to then pass them in. Do not.
provider "aws" {
region = "eu-west-1"
access_key = "givemymoneyaway"
secret_key = "to-bitcoin-miners"
}
Open the sub-folder basic-aws-auth in your console. Validate your authentation set-up by executing terraform init and then terraform apply:
with the GCP Provider
Basic auth with GCP is pretty similar, create a service account in your GCP project, create a key file and download into your profile, create an environmental variable that points to it e.g. :
export GOOGLE_CLOUD_KEYFILE_JSON={{path}}
Open basic-gcp-auth in your console, and update your provider.gcp.tf to have the name of your project.
provider "google" {
project = "examplea"
region = "us-central1"
version = "2.17"
}
Run Terraform init and then apply:
You now have your GCP auth set-up.
Tip - Create a GCP project called examplea
All the GCP examples are based around a project called examplea. Instead of updating your providers, save yourself some time and create yourself a project called examplea.
Terraform commands
Terraform is a command line tool, to see its usage, just Type Terraform at your console now.
$ terraform
Usage: terraform [-version] [-help] <command> [args]
The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.
Common commands:
apply Builds or changes infrastructure
console Interactive console for Terraform interpolations
destroy Destroy Terraform-managed infrastructure
env Workspace management
fmt Rewrites config files to canonical format
get Download and install modules for the configuration
graph Create a visual graph of Terraform resources
import Import existing infrastructure into Terraform
init Initialize a Terraform working directory
output Read an output from a state file
plan Generate and show an execution plan
providers Prints a tree of the providers used in the configuration
push Upload this Terraform module to Atlas to run
refresh Update local state file against real resources
show Inspect Terraform state or plan
taint Manually mark a resource for recreation
untaint Manually unmark a resource as tainted
validate Validates the Terraform files
version Prints the Terraform version
workspace Workspace management
All other commands:
debug Debug output management (experimental)
force-unlock Manually unlock the terraform state
state Advanced state management
That's a lot of commands, however there are only handful of actually common commands that you really use, 90% of the time it is an just Terraform and:
Init
This command sets up the project, gets providers and connects any defined back-ends.
terraform init
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Terraform init can be thought of an equivalent to git init, it downloads the provider executable, modules and does an initial syntax check, all into a .terraform folder.
For the full description its:
terraform init --help
if you open a .terraform folder you find
$ ls -l
total 0
drwxrwxrwx 1 jim jim 512 Nov 4 23:00 modules
drwxrwxrwx 1 jim jim 512 Nov 4 22:18 plugins
The modules folder hold a copy of the terraform modules that you are using. The plugins hold the downloaded copies of the executable providers.
Plan
What would happen on an Apply. The command is a hangover from older versions of Terraform, the apply command now includes a plan stage by default.
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_vpc.main will be created
+ resource "aws_vpc" "main" {
+ arn = (known after apply)
+ assign_generated_ipv6_cidr_block = false
+ cidr_block = "10.0.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_classiclink = (known after apply)
+ enable_classiclink_dns_support = (known after apply)
+ enable_dns_hostnames = (known after apply)
+ enable_dns_support = true
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "createdby" = "Terraform"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
Apply
The actual doing. This can create and destroy, infrastructure will be modified to follow your definitions and compared to your state.
terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_vpc.main will be created
+ resource "aws_vpc" "main" {
+ arn = (known after apply)
+ assign_generated_ipv6_cidr_block = false
+ cidr_block = "10.0.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_classiclink = (known after apply)
+ enable_classiclink_dns_support = (known after apply)
+ enable_dns_hostnames = (known after apply)
+ enable_dns_support = true
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "createdby" = "Terraform"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
Targeted Apply
With a Targeted Apply you can cherry pick the apply, this is especially useful when were developing or debugging:
terraform apply --target aws_vpc.main
This command will only make the VPC, and any of its dependant objects.
Destroy
What does it destroy, the definition or the state reference?
$ terraform destroy
...
Taint
To force the recreation of an object you can taint it, to force it to be changed even if there's no drift.
terraform taint aws_instance.web
Targeting
It can be very useful to just target one resource at a time, in the previous example just one resource was tainted and a similar method can be used with apply:
terraform apply --target module.webbfarm.aws_instance.web
Which would only target module.webbfarm.aws_instance.web and ITS' DEPENDENCIES.
Modifying existing infrastructure
If the definition differs from the existing state captured. Some properties changing causes existing objects to be modified others the recreation.
How can I tell what which will happen?
TODO:show where changes/destroyed
And usually in this order.
Speeding up your Terraform builds and development
When you use Terraform The first step and command in the Terraform init this process cuases the appropriate provider executables to be downloaded. When you have multiple Terraform projects and environments, that can end up being a lot of copying and downloading, even if you don't terraform init that often. A better way is to set up and use a provider cache.
Setting up a Windows plug-in cache
``powershell fct_label="powershell" ni $env:APPDATA\terraform.rc Add-Content $env:APPDATA\terraform.rc "plugin_cache_dir =
"$HOME\.terraform.d\plugin-cache`"" mkdir "$HOME/.terraform.d/plugin-cache"
```shell fct_label="*nix"
touch ~/.terraformrc
echo plugin_cache_dir = \"$HOME/.terraform.d/plugin-cache\" >> ~/.terraformrc
mkdir "$HOME/.terraform.d/plugin-cache"
Note
WSL Windows sub-system for Linux
[How to set up WSL](https://docs.microsoft.com/en-us/windows/wsl/wsl2-install)