Terraform Provider Basics #
Overview #
The very first command we run is terraform init. This installs all the requirements and plugins needed for your configuration, such as the AWS, GCP, or Azure providers.
Provider Types #
There are three types of providers available:
- Official — Owned and maintained by HashiCorp (e.g., AWS, GCP, Azure).
- Partner — Owned and maintained by a third party, but vetted by HashiCorp.
- Community — Owned and maintained by a third party, not vetted by HashiCorp.
Multiple Providers #
resource "local_file" "pet" {
filename = "/root/pets.txt"
content = "We love pets!"
}
resource "random_pet" "name" {
length = 2
prefix = "Mrs"
separator = "."
}When running terraform init, it sees that the local provider is already installed, but the random provider will need to be installed.
Resource Attribute References #
resource "random_string" "server-suffix" {
length = 6
upper = false
special = false
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "web-${random_string.server-suffix.id}"
}
}Here is another example using two different providers. The random_string resource creates a random string, and the aws_instance resource uses the AWS provider.
The expression ${random_string.server-suffix.id} is called a resource attribute reference. It is used to reference the output of one resource as an input to another resource. When terraform apply is run, two resources will be created — the random string is created first, and then the AWS instance is created with the random string as part of its Name tag.
Version Constraints #
By default, terraform init downloads the latest version of each provider. You can pin or constrain versions in the terraform block:
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "~> 1.4.0"
}
}
}
resource "local_file" "pet" {
filename = "/root/pets.txt"
content = "We love pets!"
}Now when terraform init runs, it will download version 1.4.0 of the local provider.
Pessimistic Constraint Operator (~>)
#
The ~> operator allows for flexible version matching:
Minor version constraint (~> 1.4):
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "~> 1.4"
}
}
}This will allow any version >= 1.4.0 but < 2.0.0.
Patch version constraint (~> 1.4.0):
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "~> 1.4.0"
}
}
}This will allow any version >= 1.4.0 but < 1.5.0.
Provider Aliases #
resource "aws_key_pair" "alpha" {
key_name = "alpha"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3……alpha@a-server"
}
resource "aws_key_pair" "beta" {
key_name = "beta"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3………beta@b-server"
}These two resource blocks need a provider block. Say this is the provider block in provider.tf:
provider "aws" {
region = "us-east-1"
}If you create the above resources, both key pairs will be created in the us-east-1 region. But what if we want to create one key pair in us-east-1 and another in us-west-2? We can use provider aliases to achieve this.
Defining Aliases #
provider "aws" {
region = "us-east-1"
alias = "east"
}
provider "aws" {
region = "us-west-2"
alias = "west"
}Using Aliases in Resources #
resource "aws_key_pair" "alpha" {
key_name = "alpha"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3……alpha@a-server"
}
resource "aws_key_pair" "beta" {
key_name = "beta"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3………beta@b-server"
provider = aws.west
}Now when you run terraform show, you will see that the alpha key pair is created in the us-east-1 region and the beta key pair is created in the us-west-2 region.