== AWS Examples
Examples of AWS Terraform modules.
Each module corresponds to a module that uses that resource, eg aws_vpc
.
aws_db_cluster_snapshot/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a snapshot of an RDS Aurora MySQL 1 Cluster instance
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
profile = "terraform-examples"
default_tags {
tags = {
cs_terraform_examples = "aws_db_cluster_snapshot/simple"
}
}
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_aurora_cluster_username" {
description = "the username for the login credentials to your db"
default = "username_example"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_aurora_cluster_password" {
description = "the password, which must be more than 8 characters long"
default = "password_example"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster
resource "aws_rds_cluster" "changeme_aws_aurora_cluster_instance" {
# The login credentials are stored as plain-text in the state files
# https://www.terraform.io/docs/language/state/sensitive-data.html
# For security, use a secrets manager
# https://registry.terraform.io/modules/yurymkomarov/rds-aurora-cluster/aws/latest#secretsmanager_secret
master_username = var . changeme_aws_aurora_cluster_username
master_password = var . changeme_aws_aurora_cluster_password
skip_final_snapshot = true
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_cluster_snapshot
resource "aws_db_cluster_snapshot" "changeme_aws_aurora_snapshot" {
db_cluster_identifier = aws_rds_cluster . changeme_aws_aurora_cluster_instance . id
db_cluster_snapshot_identifier = "changeme-snapshot-identifier"
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_db_instance/postgres/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a simple AWS RDS DB Instance with Postgresql
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_db_instance/postgres"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance
# Explanation: This resource creates the DB Instance. This Example creates a Postgresql Server version 9.6.9 as a Managed RDS Service.
# Allocates a Postgres Database service version 9.6.9 in a t3.micro instance with a database name 'changeme_simple_postgresql_instance', username 'changeme_username' and passwd 'changeme_password'
resource "aws_db_instance" "changeme_simple_postgresql_instance" {
allocated_storage = 5
engine = "postgres"
engine_version = "12.5"
instance_class = "db.t3.micro"
name = "changeme_simple_postgresql_instance"
username = "changeme_username"
password = "changeme_password"
skip_final_snapshot = true
storage_encrypted = false
}
##Explanation:
# Details on Arguments:
# Required Argument - allocated_storage: How Much storage will be allocated for the Database in Gbi
# Required Argument - engine: Engines Types like MySql, Postgres, MariaDB....
# Required Argument - engine_version: The above choosen version of Engine. For ex: MySQL version 5.7
# Required Argument - instance_class: The size of the Instance (VM)
# Required Argument - username: The Master DB-User username
# Required Argument - passord: The master DB-User password
# Optional Argument - name: The Name of the Instance
# Optional Argument - skip_final_snapshot: It's needed for destroying the instance with Terraform Destroy
# Optional Argument - storage_encrypted: If data is going to be encrypted at rest or not
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_db_instance/restore_db_from_snapshot/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a DB Instance PROD. Takes a snapshot (latest), and with the latest snapshot,creates a new DEV Instance.
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_db_instance/mount_db_snapshot"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance
# See also: (aws/aws_db_instance/simple)
# Explanation: This resource creates the DB Instance. This Example creates a MySQL version 5.7 as a Managed RDS Service.
resource "aws_db_instance" "changeme_aws_db_instance_prod" {
allocated_storage = 10
engine = "mysql"
engine_version = "5.7"
instance_class = "db.t2.micro"
name = "changeme_db_prod"
identifier = "changeme-db-identifier"
username = "changeme_username_prod"
password = "changeme_password_prod"
final_snapshot_identifier = "changeme-final-snapshot"
skip_final_snapshot = true # change to false if you want to keep snapshot after deleting the instance
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_snapshot
# Explanation: Run a backup snapshot from prod Database. It uses timeouts for waiting until the snapshot operation complete
resource "aws_db_snapshot" "changeme_db_prod_snapshot" {
db_instance_identifier = aws_db_instance . changeme_aws_db_instance_prod . id
db_snapshot_identifier = "changeme-prod-snapshot"
timeouts {
read = "10m"
}
depends_on = [
aws_db_instance . changeme_aws_db_instance_prod
]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/db_snapshot
# Explanation: Data Source, reads the latest snapshot from the prod Database and gets its id
data "aws_db_snapshot" "changeme_latest_prod_snapshot" {
depends_on = [
aws_db_snapshot . changeme_db_prod_snapshot
]
db_instance_identifier = aws_db_instance . changeme_aws_db_instance_prod . id
most_recent = true
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance
# Explanation: Use the latest production snapshot to create a DEV instance DB.
resource "aws_db_instance" "changeme_db_dev" {
instance_class = "db.t2.micro"
identifier = "changeme-db-from-backup"
snapshot_identifier = data . aws_db_snapshot . changeme_latest_prod_snapshot . id
skip_final_snapshot = true
lifecycle {
ignore_changes = [ snapshot_identifier ]
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_db_instance/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a simple AWS RDS DB Instance with MySQL
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_db_instance/simple"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance
# Explanation: This resource creates the DB Instance. This Example creates a MySql Server version 5.7 as a Managed RDS Service.
# Allocates a MySQl version 5.7 in a t3.micro instance with a database name 'changeme_simple_aws_db_instance', username 'changeme_username' and passwd 'changeme_password'
resource "aws_db_instance" "changeme_simple_aws_db_instance" {
allocated_storage = 5
engine = "mysql"
engine_version = "5.7"
instance_class = "db.t3.micro"
name = "changeme_simple_aws_db_instance"
username = "changemeusername"
password = "changeme_password"
skip_final_snapshot = true
}
##Explanation:
# Details on Arguments:
# Required Argument - allocated_storage: How Much storage will be allocated for the Database in Gbi
# Required Argument - engine: Engines Types like MySql, Postgres, MariaDB....
# Required Argument - engine_version: The above choosen version of Engine. For ex: MySQL version 5.7
# Required Argument - instance_class: The size of the Instance (VM)
# Required Argument - username: The Master DB-User username
# Required Argument - passord: The master DB-User password
# Optional Argument - name: The Name of the Instance
# Optional Argument - skip_final_snapshot: It's needed for destroying the instance with Terraform Destroy
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_dynamodb_table/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create an empty table in AWS DynamoDB
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
profile = "terraform-examples"
default_tags {
tags = {
cs_terraform_examples = "aws_dynamodb_table/simple"
}
}
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_hash_key" {
description = "the hash key that's also defined as an attribute"
default = "example_hash_key"
}
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table#argument-reference
resource "aws_dynamodb_table" "changeme_aws_dynamodb_table" {
name = "changeme_table_name" # Explanation: the table's name, which needs to be unique to a region
read_capacity = 10 # Explanation: the number of read units for the table
write_capacity = 10 # Explanation: the number of write units for the table
hash_key = var . changeme_hash_key
attribute {
name = var . changeme_hash_key # Explanation: the attribute must be of type [S]tring, [N]umber, or [B]inary
type = "S"
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_dynamodb_table_item/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a table with one item in AWS DynamoDB
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
profile = "terraform-examples"
default_tags {
tags = {
cs_terraform_examples = "aws_dynamodb_table_item/simple"
}
}
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_item_hash_key" {
description = "the hash key that's also defined as an attribute"
default = "example_hash_key"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table_item
resource "aws_dynamodb_table_item" "changeme_dynamodb_table_item" {
table_name = aws_dynamodb_table . changeme_aws_dynamodb_table_resource . name
hash_key = aws_dynamodb_table . changeme_aws_dynamodb_table_resource . hash_key
item = << ITEM
{
"example_hash_key": {"S": "something"},
"example_attribute": {"N": "11111"}
}
ITEM
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table
resource "aws_dynamodb_table" "changeme_aws_dynamodb_table_resource" {
name = "changeme_dynamodb_table_name" # Explanation: the table's name, which needs to be unique to a region
read_capacity = 10 # Explanation: the number of read units for the table
write_capacity = 10 # Explanation: the number of write units for the table
hash_key = var . changeme_item_hash_key
attribute {
name = var . changeme_item_hash_key # Explanation: the attribute must be of type [S]tring, [N]umber, or [B]inary
type = "S"
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_ebs_volume/ebs_snapshot/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a Snapshot for a Given EBS Volume
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_ebs_volume/ebs_snapshot"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones
data "aws_availability_zones" "changeme_az_list_ebs_snapshot" {
state = "available"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume
# Explanation: The AWS 'aws_ebs_volume' resource is responsible for creating the EBS volume. The only required field is Availability Zone
# where the EBS vol is going to be created. Some optional arguments are Size in GBi, encryption(TRUE/FALSE) and he type of EBS volume. Can be "standard", "gp2", "io1", "sc1" or "st1" (Default: "standard").
resource "aws_ebs_volume" "changeme_ebs_volume_snapshot" {
availability_zone = data . aws_availability_zones . changeme_az_list_ebs_snapshot . names [ 0 ]
size = 10
type = "standard"
encrypted = false
tags = {
Name = "changeme_ebs_volume_tag"
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_snapshot
# Explanation: Takes a Snapshot from the EBS Volume created Above
resource "aws_ebs_snapshot" "changeme_ebs_snapshot" {
volume_id = aws_ebs_volume . changeme_ebs_volume_snapshot . id
tags = {
Name = "Hello_CS_snap"
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_ebs_volume/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create an EBS volume in AWS
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_ebs_volume/simple"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones
data "aws_availability_zones" "changeme_available_az_list" {
state = "available"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume
# Explanation: The AWS 'aws_ebs_volume' resource is responsible for creating the EBS volume. The only required field is Availability Zone
# where the EBS vol is going to be created. Some optional arguments are Size in GBi, encryption(TRUE/FALSE) and he type of EBS volume. Can be "standard", "gp2", "io1", "sc1" or "st1" (Default: "standard").
resource "aws_ebs_volume" "changeme_simple_aws_ebs_volume" {
availability_zone = data . aws_availability_zones . changeme_available_az_list . names [ 0 ]
size = 10
type = "standard"
encrypted = false
tags = {
Name = "changeme_ebs_volume_tag"
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_ebs_volume/volume_attachment/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create an EBS volume in AWS and attach to EC2 instance
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_ebs_volume/volume_attachment"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones
data "aws_availability_zones" "changeme_az_list" {
state = "available"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/volume_attachment
# Explanation: Provide the attachment between the extra EBS external volume and the Ec2 Instance
resource "aws_volume_attachment" "changeme_aws_volume_attachment" {
device_name = "/dev/sdh"
volume_id = aws_ebs_volume . changeme_aws_ebs_volume . id
instance_id = aws_instance . changeme_aws_instance . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume
# Explanation: The AWS 'aws_ebs_volume' resource is responsible for creating the EBS volume. The only required field is Availability Zone
# where the EBS vol is going to be created. Some optional arguments are Size in GBi, encryption(TRUE/FALSE) and he type of EBS volume. Can be "standard", "gp2", "io1", "sc1" or "st1" (Default: "standard").
resource "aws_ebs_volume" "changeme_aws_ebs_volume" {
availability_zone = data . aws_availability_zones . changeme_az_list . names [ 0 ]
size = 5
type = "standard"
encrypted = false
tags = {
Name = "changeme_ebs_volume_tag"
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
# Explanation: The AWS 'aws_instance' resource is responsible for allocating an EC2 instance. It's needed as we want to deliver the
# the EBS volume to it.
resource "aws_instance" "changeme_aws_instance" {
instance_type = "t2.micro"
# Explanation: AMI IDs are region-specific. This AMI ID is specific to the `us-east-1` region. If you use a different region, you will need to change this ID.
ami = "ami-0c2b8ca1dad447f8a" # us-east-1 / Amazon Linux
availability_zone = data . aws_availability_zones . changeme_az_list . names [ 0 ]
tags = {
Name = "changeme_aws_instance_tag"
}
user_data = <<- EOF
#!/bin/bash
echo "Hello_Example!"
EOF
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_eks/fargate/spot_and_fargate/ Spot instances + fargate EKS cluster This example sets the cluster control plane on SPOT instances (for test purposes, and saving credits) and normal workloads on Fargate (Pay per Pod). To make the control plane use normal instances you just need to comment the line with capacity_type = "SPOT"
main.tf.
destroy.sh #!/bin/bash
../../../../ bin / destroy . sh aws
main.tf # Summary: See README.md
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
local = {
version = "~> 1.4"
}
external = {
version = "~> 1.2"
}
kubernetes = {
version = "~> 1.10"
}
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_eks/fargate/spot_and_fargate"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "kubernetes" {
host = data . aws_eks_cluster . changeme_spot_and_fargate_eks_cluster_data . endpoint
load_config_file = false
cluster_ca_certificate = base64decode ( data . aws_eks_cluster . changeme_spot_and_fargate_eks_cluster_data . certificate_authority [ 0 ] . data )
token = data . aws_eks_cluster_auth . changeme_spot_and_fargate_eks_cluster_auth_data . token
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_name" {
description = "the name of your stack, e.g. \" demo \" "
default = "eks-example"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_environment" {
description = "the name of your environment, e.g. \" prod \" "
default = "prod"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_region" {
description = "the AWS region in which resources are created, you must set the availability_zones variable as well if you define this value to something other than the default"
default = "us-east-1"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_availability_zones" {
description = "a comma-separated list of availability zones, defaults to all AZ of the region, if set to something other than the defaults, both private_subnets and public_subnets have to be defined as well"
default = [ "us-east-1a" , "us-east-1b" , "us-east-1c" ]
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_cidr" {
description = "The CIDR block for the VPC."
default = "10.0.0.0/16"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_private_subnets" {
description = "a list of CIDRs for private subnets in your VPC, must be set if the cidr variable is defined, needs to have as many elements as there are availability zones"
default = [ "10.0.0.0/20" , "10.0.32.0/20" , "10.0.64.0/20" ]
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_public_subnets" {
description = "a list of CIDRs for public subnets in your VPC, must be set if the cidr variable is defined, needs to have as many elements as there are availability zones"
default = [ "10.0.16.0/20" , "10.0.48.0/20" , "10.0.80.0/20" ]
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_spot_and_fargate_k8s_version" {
description = "kubernetes version"
default = ""
}
# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "aws_eks_cluster" "changeme_spot_and_fargate_eks_cluster_data" {
name = aws_eks_cluster . changeme_spot_and_fargate_eks_cluster . id
}
# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "aws_eks_cluster_auth" "changeme_spot_and_fargate_eks_cluster_auth_data" {
name = aws_eks_cluster . changeme_spot_and_fargate_eks_cluster . id
}
# Fetch OIDC provider thumbprint for root CA
# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "external" "changeme_external_thumbprint_data" {
program = [ "${path.module}/oidc_thumbprint.sh" , var . changeme_spot_and_fargate_region ]
depends_on = [ aws_eks_cluster . changeme_spot_and_fargate_eks_cluster ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
resource "aws_vpc" "changeme_spot_and_fargate_vpc" {
cidr_block = var . changeme_spot_and_fargate_cidr
enable_dns_support = true
enable_dns_hostnames = true
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway
resource "aws_internet_gateway" "changeme_spot_and_fargate_internet_gateway" {
vpc_id = aws_vpc . changeme_spot_and_fargate_vpc . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway
resource "aws_nat_gateway" "changeme_spot_and_fargate_nat_gateway" {
count = length ( var . changeme_spot_and_fargate_private_subnets )
allocation_id = element ( aws_eip . changeme_spot_and_fargate_eip .*. id , count . index )
subnet_id = element ( aws_subnet . changeme_spot_and_fargate_subnet_public .*. id , count . index )
depends_on = [ aws_internet_gateway . changeme_spot_and_fargate_internet_gateway ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip
resource "aws_eip" "changeme_spot_and_fargate_eip" {
count = length ( var . changeme_spot_and_fargate_private_subnets )
vpc = true
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet
resource "aws_subnet" "changeme_spot_and_fargate_subnet_private" {
vpc_id = aws_vpc . changeme_spot_and_fargate_vpc . id
cidr_block = element ( var . changeme_spot_and_fargate_private_subnets , count . index )
availability_zone = element ( var . changeme_spot_and_fargate_availability_zones , count . index )
count = length ( var . changeme_spot_and_fargate_private_subnets )
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet
resource "aws_subnet" "changeme_spot_and_fargate_subnet_public" {
vpc_id = aws_vpc . changeme_spot_and_fargate_vpc . id
cidr_block = element ( var . changeme_spot_and_fargate_public_subnets , count . index )
availability_zone = element ( var . changeme_spot_and_fargate_availability_zones , count . index )
count = length ( var . changeme_spot_and_fargate_public_subnets )
map_public_ip_on_launch = true
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table
resource "aws_route_table" "changeme_spot_and_fargate_route_table_public" {
vpc_id = aws_vpc . changeme_spot_and_fargate_vpc . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route
resource "aws_route" "changeme_spot_and_fargate_aws_route_public" {
route_table_id = aws_route_table . changeme_spot_and_fargate_route_table_public . id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway . changeme_spot_and_fargate_internet_gateway . id
timeouts {
create = "5m"
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table
resource "aws_route_table" "changeme_spot_and_fargate_route_table_private" {
count = length ( var . changeme_spot_and_fargate_private_subnets )
vpc_id = aws_vpc . changeme_spot_and_fargate_vpc . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route
resource "aws_route" "changeme_spot_and_fargate_route_private" {
count = length ( compact ( var . changeme_spot_and_fargate_private_subnets ))
route_table_id = element ( aws_route_table . changeme_spot_and_fargate_route_table_private .*. id , count . index )
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = element ( aws_nat_gateway . changeme_spot_and_fargate_nat_gateway .*. id , count . index )
timeouts {
create = "5m"
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association
resource "aws_route_table_association" "changeme_spot_and_fargate_route_table_association_private" {
count = length ( var . changeme_spot_and_fargate_private_subnets )
subnet_id = element ( aws_subnet . changeme_spot_and_fargate_subnet_private .*. id , count . index )
route_table_id = element ( aws_route_table . changeme_spot_and_fargate_route_table_private .*. id , count . index )
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association
resource "aws_route_table_association" "changeme_spot_and_fargate_route_table_association_public" {
count = length ( var . changeme_spot_and_fargate_public_subnets )
subnet_id = element ( aws_subnet . changeme_spot_and_fargate_subnet_public .*. id , count . index )
route_table_id = aws_route_table . changeme_spot_and_fargate_route_table_public . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "changeme_spot_and_fargate_iam_role_cluster" {
name = "${var.changeme_spot_and_fargate_name}-eks-cluster-role"
force_detach_policies = true
assume_role_policy = << POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"eks.amazonaws.com",
"eks-fargate-pods.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
POLICY
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEKSClusterPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
role = aws_iam_role . changeme_spot_and_fargate_iam_role_cluster . name
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEKSServicePolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSServicePolicy"
role = aws_iam_role . changeme_spot_and_fargate_iam_role_cluster . name
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster
resource "aws_eks_cluster" "changeme_spot_and_fargate_eks_cluster" {
name = "${var.changeme_spot_and_fargate_name}-${var.changeme_spot_and_fargate_environment}"
role_arn = aws_iam_role . changeme_spot_and_fargate_iam_role_cluster . arn
vpc_config {
subnet_ids = concat ( aws_subnet . changeme_spot_and_fargate_subnet_public .*. id , aws_subnet . changeme_spot_and_fargate_subnet_private .*. id )
}
timeouts {
delete = "30m"
}
depends_on = [
aws_iam_role_policy_attachment . changeme_spot_and_fargate_AmazonEKSClusterPolicy ,
aws_iam_role_policy_attachment . changeme_spot_and_fargate_AmazonEKSServicePolicy
]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider
resource "aws_iam_openid_connect_provider" "changeme_iam_openid_connect_provider" {
client_id_list = [ "sts.amazonaws.com" ]
thumbprint_list = [ data . external . changeme_external_thumbprint_data . result . thumbprint ]
url = data . aws_eks_cluster . changeme_spot_and_fargate_eks_cluster_data . identity [ 0 ] . oidc [ 0 ] . issuer
lifecycle {
ignore_changes = [ thumbprint_list ]
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "changeme_spot_and_fargate_iam_role_node_group" {
name = "${var.changeme_spot_and_fargate_name}-eks-node-group-role"
force_detach_policies = true
assume_role_policy = << POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
POLICY
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEKSWorkerNodePolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
role = aws_iam_role . changeme_spot_and_fargate_iam_role_node_group . name
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEKS_CNI_Policy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
role = aws_iam_role . changeme_spot_and_fargate_iam_role_node_group . name
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment
resource "aws_iam_role_policy_attachment" "changeme_spot_and_fargate_AmazonEC2ContainerRegistryReadOnly" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
role = aws_iam_role . changeme_spot_and_fargate_iam_role_node_group . name
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group
resource "aws_eks_node_group" "changeme_spot_and_fargate_eks_node_group" {
cluster_name = aws_eks_cluster . changeme_spot_and_fargate_eks_cluster . name
node_group_name = "changeme-eks-cluster-kube-system"
node_role_arn = aws_iam_role . changeme_spot_and_fargate_iam_role_node_group . arn
subnet_ids = aws_subnet . changeme_spot_and_fargate_subnet_private .*. id
capacity_type = "SPOT"
scaling_config {
desired_size = 1
max_size = 1
min_size = 1
}
instance_types = [ "t2.micro" ]
version = var . changeme_spot_and_fargate_k8s_version
# Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling.
# Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces.
depends_on = [
aws_iam_role_policy_attachment . changeme_spot_and_fargate_AmazonEKSWorkerNodePolicy ,
aws_iam_role_policy_attachment . changeme_spot_and_fargate_AmazonEKS_CNI_Policy ,
aws_iam_role_policy_attachment . changeme_spot_and_fargate_AmazonEC2ContainerRegistryReadOnly ,
]
}
# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "cluster_id" {
description = "ID of the created cluster"
value = aws_eks_cluster . changeme_spot_and_fargate_eks_cluster . id
}
oidc_thumbprint.sh #!/bin/bash
# source: https://github.com/terraform-providers/terraform-provider-aws/issues/10104
THUMBPRINT = $ ( echo | openssl s_client - servername oidc . eks . "${1}" . amazonaws . com - showcerts - connect oidc . eks . "${1}" . amazonaws . com : 443 2 >&- | tac | sed - n '/-----END CERTIFICATE-----/,/-----BEGIN CERTIFICATE-----/p; /-----BEGIN CERTIFICATE-----/q' | tac | openssl x509 - fingerprint - noout | sed 's/://g' | awk - F = '{print tolower($2)}' )
THUMBPRINT_JSON = "{ \" thumbprint \" : \" ${THUMBPRINT} \" }"
echo "$THUMBPRINT_JSON"
run.sh #!/bin/bash
../../../../ bin / apply . sh aws
aws_elb/classic_elb/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Creates a simple Classic Elastic Load Balancer with two EC2 Instances
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-2"
default_tags {
tags = {
cs_terraform_examples = "aws_elb/classic_elb"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
# See also: [aws/aws_security_group/ssh](https://github.com/ContainerSolutions/terraform-examples/tree/main/aws/aws_security_group/ssh)
resource "aws_security_group" "changeme_aws_security_group" {
name = "changeme-aws-security-group-classic-elb-name"
description = "Allow HTTP 8080 inbound traffic"
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
# Explanation: Deploys the first Server in us-east-2a
resource "aws_instance" "changeme_first_aws_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
availability_zone = "us-east-2a"
vpc_security_group_ids = [ aws_security_group . changeme_aws_security_group . id ]
user_data = <<- EOF
#!/bin/bash
echo "Hello, World from Host1" > index.html
nohup busybox httpd -f -p 8080 &
EOF
tags = {
Name = "changeme_first_aws_instance_tag"
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
# Explanation: Deploys the second Server in us-east-2b
resource "aws_instance" "changeme_second_aws_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
availability_zone = "us-east-2b"
vpc_security_group_ids = [ aws_security_group . changeme_aws_security_group . id ]
user_data = <<- EOF
#!/bin/bash
echo "Hello, World from Host2" > index.html
nohup busybox httpd -f -p 8080 &
EOF
tags = {
Name = "changeme_second_aws_instance_tag"
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elb
# Explanation: Deploys the Classic Load Balancer, allows traffic in 8080 ports
resource "aws_elb" "changeme_simple_aws_elb" {
name = "changeme-simple-aws-elb"
availability_zones = [ "us-east-2a" , "us-east-2b" ]
listener {
instance_port = 8080
instance_protocol = "http"
lb_port = 8080
lb_protocol = "http"
}
health_check {
healthy_threshold = 10
unhealthy_threshold = 2
timeout = 5
target = "HTTP:8080/"
interval = 10
}
instances = [ aws_instance . changeme_first_aws_instance . id , aws_instance . changeme_second_aws_instance . id ]
cross_zone_load_balancing = true
idle_timeout = 400
connection_draining = true
connection_draining_timeout = 400
tags = {
Name = "changeme_simple_aws_elb_tag"
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_iam/groups/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a two users in two groups
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_iam/groups"
}
}
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_iam_groups_groups" {
type = list ( any )
default = [
"Dev" ,
"Infra"
]
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_iam_groups_users" {
type = map ( any )
default = {
"jane.doe" = {
"groups" = [
"Dev"
] ,
} ,
"john.doe" = {
"groups" = [
"Infra"
] ,
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group
resource "aws_iam_group" "changeme_iam_groups_groups" {
count = length ( var . changeme_iam_groups_groups )
name = var . changeme_iam_groups_groups [ count . index ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy_attachment
resource "aws_iam_group_policy_attachment" "changeme_iam_group_policy_attachment_administrators" {
group = aws_iam_group . changeme_iam_groups_groups [ 1 ] . name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy
resource "aws_iam_group_policy" "changeme_iam_group_policy_dev" {
name = "changeme-iam-group-policy-dev"
group = aws_iam_group . changeme_iam_groups_groups [ 1 ] . id
policy = << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
EOF
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_group_policy
resource "aws_iam_group_policy" "changeme_iam_group_policy_dev_assumerole" {
name = "changeme-iam-group-policy-devsecops-assumerole"
group = aws_iam_group . changeme_iam_groups_groups [ 1 ] . id
policy = << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
EOF
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user
resource "aws_iam_user" "changeme_iam_user_users" {
for_each = var . changeme_iam_groups_users
name = each . key
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_group_membership
resource "aws_iam_user_group_membership" "changeme_iam_user_group_membership_user_groups" {
for_each = var . changeme_iam_groups_users
user = each . key
groups = each . value [ "groups" ]
# This manual dependency is required, else Terraform complains the users do not exist yet.
depends_on = [
aws_iam_user . changeme_iam_user_users ,
aws_iam_group . changeme_iam_groups_groups
]
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_instance/ami_lookup/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Data Source for getting latest getting AMI Linux Imagehttps://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html
# Documentation: https://www.tserraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_instance/ami_lookup"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami
# Explanation: Get most_recent version of Ubuntu Image
data "aws_ami" "changeme_aws_ami" {
most_recent = true
# Explanation: Canonical now publishes official Ubuntu images on the Amazon cloud.
# Check supported versions here : https://uec-images.ubuntu.com/locator/
filter {
name = "name"
values = [ "ubuntu/images/hvm-ssd/ubuntu-hirsute-21.04-amd64-server-*" ]
}
filter {
name = "virtualization-type"
values = [ "hvm" ]
}
# Explanation: There are different Public providers (owners), like Canonical, AWS and others . Check here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html
# Some examples of owners: 099720109477 - Canonical and 679593333241 - AWS
owners = [ "099720109477" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_ami_lookup_aws_instance" {
ami = data . aws_ami . changeme_aws_ami . id
instance_type = "t3.micro"
tags = {
Name = "changeme_ami_lookup_aws_instance"
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_instance/count/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Uses the 'count' feature to create multiple EC2 instances.
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_instance/count"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_aws_instance_count_count" {
# Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
count = 2
instance_type = "t2.nano"
ami = "ami-0ddbdea833a8d2f0d"
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_instance/for_each/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Example of 'for_each' usage.
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_instance/for_each"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_aws_instance_count_foreach" {
# Documentation: https://www.terraform.io/docs/language/meta-arguments/for_each.html
for_each = {
"a" = "1"
"b" = "2"
}
tags = {
Name = "aws_resource_count_${each.key}${each.value}"
}
instance_type = "t2.nano"
ami = "ami-0ddbdea833a8d2f0d"
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_instance/remote-exec/inline/ To run this:
../../../../bin/apply_aws.sh
destroy.sh #!/bin/bash
../../../../ bin / destroy . sh aws
main.tf # Summary: Remote execution using default expected location of your ssh keys,
# and setup of provider connection.
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_instance/remote-exec/inline"
}
}
}
# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "aws_vpc" "changeme_aws_vpc_default" {
default = true
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_ssh_private_key_path" {
description = "SSH private key file path"
default = "~/.ssh/id_rsa"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_ssh_public_key_path" {
description = "SSH public key file path"
default = "~/.ssh/id_rsa.pub"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_ssh_username" {
description = "Default username built into the AMI"
default = "ubuntu"
}
# Explanation: Create an SSH key pair for accessing the EC2 instance
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "changeme_remote_exec_inline_aws_key_pair" {
public_key = file ( var . changeme_aws_instance_remote_exec_inline_ssh_public_key_path )
}
# Explanation: Create our default security group to access the instance, over specific protocols
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_remote_exec_inline_security_group" {
vpc_id = data . aws_vpc . changeme_aws_vpc_default . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_security_group_rule_outgoing_any" {
security_group_id = aws_security_group . changeme_remote_exec_inline_security_group . id
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_security_group_rule_incoming_ssh" {
security_group_id = aws_security_group . changeme_remote_exec_inline_security_group . id
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_remote_exec_inline_aws_instance" {
# Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
count = 2
instance_type = "t2.nano"
ami = "ami-0ddbdea833a8d2f0d"
key_name = aws_key_pair . changeme_remote_exec_inline_aws_key_pair . id # the name of the SSH keypair to use for provisioning
vpc_security_group_ids = [ aws_security_group . changeme_remote_exec_inline_security_group . id ]
# Documentation: https://www.terraform.io/docs/language/resources/provisioners/connection.html
connection {
host = self . public_ip
user = var . changeme_aws_instance_remote_exec_inline_ssh_username
private_key = file ( var . changeme_aws_instance_remote_exec_inline_ssh_private_key_path )
agent = false # don't use SSH agent because we have the private key right here
}
# Documentation: https://www.terraform.io/docs/language/resources/provisioners/remote-exec.html
provisioner "remote-exec" {
inline = [
"echo ${self.ami}"
]
}
}
run.sh #!/bin/bash
../../../../ bin / check_or_create_ssh_key . sh
../../../../ bin / apply . sh aws
Connection to Windows instances should be done using WinRM. In this example WinRM is enabled in the instance’s user_data.
After that, the assigned password is retrieved using the get_password_data
argument and the private key. We use the Administrator
user and its retrieved password to connect to the instance, copy the hello.ps1 script and execute it.
To run this:
../../../../../bin/apply_aws.sh
destroy.sh #!/bin/bash
../../../../../ bin / destroy . sh aws
main.tf # Summary: Run a command in a newly-created Windows machine
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_instance/remote-exec/inline/windows"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc
data "aws_vpc" "changeme_aws_vpc" {
default = true
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path" {
description = "SSH private key file path"
default = "~/.ssh/id_rsa"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_windows_ssh_public_key_path" {
description = "SSH public key file path"
default = "~/.ssh/id_rsa.pub"
}
# Explanation: Create an SSH key pair for accessing the EC2 instance
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "changeme_remote_exec_inline_windows_key_pair" {
public_key = file ( var . changeme_aws_instance_remote_exec_inline_windows_ssh_public_key_path )
}
# Explanation: Create our default security group to access the instance, over specific protocols
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_remote_exec_inline_windows_security_group" {
vpc_id = data . aws_vpc . changeme_aws_vpc . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_windows_security_group_rule_outgoing_any" {
security_group_id = aws_security_group . changeme_remote_exec_inline_windows_security_group . id
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_security_group_rule_incoming_rdp" {
security_group_id = aws_security_group . changeme_remote_exec_inline_windows_security_group . id
type = "ingress"
from_port = 3389
to_port = 3389
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_incoming_winrm" {
security_group_id = aws_security_group . changeme_remote_exec_inline_windows_security_group . id
type = "ingress"
from_port = 5986
to_port = 5986
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_remote_exec_inline_windows_aws_instance" {
instance_type = "t2.micro"
ami = "ami-0f93c815788872c5d"
key_name = aws_key_pair . changeme_remote_exec_inline_windows_key_pair . id # the name of the SSH keypair to use for provisioning
vpc_security_group_ids = [ aws_security_group . changeme_remote_exec_inline_windows_security_group . id ]
user_data = file ( "scripts/user_data.txt" )
get_password_data = true
tags = { Name = "terraform-examples" }
}
# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_admin_password" {
value = rsadecrypt ( aws_instance . changeme_remote_exec_inline_windows_aws_instance . password_data , file ( var . changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path ))
}
# Documentation: https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource
resource "null_resource" "changeme_provision_files" {
# Documentation: https://www.terraform.io/docs/language/resources/provisioners/connection.html
connection {
host = aws_instance . changeme_remote_exec_inline_windows_aws_instance . public_ip
type = "winrm"
user = "Administrator"
password = rsadecrypt ( aws_instance . changeme_remote_exec_inline_windows_aws_instance . password_data , file ( var . changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path ))
https = true
insecure = true
port = 5986
timeout = "1m"
}
# Documentation https://www.terraform.io/docs/language/resources/provisioners/index.html
provisioner "file" {
source = "scripts/hello.ps1"
destination = "C:/hello.ps1"
}
# Documentation: https://www.terraform.io/docs/language/resources/provisioners/remote-exec.html
provisioner "remote-exec" {
inline = [
"powershell.exe -ExecutionPolicy Bypass -File C:/hello.ps1"
]
}
}
run.sh #!/bin/bash
../../../../../ bin / check_or_create_ssh_key . sh
../../../../../ bin / apply . sh aws
hello.ps1 $hello = "Hello " + $env : COMPUTERNAME
Write - Host $hello
Set - Content "hello.txt" $hello - Force
user_data.txt < powershell >
#https://github.com/sdu-rds/beagile-frontera-golden-image/blob/master/packer/scripts/bootstrap.txt
write - output "Running User Data Script"
write - host "(host) Running User Data Script"
Set - ExecutionPolicy Unrestricted - Scope LocalMachine - Force - ErrorAction Ignore
# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"
# Remove HTTP listener
Remove - Item - Path WSMan :\ Localhost \ listener \ listener * - Recurse
# Create a self-signed certificate to let ssl work
$Cert = New - SelfSignedCertificate - CertstoreLocation Cert :\ LocalMachine \ My - DnsName "packer"
New - Item - Path WSMan :\ LocalHost \ Listener - Transport HTTPS - Address * - CertificateThumbPrint $Cert . Thumbprint - Force
# WinRM
write - output "Setting up WinRM"
write - host "(host) setting up WinRM"
cmd . exe / c winrm quickconfig - q
cmd . exe / c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd . exe / c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd . exe / c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd . exe / c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd . exe / c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd . exe / c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd . exe / c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd . exe / c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`" 5986 ` ";Hostname=`" packer ` ";CertificateThumbprint=`" $ ( $Cert . Thumbprint )` "}"
cmd . exe / c netsh advfirewall firewall set rule group = "remote administration" new enable = yes
cmd . exe / c netsh advfirewall firewall set rule name = "WinRM-HTTPS" new action = allow
cmd . exe / c netsh firewall add portopening TCP 5986 "Port 5986"
cmd . exe / c net stop winrm
cmd . exe / c sc config winrm start = auto
cmd . exe / c net start winrm
</ powershell >
aws_instance/remote-exec/inline/windows/ Connection to Windows instances should be done using WinRM. In this example WinRM is enabled in the instance’s user_data.
After that, the assigned password is retrieved using the get_password_data
argument and the private key. We use the Administrator
user and its retrieved password to connect to the instance, copy the hello.ps1 script and execute it.
To run this:
../../../../../bin/apply_aws.sh
destroy.sh #!/bin/bash
../../../../../ bin / destroy . sh aws
main.tf # Summary: Run a command in a newly-created Windows machine
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_instance/remote-exec/inline/windows"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc
data "aws_vpc" "changeme_aws_vpc" {
default = true
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path" {
description = "SSH private key file path"
default = "~/.ssh/id_rsa"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_remote_exec_inline_windows_ssh_public_key_path" {
description = "SSH public key file path"
default = "~/.ssh/id_rsa.pub"
}
# Explanation: Create an SSH key pair for accessing the EC2 instance
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "changeme_remote_exec_inline_windows_key_pair" {
public_key = file ( var . changeme_aws_instance_remote_exec_inline_windows_ssh_public_key_path )
}
# Explanation: Create our default security group to access the instance, over specific protocols
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_remote_exec_inline_windows_security_group" {
vpc_id = data . aws_vpc . changeme_aws_vpc . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_windows_security_group_rule_outgoing_any" {
security_group_id = aws_security_group . changeme_remote_exec_inline_windows_security_group . id
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_remote_exec_inline_security_group_rule_incoming_rdp" {
security_group_id = aws_security_group . changeme_remote_exec_inline_windows_security_group . id
type = "ingress"
from_port = 3389
to_port = 3389
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_incoming_winrm" {
security_group_id = aws_security_group . changeme_remote_exec_inline_windows_security_group . id
type = "ingress"
from_port = 5986
to_port = 5986
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_remote_exec_inline_windows_aws_instance" {
instance_type = "t2.micro"
ami = "ami-0f93c815788872c5d"
key_name = aws_key_pair . changeme_remote_exec_inline_windows_key_pair . id # the name of the SSH keypair to use for provisioning
vpc_security_group_ids = [ aws_security_group . changeme_remote_exec_inline_windows_security_group . id ]
user_data = file ( "scripts/user_data.txt" )
get_password_data = true
tags = { Name = "terraform-examples" }
}
# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_admin_password" {
value = rsadecrypt ( aws_instance . changeme_remote_exec_inline_windows_aws_instance . password_data , file ( var . changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path ))
}
# Documentation: https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource
resource "null_resource" "changeme_provision_files" {
# Documentation: https://www.terraform.io/docs/language/resources/provisioners/connection.html
connection {
host = aws_instance . changeme_remote_exec_inline_windows_aws_instance . public_ip
type = "winrm"
user = "Administrator"
password = rsadecrypt ( aws_instance . changeme_remote_exec_inline_windows_aws_instance . password_data , file ( var . changeme_aws_instance_remote_exec_inline_windows_ssh_private_key_path ))
https = true
insecure = true
port = 5986
timeout = "1m"
}
# Documentation https://www.terraform.io/docs/language/resources/provisioners/index.html
provisioner "file" {
source = "scripts/hello.ps1"
destination = "C:/hello.ps1"
}
# Documentation: https://www.terraform.io/docs/language/resources/provisioners/remote-exec.html
provisioner "remote-exec" {
inline = [
"powershell.exe -ExecutionPolicy Bypass -File C:/hello.ps1"
]
}
}
run.sh #!/bin/bash
../../../../../ bin / check_or_create_ssh_key . sh
../../../../../ bin / apply . sh aws
hello.ps1 $hello = "Hello " + $env : COMPUTERNAME
Write - Host $hello
Set - Content "hello.txt" $hello - Force
user_data.txt < powershell >
#https://github.com/sdu-rds/beagile-frontera-golden-image/blob/master/packer/scripts/bootstrap.txt
write - output "Running User Data Script"
write - host "(host) Running User Data Script"
Set - ExecutionPolicy Unrestricted - Scope LocalMachine - Force - ErrorAction Ignore
# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"
# Remove HTTP listener
Remove - Item - Path WSMan :\ Localhost \ listener \ listener * - Recurse
# Create a self-signed certificate to let ssl work
$Cert = New - SelfSignedCertificate - CertstoreLocation Cert :\ LocalMachine \ My - DnsName "packer"
New - Item - Path WSMan :\ LocalHost \ Listener - Transport HTTPS - Address * - CertificateThumbPrint $Cert . Thumbprint - Force
# WinRM
write - output "Setting up WinRM"
write - host "(host) setting up WinRM"
cmd . exe / c winrm quickconfig - q
cmd . exe / c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd . exe / c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd . exe / c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd . exe / c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd . exe / c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd . exe / c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd . exe / c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd . exe / c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`" 5986 ` ";Hostname=`" packer ` ";CertificateThumbprint=`" $ ( $Cert . Thumbprint )` "}"
cmd . exe / c netsh advfirewall firewall set rule group = "remote administration" new enable = yes
cmd . exe / c netsh advfirewall firewall set rule name = "WinRM-HTTPS" new action = allow
cmd . exe / c netsh firewall add portopening TCP 5986 "Port 5986"
cmd . exe / c net stop winrm
cmd . exe / c sc config winrm start = auto
cmd . exe / c net start winrm
</ powershell >
aws_instance/remote-exec/inline/windows/scripts/ hello.ps1 $hello = "Hello " + $env : COMPUTERNAME
Write - Host $hello
Set - Content "hello.txt" $hello - Force
user_data.txt < powershell >
#https://github.com/sdu-rds/beagile-frontera-golden-image/blob/master/packer/scripts/bootstrap.txt
write - output "Running User Data Script"
write - host "(host) Running User Data Script"
Set - ExecutionPolicy Unrestricted - Scope LocalMachine - Force - ErrorAction Ignore
# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"
# Remove HTTP listener
Remove - Item - Path WSMan :\ Localhost \ listener \ listener * - Recurse
# Create a self-signed certificate to let ssl work
$Cert = New - SelfSignedCertificate - CertstoreLocation Cert :\ LocalMachine \ My - DnsName "packer"
New - Item - Path WSMan :\ LocalHost \ Listener - Transport HTTPS - Address * - CertificateThumbPrint $Cert . Thumbprint - Force
# WinRM
write - output "Setting up WinRM"
write - host "(host) setting up WinRM"
cmd . exe / c winrm quickconfig - q
cmd . exe / c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd . exe / c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd . exe / c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd . exe / c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd . exe / c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd . exe / c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd . exe / c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd . exe / c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`" 5986 ` ";Hostname=`" packer ` ";CertificateThumbprint=`" $ ( $Cert . Thumbprint )` "}"
cmd . exe / c netsh advfirewall firewall set rule group = "remote administration" new enable = yes
cmd . exe / c netsh advfirewall firewall set rule name = "WinRM-HTTPS" new action = allow
cmd . exe / c netsh firewall add portopening TCP 5986 "Port 5986"
cmd . exe / c net stop winrm
cmd . exe / c sc config winrm start = auto
cmd . exe / c net start winrm
</ powershell >
aws_instance/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Simplest example of an aws_instance resource
#
# Note: This example simply creates the VM, but does not set up a keypair,
# or networking such that you can ssh into it from the internet.
# For a more complete example, see `aws/aws_instance/remote_exec/inline`.
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_instance/simple"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_aws_resource_simple" {
instance_type = "t2.nano"
ami = "ami-0ddbdea833a8d2f0d"
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_instance/simple_ssh_access/ To run this:
../../../../bin/apply_aws.sh
destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Remote execution using default expected location of your ssh keys,
# and setup of provider connection.
#
# Note: assumes you have a keypair set up in the location specified in
# `changeme_aws_instance_simple_ssh_access_ssh_private_key_path.default` below.
# This has been set to a useful default of `~/.ssh/id_rsa`.
# You can retrieve the public IP address by looking at the output of `terraform show`,
# eg `terraform show | grep public_ip`.
# You should then be able to log in with, eg: `ssh -i ~/.ssh/id_rsa ubuntu@<<PUBLIC IP ADDRESS>>`.
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_instance/simple_ssh_access"
}
}
}
# Documentation: https://www.terraform.io/docs/language/data-sources/index.html
data "aws_vpc" "changeme_aws_simple_ssh_access_vpc_default" {
default = true
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_simple_ssh_access_ssh_private_key_path" {
description = "SSH private key file path"
default = "~/.ssh/id_rsa"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_simple_ssh_access_ssh_public_key_path" {
description = "SSH public key file path"
default = "~/.ssh/id_rsa.pub"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_instance_simple_ssh_access_ssh_username" {
description = "Default username built into the AMI"
default = "ubuntu"
}
# Explanation: Create an SSH key pair for accessing the EC2 instance
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair
resource "aws_key_pair" "changeme_simple_ssh_access_aws_key_pair" {
public_key = file ( var . changeme_aws_instance_simple_ssh_access_ssh_public_key_path )
}
# Explanation: Create our default security group to access the instance, over specific protocols
#
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_simple_ssh_access_security_group" {
vpc_id = data . aws_vpc . changeme_aws_simple_ssh_access_vpc_default . id
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_simple_ssh_access_security_group_rule_outgoing_any" {
security_group_id = aws_security_group . changeme_simple_ssh_access_security_group . id
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule
resource "aws_security_group_rule" "changeme_simple_ssh_access_security_group_rule_incoming_ssh" {
security_group_id = aws_security_group . changeme_simple_ssh_access_security_group . id
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "changeme_simple_ssh_access_aws_instance" {
# Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
instance_type = "t2.nano"
ami = "ami-0ddbdea833a8d2f0d"
key_name = aws_key_pair . changeme_simple_ssh_access_aws_key_pair . id # the name of the SSH keypair to use for provisioning
vpc_security_group_ids = [ aws_security_group . changeme_simple_ssh_access_security_group . id ]
}
run.sh #!/bin/bash
../../../ bin / check_or_create_ssh_key . sh
../../../ bin / apply . sh aws
aws_lambda_function/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a lambda function in AWS
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
profile = "terraform-examples"
default_tags {
tags = {
cs_terraform_examples = "aws_lambda_function/simple"
}
}
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_lambda_function_name" {
description = "the name of your stack, e.g. \" demo \" "
default = "lambda-example"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_lambda_function_runtime" {
description = "the runtime environment of your function"
default = "nodejs12.x"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_lambda_function_zip" {
description = "the zip file containing your code for your lambda function"
default = "lambda_function_payload.zip"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_lambda_function_handler" {
description = "the name of the handler function"
default = "main.handler"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "changeme_lambda_function_iam_role" {
name = "${var.changeme_lambda_function_name}-lambda-role"
assume_role_policy = << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_lambda_function" "changeme_lambda_function" {
filename = var . changeme_lambda_function_zip
function_name = var . changeme_lambda_function_name
role = aws_iam_role . changeme_lambda_function_iam_role . arn
handler = var . changeme_lambda_function_handler
# The filebase64sha256() function is available in Terraform 0.11.12 and later
# For Terraform 0.11.11 and earlier, use the base64sha256() function and the file() function:
# source_code_hash = "${base64sha256(file("lambda_function_payload.zip"))}"
source_code_hash = filebase64sha256 ( "${var.changeme_lambda_function_zip}" )
runtime = var . changeme_lambda_function_runtime
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_rds_cluster/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create an RDS Aurora MySQL 1 Cluster instance that does not inherit configuration from the cluster
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
profile = "terraform-examples"
default_tags {
tags = {
cs_terraform_examples = "aws_rds_cluster/simple"
}
}
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_aurora_username" {
description = "the username for the login credentials to your db"
default = "username_example"
}
# Documentation: https://www.terraform.io/docs/language/values/variables.html
variable "changeme_aws_aurora_password" {
description = "the password, which must be more than 8 characters long"
default = "password_example"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster
resource "aws_rds_cluster" "changeme_aws_aurora_cluster" {
# The login credentials are stored as plain-text in the state files
# https://www.terraform.io/docs/language/state/sensitive-data.html
# For security, use a secrets manager
# https://registry.terraform.io/modules/yurymkomarov/rds-aurora-cluster/aws/latest#secretsmanager_secret
master_username = var . changeme_aws_aurora_username
master_password = var . changeme_aws_aurora_password
skip_final_snapshot = true
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_route53/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create a simple route53 zone and TXT record
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_route53/simple"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone
resource "aws_route53_zone" "changeme_aws_route53_simple_zone" {
name = "changeme.com"
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record
resource "aws_route53_record" "changeme_aws_route53_simple_record" {
zone_id = aws_route53_zone . changeme_aws_route53_simple_zone . zone_id
name = "changeme.com"
type = "TXT"
ttl = "300"
records = [ "changeme" ]
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_s3_bucket/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Create an S3 bucket
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_s3_bucket/simple"
}
}
}
# Explanation: This resource is not necessary for the creation of an S3 bucket, but is here to ensure that
# the S3 bucket name is unique.
#
# Documentation: https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id
resource "random_id" "changeme_bucket_name" {
byte_length = 16
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket
resource "aws_s3_bucket" "changeme_aws_s3_bucket_simple" {
bucket = "te-${random_id.changeme_bucket_name.hex}"
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_security_group/dynamic/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Uses 'dynamic' to create multiple 'ingress' blocks within an 'aws_security_group' resource.
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_security_group/dynamic"
}
}
}
# Documentation: https://www.terraform.io/docs/language/values/locals.html
locals {
ports = [ 80 , 443 , 8080 ]
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_aws_security_group_dynamic" {
name = "changeme-aws-security-group-dynamic"
# Documentation: https://www.terraform.io/docs/language/expressions/dynamic-blocks.html
dynamic "ingress" {
for_each = local . ports
content {
description = "changeme-aws-security-group-dynamic-ingress-${ingress.key}"
from_port = ingress . value
to_port = ingress . value
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_security_group/open/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: A completely open security group
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_secrurity_group/open"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_aws_security_group_open" {
name = "changeme_aws_security_group_open_name"
description = "Allow all traffic"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [ "0.0.0.0/0" ]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [ "0.0.0.0/0" ]
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_security_group/ssh/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
main.tf # Summary: Security group that allows SSH connections
# https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_security_group/ssh"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "changeme_aws_security_group_ssh" {
name = "changeme_aws_security_group_ssh_name"
description = "Allow SSH inbound traffic"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [ "0.0.0.0/0" ]
}
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_vpc/count/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
import.sh #!/bin/bash
cd "${0%/*}" || exit 1
echo '================================================================================'
echo "In $(pwd), running $0"
echo '================================================================================'
INIT_DONE = "N"
VPC_IDS = $ ( aws ec2 describe - vpcs | jq - r '.Vpcs[] | select(.Tags and .Tags[].Key=="cs_terraform_examples" and .Tags[].Value=="aws_vpc/count") | .VpcId' )
count = 0
for vpc_id in $VPC_IDS
do
if [[ $ { INIT_DONE } == "N" ]]
then
INIT_DONE = "Y"
terraform init
fi
terraform import "aws_vpc.changeme_aws_vpc_count[${count}]" "$vpc_id"
(( count ++))
done
main.tf # Summary: Example of 'for' block
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_vpc/count"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc
resource "aws_vpc" "changeme_aws_vpc_count" {
count = 3
cidr_block = format ( "172.%d.0.0/16" , 16 + count . index )
}
# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_aws_vpc_count_splat" {
value = aws_vpc . changeme_aws_vpc_count [ * ] . cidr_block
}
# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_aws_vpc_count_for" {
# Documentation: https://www.terraform.io/docs/language/expressions/for.html
value = [
for vpc in aws_vpc . changeme_aws_vpc_count :
vpc . cidr_block
]
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_vpc/for/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
import.sh #!/bin/bash
cd "${0%/*}" || exit 1
echo '================================================================================'
echo "In $(pwd), running $0"
echo '================================================================================'
INIT_DONE = "N"
VPC_IDS = $ ( aws ec2 describe - vpcs | jq - r '.Vpcs[] | select(.Tags and .Tags[].Key=="cs_terraform_examples" and .Tags[].Value=="aws_vpc/for") | .VpcId' )
count = 0
for vpc_id in $VPC_IDS
do
if [[ $ { INIT_DONE } == "N" ]]
then
INIT_DONE = "Y"
terraform init
fi
terraform import "aws_vpc.changeme_aws_vpc_for[${count}]" "$vpc_id"
(( count ++))
done
main.tf # Summary: Simple example of a 'for' expression in Terraform
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_vpc/for"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
resource "aws_vpc" "changeme_aws_vpc_for" {
# Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
count = 3
cidr_block = format ( "172.%d.0.0/16" , 16 + count . index )
}
# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_aws_vpc_for_output" {
# Documentation: https://www.terraform.io/docs/language/expressions/for.html
value = [
for vpc in aws_vpc . changeme_aws_vpc_for :
vpc . cidr_block
]
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_vpc/simple/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
import.sh #!/bin/bash
cd "${0%/*}" || exit 1
echo '================================================================================'
echo "In $(pwd), running $0"
echo '================================================================================'
INIT_DONE = "N"
VPC_IDS = $ ( aws ec2 describe - vpcs | jq - r '.Vpcs[] | select(.Tags and .Tags[].Key=="cs_terraform_examples" and .Tags[].Value=="aws_vpc/simple") | .VpcId' )
count = 0
for vpc_id in $VPC_IDS
do
if [[ $ { INIT_DONE } == "N" ]]
then
INIT_DONE = "Y"
terraform init
fi
terraform import "aws_vpc.changeme_aws_vpc_simple" "$vpc_id"
(( count ++))
done
main.tf # Summary: Create an AWS VPC
# Documentation: https://www.terraform.io/docs/language/settings/index.html
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_vpc/simple"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc
resource "aws_vpc" "changeme_aws_vpc_simple" {
cidr_block = "10.1.0.0/16"
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws
aws_vpc/splat/ destroy.sh #!/bin/bash
../../../ bin / destroy . sh aws
import.sh #!/bin/bash
cd "${0%/*}" || exit 1
echo '================================================================================'
echo "In $(pwd), running $0"
echo '================================================================================'
INIT_DONE = "N"
VPC_IDS = $ ( aws ec2 describe - vpcs | jq - r '.Vpcs[] | select(.Tags and .Tags[].Key=="cs_terraform_examples" and .Tags[].Value=="aws_vpc/splat") | .VpcId' )
count = 0
for vpc_id in $VPC_IDS
do
if [[ $ { INIT_DONE } == "N" ]]
then
INIT_DONE = "Y"
terraform init
fi
terraform import "aws_vpc.changeme_aws_vpc_splat[${count}]" "$vpc_id"
(( count ++))
done
main.tf # Summary: Uses the 'count' feature to create multiple EC2 instances.
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.38"
}
}
}
# Documentation: https://www.terraform.io/docs/language/providers/requirements.html
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
cs_terraform_examples = "aws_vpc/splat"
}
}
}
# Documentation: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
resource "aws_vpc" "changeme_aws_vpc_splat" {
# Documentation: # Documentation: https://www.terraform.io/docs/language/meta-arguments/count.html
count = 3
cidr_block = format ( "172.%d.0.0/16" , 16 + count . index )
}
# Documentation: https://www.terraform.io/docs/language/values/outputs.html
output "changeme_cidr_block_full_splat" {
# Documentation: https://www.terraform.io/docs/language/expressions/splat.html
value = aws_vpc . changeme_aws_vpc_splat [ * ] . cidr_block
}
run.sh #!/bin/bash
../../../ bin / apply . sh aws