Terraform Providers & Resources

Providers are plugins that Terraform uses to interact with cloud providers and services. Resources are the building blocks that represent infrastructure objects.

What are Providers?

Provider Purpose

Providers are plugins that Terraform uses to interact with cloud providers, SaaS providers, and other APIs. Each provider adds a set of resource types and data sources that Terraform can manage.

Common Providers

Cloud Providers

  • AWS - hashicorp/aws
  • Azure - hashicorp/azurerm
  • GCP - hashicorp/google
  • Alibaba Cloud - aliyun/alicloud
  • Oracle Cloud - oracle/oci

Infrastructure Providers

  • Docker - kreuzwerker/docker
  • Kubernetes - hashicorp/kubernetes
  • VMware vSphere - hashicorp/vsphere

Configuring Providers

Required Providers Block

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0"
    }
  }
}

Provider Configuration

# AWS Provider
provider "aws" {
  region = "us-east-1"
  
  # Authentication methods:
  # 1. Environment variables
  #    AWS_ACCESS_KEY_ID
  #    AWS_SECRET_ACCESS_KEY
  #    AWS_REGION
  
  # 2. AWS credentials file (~/.aws/credentials)
  # shared_credentials_files = ["~/.aws/credentials"]
  # profile                  = "production"
  
  # 3. Direct configuration (not recommended)
  # access_key = var.aws_access_key
  # secret_key = var.aws_secret_key
}

# Multiple provider instances
provider "aws" {
  alias  = "us-east"
  region = "us-east-1"
}

provider "aws" {
  alias  = "us-west"
  region = "us-west-2"
}

Resources

Resource Block Syntax

resource "resource_type" "resource_name" {
  argument1 = value1
  argument2 = value2
  
  # Nested blocks
  nested_block {
    nested_argument = value
  }
  
  # Multiple instances with count
  count = 3
  
  # Multiple instances with for_each
  for_each = var.instances
}

AWS Resource Examples

EC2 Instance

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "WebServer"
  }
}

S3 Bucket

resource "aws_s3_bucket" "website" {
  bucket = "my-website-bucket"
  
  tags = {
    Name = "Website Bucket"
  }
}

resource "aws_s3_bucket_versioning" "website" {
  bucket = aws_s3_bucket.website.id
  
  versioning_configuration {
    status = "Enabled"
  }
}

VPC

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
  
  tags = {
    Name = "main-vpc"
  }
}

Data Sources

What are Data Sources?

Data sources allow Terraform to fetch information from outside Terraform:

AWS Data Source Examples

# Get AMI
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

# Get VPC
data "aws_vpc" "existing" {
  id = "vpc-12345678"
}

# Get availability zones
data "aws_availability_zones" "available" {
  state = "available"
}

# Use data sources
resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t2.micro"
  subnet_id     = data.aws_subnet.main.id
}

Resource Dependencies

Implicit Dependencies

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "web" {
  vpc_id     = aws_vpc.main.id  # Implicit dependency
  cidr_block = "10.0.0.0/24"
}

Explicit Dependencies

resource "aws_instance" "web" {
  # ...
  
  depends_on = [
    aws_iam_role.example,
    aws_security_group.example
  ]
}

Multiple Resource Instances

Using count

resource "aws_instance" "web" {
  count = 3
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "WebServer-${count.index + 1}"
  }
}

# Access
aws_instance.web[0].id
aws_instance.web[1].id

Using for_each

variable "instances" {
  type = map(string)
  default = {
    web1 = "t2.micro"
    web2 = "t2.small"
    web3 = "t3.medium"
  }
}

resource "aws_instance" "web" {
  for_each = var.instances
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = each.value
  
  tags = {
    Name = each.key
  }
}

# Access
aws_instance.web["web1"].id

Next Steps