Professional Documents
Culture Documents
Certification Details
60 Minutes 70.50 USD
https://www.hashicorp.com/certification/terraform-associate
Multiple Choice Quiz
Introduction to
Terraform Cloud
Terraform Cloud
Physical Machines
AWS
GCP
Azure
Terraform Cloud
Version
Control
1.0 0.12
Terraform Cloud
Shared State
UI Interface
Secret Management
Access Controls
Private Registry
Policy Controls
Multiple Choice Quiz
Terraform Cloud
Plans
https://www.hashicorp.com/products/terraform/pricing
Terraform Cloud
BUSINESS
SSO
Custom Concurrency
Self-hosted options
Premium Support
Multiple Choice Quiz
Recap -
Infrastructure as
Code
Types of IAC Tools
Types of IAC Tools
Configuration Management
Designed to Install and Manage Software
Version Control
Idempotent
Server Templating Tools
Immutable Infrastructure
Provisioning Tools
Multiple Providers
Which IaC Tools Should I Use?
ec2.yaml
Physical Machines
VMWare
AWS
GCP
Azure
Multiple Choice Quiz
Installing Terraform
& HCL Basics
>_
$ wget https://releases.hashicorp.com/terraform/0.13.0/terraform_0.13.0_linux_amd64.zip
$ unzip terraform_0.13.0_linux_amd64.zip
$ mv terraform /usr/local/bin
$ terraform version
Terraform v0.13.0
HCL – Declarative Language
local.tf
local.tf
aws.tf
>_
$ terraform init
Initializing the backend...
To prevent automatic upgrades to new major versions that may contain breaking
changes, we recommend adding version constraints in a required_providers block
in your configuration, with the constraint strings suggested below.
------------------------------------------------------------------------
------------------------------------------------------------------------
$ cat /root/pets.txt
We love pets!
>_
$ terraform apply –auto-approve
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
local_file.new_file: Creating...
local_file.new_file: Creation complete after 0s
[id=521c5c732c78cb42cc9513ecc7c0638c4a115b55]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
$ cat /root/pets.txt
We love pets!
>_
$ terraform show
# local_file.pet:
resource "local_file" “pet" {
content = "We love pets!"
directory_permission = "0777"
file_permission = "0777"
filename = "/root/pets.txt"
id = "cba595b7d9f94ba1107a46f3f731912d95fb3d2c"
}
local.tf
resource_type
https://registry.terraform.io/providers/hashicorp/local/latest/docs
provider Local provider
resource_type local_file
filename (required)
Content (optional)
Arguments file_permission (optional)
directory_permission (optional)
sensitive_content (optional)
content_base64 (optional)
Multiple Choice Quiz
Update and Destroy
Infrastructure
>_
$ terraform plan
local_file.pet: Refreshing state...
[id=5f8fb950ac60f7f23ef968097cda0a1fd3c11bdf]
----------------------------------------------------------------------
local.tf An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
resource "local_file" "pet" { -/+ destroy and then create replacement
----------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so
Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
>_
$ terraform apply
local_file.pet: Destroying...
[id=fefacccdae259f25533749abfb90e27558256459]
local_file.pet: Destruction complete after 0s
local_file.pet: Creating...
local_file.pet: Creation complete after 0s
[id=fefacccdae259f25533749abfb90e27558256459]
local.tf cat.tf
main.tf
File Name Purpose
$ terraform init
Official
Verified
Community
registry.terraform.io
>_ >_
$ terraform init $ ls /root/terraform-local-file/.terraform
Initializing the backend... plugins
Organizational
Type
Namespace
To prevent automatic upgrades to new maj
contain breaking
changes, we recommend adding version con
required_providers block
in your configuration, with the constrai
below.
* registry.terraform.io/ hashicorp/loc
Hostname Organizational
Ty
Namespace
Multiple Choice Quiz
Multiple Providers
main.tf
$ terraform init
Initializing the backend...
.
.
# random_pet.my-pet will be created
+ resource "random_pet" "my-pet" {
+ id = (known after apply)
+ length = 1
+ prefix = "Mrs"
+ separator = "."
}
random_pet.my-pet: Creating...
random_pet.my-pet: Creation complete after 0s [id=Mrs.hen]
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "1.4.0"
}
}
}
resource "local_file" "pet" {
filename = "/root/pet.txt"
content = "We love pets!"
}
main.tf >_
terraform { $ terraform init
required_providers { Initializing the backend...
local = { Initializing provider plugins...
source = "hashicorp/local" - Finding hashicorp/local versions matching "1.4.0"...
- Installing hashicorp/local v1.4.0...
version = "1.4.0" - Installed hashicorp/local v1.4.0 (signed by HashiCorp)
}
Terraform has been successfully initialized!
}
} You may now begin working with Terraform. Try running
"terraform plan" to see
any changes that are required for your infrastructure. All
resource "local_file" "pet" { Terraform commands
filename = "/root/pet.txt" should now work.
content = "We love pets!" If you ever set or change modules or backend configuration for
} Terraform,
rerun this command to reinitialize your working directory. If
you forget, other
commands will detect it and remind you to do so if necessary.
main.tf >_
terraform { $ terraform init
required_providers { Initializing the backend...
local = {
Initializing provider plugins...
source = "hashicorp/local" - Finding hashicorp/local versions matching "> 1.2.0, <
version
version == "1.4.0"
">
"<
"!=1.2.0,
1.4.0"
1.1.0"
2.0.0"< 2.0.0, != 1.4.0" 2.0.0, != 1.4.0"...
} - Installing hashicorp/local v1.3.0...
} - Installed hashicorp/local v1.3.0 (signed by
HashiCorp)
}
Terraform has been successfully initialized!
resource "local_file" "pet" {
filename = "/root/pet.txt"
content = "We love pets!"
}
main.tf >_
terraform { $ terraform init
required_providers { Initializing the backend...
local = {
Initializing provider plugins...
source = "hashicorp/local"
- Finding hashicorp/local versions matching "~>
version
version === "1.4.0"
version ">
"!=1.2.0,
"<
"~> 2.0.0"< 2.0.0, != 1.4.0"
1.4.0"
1.1.0"
1.2"
1.2.0" 1.2.0"...
} - Installing hashicorp/local v1.2.2...
} - Installed hashicorp/local v1.2.2 (signed by
HashiCorp)
}
Terraform has been successfully initialized!
resource "local_file" "pet" {
filename = "/root/pet.txt"
content = "We love pets!"
}
Multiple Choice Quiz
Aliases
main.tf
provider "aws" {
region = "ca-central-1“
alias = "central"
}
>_
$ terraform show
# aws_key_pair.alpha:
resource "aws_key_pair" "alpha" {
arn = "arn:aws:ec2:us-east-1::key-pair/alpha"
fingerprint = "d7:ff:a6:63:18:64:9c:57:a1:ee:ca:a4:ad:c2:81:62"
id = "alpha"
key_name = "alpha"
public_key = "ssh-rsa
AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8gi
upGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKV
HO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwW
dhXmXSrbX8ZbabVohBK41 alpha@a-server"
tags_all = {}
}
# aws_key_pair.beta:
resource "aws_key_pair" "beta" {
arn = "arn:aws:ec2:ca-central-1::key-pair/beta"
fingerprint = "d7:ff:a6:63:18:64:9c:57:a1:ee:ca:a4:ad:c2:81:62"
id = "beta"
key_name = "beta"
public_key = "ssh-rsa
AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8gi
upGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKV
HO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwW
dhXmXSrbX8ZbabVohBK41 beta@b-server"
tags_all = {}
}
Multiple Choice Quiz
Define Input
Variables
main.tf variables.tf
}
Interactive Mode
>_
$ terraform apply
var.ami
Enter a value: ami-0edab43b6fa892279
var.instance_type
Enter a value: t2.micro
Command Line Flags
>_
>_
$ export TF_VAR_instance_type="t2.micro"
$ export TF_VAR_ami="ami-0edab43b6fa892279"
$ terraform apply
Variable Definition Files
variable.tfvars
ami="ami-0edab43b6fa892279"
instance_type="t2.micro"
>_
terraform.tfvars | terraform.tfvars.json
Automatically Loaded
*.auto.tfvars | *.auto.tfvars.json
Variable Definition Precedence
Order Option
>_
1 Environment Variables
$ export TF_VAR_type= "t2.nano" 1?
2 terraform.tfvars
variable.auto.tfvars
type = "t3.small" 3?
>_
variable "instance_type" {
}
variables.tf
variable "ami" {
default = "ami-0edab43b6fa892279"
description = "Type of AMI to use"
type = string
sensitive = true
}
variable "instance_type" {
default = "t2.micro"
description = "Size of EC2"
type = string
sensitive = false
}
variables.tf
variable "ami" {
type = string
description = "The id of the machine image (AMI) to use for the server."
validation {
condition = substr(var.ami, 0, 4) == "ami-"
error_message = "The AMI should start with \"ami-\"."
}
}
>_
$ terraform apply –var "ami=abc-11223"
Error: Invalid value for variable
on main.tf line 1:
1: variable "ami" {
The image_id value must be a valid AMI id, starting with "ami-".
} bool true/false
variable "instance_type" {
default = "t2.micro" any Default Value
string "t2.micro"
number 2
bool true/false
region1 = us-east-1
map
region2 = us-west-2
Complex Data
object
Structure
Complex Data
tuple
Structure
variables.tf
variable "count" {
default = 2
type = number
description = "Count of VM’s"
}
variable "monitoring" {
default = true
type = bool
description = "Enable detailed monitoring"
}
variables.tf
variable "count" {
default = 2"2"
type = number
description = "Count of VM’s"
}
variable "monitoring" {
default = "true"
true
type = bool
description = "Enable detailed monitoring"
}
variables.tf
variable "monitoring" {
default = 1
type = bool
description = "Enable detailed monitoring"
}
>_
$ terraform init
This default value is not compatible with the variable's type constraint: bool
required.
List
variables.tf maint.tf
Index Value
0 web1
1 web2
2 web3
Map
variables.tf maint.tf
Key Value
production m5.large
development t2.micro
List of a Type
variables.tf variables.tf
variables.tf >_
$ terraform plan
variable "prefix" { Error: Invalid default value for variable
variables.tf variables.tf
variable "instance_type" { variable "server_count" {
default = { default = {
"production" = "m5.large" "web" = 3
"development" = "t2.micro" "db" = 1
} "agent" = 2
type = map(string) }
} type = map(number)
}
Set
variables.tf variables.tf
variable "servers" { variable "prefix" {
default = ["web1", "web2", "web3"] default = ["web1", "web2", "web2"]
type = set(string) type = set(string)
} }
variables.tf variables.tf
variable "db" { variable "db" {
default = ["db1", "db2"] default = ["db1", "db2", "db1" ]
type = set(string) type = set(string)
} }
variables.tf variables.tf
variable "count" { variable "count" {
default = [10, 12, 15] default = [10, 12, 15, 10]
type = set(number) type = set(number)
} }
Objects
Key Example Type
variables.tf
name bella string
variable "bella" {
color brown string type = object({
name = string
age 7 number color = string
age = number
food ["fish", "chicken", "turkey"] list
food = list(string)
favorite_pet true bool
favorite_pet = bool
})
default = {
name = "bella"
color = "brown"
age = 7
food = ["fish", "chicken", "turkey"]
favorite_pet = true
}
}
Tuples
variables.tf
variable web {
type = tuple([string, number, bool])
default = ["web1", 3, true]
variables.tf >_
$ terraform plan
variable db { Error: Invalid default value for variable
type = tuple([string, number, bool])
default = ["db1", 1, true, "db2"] on variables.tf line 3, in variable "db":
3: default = ["db1", 1, true, "db2"]
} This default value is not compatible with the
variable's type constraint:
tuple required.
Multiple Choice Quiz
Resource Attributes
and Dependencies
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair#attributes-reference
main.tf
resource "aws_key_pair" "alpha" {
key_name = "alpha"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3……alpha@a-server"
>_
$ terraform show
# aws_key_pair.alpha:
resource "aws_key_pair" "alpha" {
arn = "arn:aws:ec2:us-east-1::key-pair/alpha"
fingerprint = "d7:ff:a6:63:18:64:9c:57:a1:ee:ca:a4:ad:c2:81:62"
id = "alpha"
key_name = "alpha"
public_key = "ssh-rsa
AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8gi
upGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKV
HO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwW
dhXmXSrbX8ZbabVohBK41 alpha@a-server"
tags_all = {}
}
ami key_name public_key key_name
instance_type
main.tf key_name
}
resource "aws_instance" "cerberus" { <RESOURCE TYPE>.<RESOURCE_NAME>.<ATTRIBUTE>
ami = var.ami
instance_type = var.instance_type
key_name = aws_key_pair.alpha.key_name
}
>_
$ terraform apply
.
.
.
2 1 aws_key_pair.alpha: Creating...
aws_key_pair.alpha: Creation complete after 1s [id=alpha]
aws_instance.cerberus: Creating...
aws_instance.cerberus: Still creating... [10s elapsed]
aws_instance.cerberus: Creation complete after 10s [id=i-
c791dc46a6639d4a7]
}
resource "aws_instance" "web" {
ami = var.web_ami
instance_type = var.db_instance_type web db
depends_on = [
aws_instance.db
]
}
Multiple Choice Quiz
Resource Targetting
main.tf
output "<variable_name>" {
value = "<variable_value>"
<arguments>
}
>_
$ terraform apply
.
.
.
.
Outputs:
pub_ip = 54.214.145.69
>_
$ terraform output
pub_ip = 54.214.145.69
>_
$ terraform output pub_ip
54.214.145.69
Output Variable
SHELL SCRIPTS
Multiple Choice Quiz
Recap Terraform
State
>_
main.tf $ terraform apply
resource "aws_instance" "cerberus" {
.
ami = var.ami
.
instance_type = var.instance_type .
}
aws_instance.cerberus: Creating...
aws_instance.cerberus: Still creating... [10s elapsed]
variables.tf aws_instance.cerberus: Creation complete after 10s [id=i-
c791dc46a6639d4a7]
variable "ami" {
default = "ami-06178cf087598769c" Apply complete! Resources: 1 added, 0 changed, 0 destroyed
}
variable "instance_type" {
default = "m5.large"
}
>_
$ ls
{
"version": 4,
"terraform_version": "0.13.3",
"serial": 2,
"lineage": "ccd95cf0-9966-549b-c7d1-1d2683b3119b",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "aws_instance",
"name": "cerberus",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-06178cf087598769c",
"arn": "arn:aws:ec2:eu-west-2::instance/i-1db6bfe81bd1e3ed7",
"associate_public_ip_address": true,
"availability_zone": "eu-west-2a",
"capacity_reservation_specification": [],
"cpu_core_count": null,
"cpu_threads_per_core": null,
"credit_specification": [],
"disable_api_termination": false,
"ebs_block_device": [],
>_
apply
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
>_
$ terraform apply -refresh=false
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
>_
variables.tf
[terraform-local-file]$ cat terraform.tfstate
variable "ami" {
default = "ami-06178cf087598769c" {
} "version": 4,
variable "instance_type" { "terraform_version": "0.13.3",
default = "m5.large" "serial": 1,
"t3.micro"
} "lineage": "160ca48f-cd6a-bd64-fc1b-0e2e78c2bc10",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "aws_instance",
Plan "name": "cerberus",
"provider":
"provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-06178cf087598769c",
"arn": "arn:aws:ec2:eu-west-2::instance/i-
9d394a982f158e887",
" "instance_state": "running",
"instance_type": "m5.large",
>_ Plan
Init
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
.
.
Resource actions are indicated with the following symbols:
~ update in-place
"dependencies": [
"aws_instance.db"
]
web
Sensitive Data
terraform.tfstate
{
"mode": "managed",
"type": "aws_instance",
"name": "web",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-0a634ae95e11c6f91",
.
.
.
"primary_network_interface_id": "eni-0ccd57b1597e633e0",
"private_dns": "ip-172-31-7-21.us-west-2.compute.internal",
"private_ip": "172.31.7.21",
"public_dns": "ec2-54-71-34-19.us-west-2.compute.amazonaws.com",
"public_ip": "54.71.34.19",
"root_block_device": [
{
"delete_on_termination": true,
"device_name": "/dev/sda1",
"encrypted": false,
"iops": 100,
Terraform State Considerations
Remote State Backends Version
Control
terraform.tfstate main.tf
{ resource "aws_instance" "db" {
"mode": "managed",
"type": "aws_instance",
ami = var.ami
"name": "web", instance_type = var.instance_type
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]", }
"instances": [
{
"schema_version": 1, resource "aws_instance" "web" {
"attributes": { ami = var.ami
"ami": "ami-0a634ae95e11c6f91",
. instance_type = var.instance_type
. depends_on = [ aws_instance.db ]
.
"primary_network_interface_id": "eni-0ccd57b1597e633e0",
"private_dns": "ip-172-31-7-21.us-west-2.compute.internal", }
"private_ip": "172.31.7.21",
"public_dns": "ec2-54-71-34-19.us-west-2.compute.amazonaws.com",
"public_ip": "54.71.34.19",
"root_block_device": [
{
"delete_on_termination": true,
"device_name": "/dev/sda1",
"encrypted": false,
"iops": 100,
"kms_key_id": "",
"volume_id": "vol-070720a3636979c22",
No Manual Edits
terraform.tfstate
{
"mode": "managed",
"type": "aws_instance",
"name": "dev-ec2",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-0a634ae95e11c6f91",
.
.
.
"primary_network_interface_id": "eni-0ccd57b1597e633e0",
"private_dns": "ip-172-31-7-21.us-west-2.compute.internal",
"private_ip": "172.31.7.21",
"public_dns": "ec2-54-71-34-19.us-west-2.compute.amazonaws.com",
"public_ip": "54.71.34.19",
"root_block_device": [
{
"delete_on_termination": true,
"device_name": "/dev/sda1",
"encrypted": false,
"iops": 100,
Multiple Choice Quiz
Remote State
>_
Mapping Configuration to Real World
$ ls
Tracking Metadata main.tf variables.tf terraform.tfstate
Performance
Collaboration
Version
Control
terraform.tfstate
main.tf {
"mode": "managed",
"type": "aws_instance",
resource "aws_instance" "dev-ec2" { "name": "dev-ec2",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
ami = var.ami "instances": [
{
instance_type = var.instance_type "schema_version": 1,
} "attributes": {
"ami": "ami-0a634ae95e11c6f91",
.
.
.
"primary_network_interface_id": "eni-0ccd57b1597e633e0",
"private_dns": "ip-172-31-7-21.us-west-2.compute.internal",
"private_ip": "172.31.7.21",
"public_dns": "ec2-54-71-34-19.us-west-2.compute.amazonaws.com",
"public_ip": "54.71.34.19",
"root_block_device": [
{
"delete_on_termination": true,
"device_name": "/dev/sda1",
"encrypted": false,
"iops": 100,
"kms_key_id": "",
"volume_id": "vol-070720a3636979c22",
"volume_size": 8,
"volume_type": "gp2"
}
>_ Terminal 1 >_ Terminal 2
$ terraform apply $ terraform apply
. Error: Error locking state: Error acquiring the state
. lock: resource temporarily unavailable
." Lock Info:
+ server_side_encryption = (known after apply) ID: fefe3806-007c-084b-be61-cef4cdc77dee
+ storage_class = (known after apply) Path: terraform.tfstate
+ version_id = (known after apply) Operation: OperationTypeApply
} Who: root@iac-server
Version: 0.13.3
Plan: 2 to add, 0 to change, 0 to destroy. Created: 2020-09-22 20:35:27.051330492 +0000 UTC
Info:
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve. Terraform acquires a state lock to protect the state from
being written
Enter a value: yes by multiple users at the same time. Please resolve the
issue above and try
aws_s3_bucket_object.finance-2020: Creating... again. For most commands, you can disable locking with
aws_s3_bucket.finance: Creating... the "-lock=false"
aws_s3_bucket_object.finance-2020: Still creating... flag, but this is not recommended.
[10s elapsed]
aws_s3_bucket.finance: Still creating... [10s
elapsed]
aws_s3_bucket_object.finance-2020: Still creating...
[20s elapsed]
aws_s3_bucket.finance: Still creating... [20s
State Locking
Infrastructure
Operation 1
Terraform State
Local
Operation 2
main.tf terraform.tfstate
user1 user2
main.tf terraform.tfstate
main.tf terraform.tfstate
S3 bucket
State Locking
Infrastructure
Operation 1
Local
Operation 2
State Locking
Security
Remote Backend
Object Value
Bucket kodekloud-terraform-state-bucket01
Key finance/terraform.tfstate
DynamoDB
Table
state-locking
main.tf terraform.tf
Bucket kodekloud-terraform-state-bucket01
Key finance/terraform.tfstate
Region us-west-1
DynamoDB
Table
state-locking
main.tf terraform.tf
>_
$ terraform apply
Backend reinitialization required. Please run "terraform init". Reason: Initial configuration of the requested backend "s3"
The "backend" is the interface that Terraform uses to store state, perform operations, etc. If this message is showing up, it means
that the Terraform configuration you're using is using a custom configuration for the Terraform backend.
Changes to backend configurations require reinitialization. This allows Terraform to setup the new configuration, copy existing
state, etc. This is only done during "terraform init". Please run that command now then try again.
$ terraform init
Initializing the backend...
Do you want to copy existing state to the new backend?
Pre-existing state was found while migrating the previous "local" backend to the newly configured "s3" backend. No existing state
was found in the newly configured "s3" backend. Do you want to copy this state to the new "s3"
backend? Enter "yes" to copy and "no" to start with an empty state.
Successfully configured the backend "s3"! Terraform will automatically use this backend unless the backend configuration changes.
>_
$ rm –rf terraform.tfstate
>_
$ terraform apply
Acquiring state lock. This may take a few moments...
Local_file.pet: Refreshing state... [id=a676sd5665sd]
main.tf >_
main.tf >_
main.tf >_
>_ >_
provider[registry.terraform.io/hashicorp/aws]
terraform output
main.tf >_
}
output pet-name {
value = random_pet.cat.id
sensitive = false
description = "Print the name of the pet"
}
terraform refresh
main.tf >_
$ terraform refresh
random_pet.cat: Refreshing state... [id=huge-owl]
local_file.pet: Refreshing state...
[id=cba595b7d9f94ba1107a46f3f731912d95fb3d2c]
terraform graph
>_
$ terraform graph
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] aws_instance.cerberus (expand)" [label = "aws_instance.cerberus", shape =
"box"]
"[root] provider[\"registry.terraform.io/hashicorp/aws\"]" [label =
"provider[\"registry.terraform.io/hashicorp/aws\"]", shape = "diamond"]
"[root] var.ami" [label = "var.ami", shape = "note"]
"[root] var.instance_type" [label = "var.instance_type", shape = "note"]
"[root] var.region" [label = "var.region", shape = "note"]
"[root] aws_instance.cerberus (expand)" -> "[root]
provider[\"registry.terraform.io/hashicorp/aws\"]"
"[root] aws_instance.cerberus (expand)" -> "[root] var.ami"
"[root] aws_instance.cerberus (expand)" -> "[root] var.instance_type"
"[root] meta.count-boundary (EachMode fixup)" -> "[root] aws_instance.cerberus
(expand)"
"[root] provider[\"registry.terraform.io/hashicorp/aws\"] (close)" -> "[root]
aws_instance.cerberus (expand)"
"[root] provider[\"registry.terraform.io/hashicorp/aws\"]" -> "[root] var.region"
"[root] root" -> "[root] meta.count-boundary (EachMode fixup)"
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/aws\"] (close)"
}
}
terraform.tfstate
>_
{
"mode": "managed",
$ vi terraform.tfstate "type": "aws_instance",
"name": "dev-ec2",
$ terraform state show aws_s3_bucket.finance "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
# terraform state <subcommand> [options] [args] "schema_version": 1,
"attributes": {
"ami": "ami-0a634ae95e11c6f91",
.
.
.
Sub-command "primary_network_interface_id": "eni-0ccd57b1597e633e0",
"private_dns": "ip-172-31-7-21.us-west-2.compute.internal",
"private_ip": "172.31.7.21",
list "public_dns": "ec2-54-71-34-19.us-west-2.compute.amazonaws.com",
"public_ip": "54.71.34.19",
"root_block_device": [
mv {
"delete_on_termination": true,
"device_name": "/dev/sda1",
pull "encrypted": false,
"iops": 100,
"kms_key_id": "",
rm "volume_id": "vol-070720a3636979c22",
"volume_size": 8,
"volume_type": "gp2"
show }
],
push
>_
# terraform state list [options] [address]
versioning {
enabled = false
mfa_delete = false
}
}
main.tf terraform.tfstate
resource "aws_dynamodb_table" "state-locking-db"
"state-locking" {
"resources": [
name = "state-locking"
{
billing_mode = "PAY_PER_REQUEST"
"mode": "managed",
hash_key = "LockID"
"type": "aws_dynamodb_table",
attribute {
"name": "state-locking-db"
"state-locking",
name = "LockID"
"provider":
type = "S"
"provider[\"registry.terraform.io/hashicorp/aws\"
}
]",
}
.
.
>_
# terraform state mv [options] SOURCE DESTINATION
$ terraform state mv aws_dynamodb_table.state-locking aws_dynamodb_table.state-locking-db
Move "aws_dynamodb_table.state-locking" to "aws_dynamodb_table.state-locking-db"
Successfully moved 1 object(s).
aws_dynamodb_table.state-locking-db: Refreshing state... [id=state-locking]
$ terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
>_
$ ls
main.tf provider.tf
>_
ami-2158cf087598787a
ignore_changes
main.tf >_
$ terraform apply
resource "aws_instance" "cerberus" {
aws_instance.webserver: Refreshing state... [id=i-
ami "ami-2158cf087598787a"
= "ami-06178cf087598769c" 05cd83b221911acd5]
instance_type = "m5.large"
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
tags = {
Name = "Cerberus-Webserver"
"Cerberus-Webserver-1"
lifecycle
lifecycle {{
ignore_changes
ignore_changes == [all
tags
]
} }}
Name = Cerberus-Webserver
Multiple Choice Quiz
Data Sources
main.tf
}
resource "aws_instance" "cerberus" {
ami = var.ami
instance_type = var.instance_type
key_name = aws_key_pair.alpha.key_name
}
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/key_pair
main.tf
}
resource "aws_instance" "cerberus" {
ami = var.ami
instance_type = var.instance_type
key_name = data.aws_key_pair.cerberus-key.key_name
}
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/key_pair
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/key_pair
main.tf
}
terraform.tfstate
main.tf variables.tf
main.tf variables.tf
main.tf variables.tf
Name = web1
web2 Name = web2
web3 Name = web3
for_each
main.tf variables.tf
}
>_
$ terraform apply
.
Name = web1 .
Name = web2 Name = web3
.
Plan: 3 to add, 0 to change, 0 to destroy.
for_each
>_
$ terraform state list
iac-server $ terraform state list
aws_instance.web["web1"]
aws_instance.web["web2"]
aws_instance.web["web3"]
$
main.tf
An execution plan has been generated and is shown below. variables.tf
Resource actions are indicated with the following symbols:
- destroy
resource
Terraform "aws_instance"
will perform "web"
the following actions: { variable "ami" {
ami = var.ami
# aws_instance.cerberus["web1"] will be destroyed
default = "ami-06178cf087598769c"
instance_type
- resource = var.instance_type
"aws_instance" "cerberus" { }
- ami = "ami-06178cf087598769c" ->
null count
for_each == =3length(var.webservers)
var.webservers variable "instance_type" {
- arn = "arn:aws:ec2:eu-west- default = "m5.large"
tags = {
2::instance/i-7f267ee9b1a6522ad" -> null
}
- associate_public_ip_address = true -> null
Name
Name == var.webservers[count.index]
- availability_zone each.value = "eu-west-2a" -> null
}
- disable_api_termination = false -> null variable "webservers" {
- ebs_optimized = false -> null
}- get_password_data = false -> null set
type = list
- id = "i-7f267ee9b1a6522ad" -> default = ["web1",
["web2", "web2",
"web3"] "web3"]
null
- instance_state = "running" -> null
- instance_type = "m5.large" -> null }
.
.
.
Plan: 0 to add, 0 to change, 1 to destroy.
.
.
Multiple Choice Quiz
Terraform
Provisioners
Remote Exec
main.tf
resource "aws_instance" "webserver" { Remote Instance (EC2)
ami = "ami-0edab43b6fa892279"
instance_type = "t2.micro"
provisioner "remote-exec" {
inline = [ "sudo apt update",
"sudo apt install nginx -y", SSH WINRM
"sudo systemctl enable nginx",
"sudo systemctl start nginx",
]
}
key_name = aws_key_pair.web.id
vpc_security_group_ids = [ aws_security_group.ssh-access.id ]
}
resource "aws_security_group" "ssh-access" { Local Machine
<< code hidden >>
}
resource "aws_key_pair" "web" {
<< code hidden >>
} ✔Network Connectivity (Security Group)
✔Authentication (SSH Key Pair)
Remote Exec
main.tf >_
resource "aws_instance" "webserver" { $ terraform apply
ami = "ami-0edab43b6fa892279" aws_key_pair.web: Creating...
aws_security_group.ssh-access: Creating...
instance_type = "t2.micro" aws_key_pair.web: Creation complete after 0s [id=terraform-
20201015013048509100000001]
provisioner
user_data = "remote-exec"
<<-EOF { aws_security_group.ssh-access: Creation complete after 1s [id=sg-0
inline = #!/bin/bash
[ "sudo apt update", aws_instance.webserver: Creating...
aws_instance.webserver: Still creating... [10s elapsed]
sudo"sudo
apt apt install nginx -y",
update aws_instance.webserver: Still creating... [20s elapsed]
sudo"sudo
apt systemctl enable
install nginx -y nginx", aws_instance.webserver: Still creating... [30s elapsed]
"sudo systemctl start nginx", aws_instance.webserver: Provisioning with 'remote-exec'...
systemctl enable nginx aws_instance.webserver (remote-exec): Connecting to remote host vi
]
systemctl start nginx aws_instance.webserver (remote-exec): Host: 3.96.136.157
} EOF aws_instance.webserver (remote-exec): User: ubuntu
aws_instance.webserver (remote-exec): Password: false
connection { aws_instance.webserver (remote-exec): Private key: true
type = "ssh" aws_instance.webserver (remote-exec): Certificate: false
host = self.public_ip aws_instance.webserver (remote-exec): SSH Agent: false
aws_instance.webserver (remote-exec): Checking Host Key: false
user = "ubuntu" aws_instance.webserver: Still creating... [40s elapsed]
private_key = file("/root/.ssh/web") aws_instance.webserver (remote-exec): Connecting to remote host vi
aws_instance.webserver (remote-exec): Host: 3.96.136.157
} aws_instance.webserver (remote-exec): User: ubuntu
key_name = aws_key_pair.web.id aws_instance.webserver (remote-exec): Password: false
aws_instance.webserver (remote-exec): Private key: true
vpc_security_group_ids = [ aws_security_group.ssh-access.id ] aws_instance.webserver (remote-exec): Certificate: false
} aws_instance.webserver (remote-exec): SSH Agent: false
aws_instance.webserver (remote-exec): Checking Host Key: false
resource "aws_key_pair" "web" { aws_instance.webserver (remote-exec): Connected!
aws_instance.webserver: Still creating... [50s elapsed]
<< code hidden >> aws_instance.webserver: Creation complete after 50s [id=i-068fad30
Local Exec
main.tf
resource "aws_instance" "webserver" { Remote Instance (EC2)
ami = "ami-0edab43b6fa892279"
instance_type = "t2.micro"
provisioner "local-exec" {
command = "echo ${aws_instance.webserver2.public_ip} >> /tmp/ips.txt"
}
>_
Local Machine
$ cat /tmp/ips.txt
54.214.68.27
Destroy Time Provisioner
main.tf
>_
$ cat /tmp/instance_state.txt
Instance 3.96.136.157 Deleted!
Failure Behavior
main.tf
>_
$ terraform apply
Error: Error running command 'echo 35.183.14.192 > /temp/pub_ip.txt': exit status 1.
Output: The system cannot find the path specified.
Failure Behavior
main.tf
>_
$ terraform apply
aws_instance.webserver (local-exec) The system cannot find the path specified.
aws_instance.project: Creation complete after 22s [id=i-01585c2b9dbc445db]
>_
$ terraform apply
Plan: 1 to add, 0 to change, 0 to destroy.
aws_instance.webserver: Creating...
aws_instance.webserver: Still creating... [10s elapsed]
aws_instance.webserver: Still creating... [20s elapsed]
aws_instance.webserver: Still creating... [30s elapsed]
aws_instance.webserver: Provisioning with 'local-exec'...
aws_instance.webserver (local-exec): Executing: ["cmd" "/C" "echo 35.183.14.192 > /temp/pub_ip.txt"]
aws_instance.webserver (local-exec): The system cannot find the path specified.
Error: Error running command 'echo 35.183.14.192 > /temp/pub_ip.txt': exit status 1. Output: The system
cannot find the path specified.
Taint
>_
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not
be
persisted to local or remote state storage.
-----------------------------------------------------------------------
-
------------------------------------------------------------------------
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
Multiple Choice Quiz
Debugging
Log Levels
>_
# export TF_LOG=<log_level> INFO
$ export TF_LOG=TRACE
WARNING
ERROR
DEBUG
TRACE
>_
$ terraform plan
----
2020/10/18 22:08:30 [INFO] Terraform version: 0.13.0
2020/10/18 22:08:30 [INFO] Go runtime version: go1.14.2
2020/10/18 22:08:30 [INFO] CLI args: []string{"C:\\Windows\\system32\\terraform.exe", "plan"}
2020/10/18 22:08:30 [DEBUG] Attempting to open CLI config file: C:\Users\vpala\AppData\Roaming\terraform.rc
2020/10/18 22:08:30 [DEBUG] File doesn't exist, but doesn't need to. Ignoring.
2020/10/18 22:08:30 [DEBUG] ignoring non-existing provider search directory terraform.d/plugins
2020/10/18 22:08:30 [DEBUG] ignoring non-existing provider search directory C:\Users\vpala\AppData\Roaming\terraform.d\plugins
2020/10/18 22:08:30 [DEBUG] ignoring non-existing provider search directory
C:\Users\vpala\AppData\Roaming\HashiCorp\Terraform\plugins
2020/10/18 22:08:30 [INFO] CLI command args: []string{"plan"}
2020/10/18 22:08:30 [WARN] Log levels other than TRACE are currently unreliable, and are supported only for backward
compatibility.
Use TF_LOG=TRACE to see Terraform's internal logs.
----
2020/10/18 22:08:30 [DEBUG] New state was assigned lineage "f413959c-538a-f9ce-524e-1615073518d4"
2020/10/18 22:08:30 [DEBUG] checking for provisioner in "."
2020/10/18 22:08:30 [DEBUG] checking for provisioner in "C:\\Windows\\system32"
2020/10/18 22:08:30 [INFO] Failed to read plugin lock file .terraform\plugins\windows_amd64\lock.json: open
.terraform\plugins\windows_amd64\lock.json: The system cannot find the path specified.
2020/10/18 22:08:30 [INFO] backend/local: starting Plan operation
2020-10-18T22:08:30.625-0400 [INFO] plugin: configuring client automatic mTLS
2020-10-18T22:08:30.646-0400 [DEBUG] plugin: starting plugin:
path=.terraform/plugins/registry.terraform.io/hashicorp/aws/3.11.0/windows_amd64/terraform-provider-aws_v3.11.0_x5.exe
args=[.terraform/plugins/registry.terraform.io/hashicorp/aws/3.11.0/windows_amd64/terraform-provider-aws_v3.11.0_x5.exe]
2020-10-18T22:08:30.935-0400 [DEBUG] plugin: plugin started:
path=.terraform/plugins/registry.terraform.io/hashicorp/aws/3.11.0/windows_amd64/terraform-provider-aws_v3.11.0_x5.exe
pid=34016
2020-10-18T22:08:30.935-0400 [DEBUG] plugin: waiting for RPC address:
path=.terraform/plugins/registry.terraform.io/hashicorp/aws/3.11.0/windows_amd64/terraform-provider-aws_v3.11.0_x5.exe
2020-10-18T22:08:30.974-0400 [INFO] plugin.terraform-provider-aws_v3.11.0_x5.exe: configuring server automatic mTLS:
>_
$ export TF_LOG_PATH=/tmp/terraform.log
$ unset TF_LOG_PATH
Multiple Choice Quiz
Terraform Import
EC2 DynamoDB Elastic Block Store EC2 DynamoDB Route 53
S3 Route 53 VPC
S3 Route 53 VPC
>_
# terraform import <resource_type>.<resource_name> <attribute>
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
terraform.tfstate
{
"mode": "managed",
"type": "aws_instance",
"name": "webserver-2",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-0edab43b6fa892279",
"instance_state": "running",
"instance_type": "t2.micro",
"key_name": "ws",
.
"tags": {
"Name": "old-ec2"
},
.
.
"vpc_security_group_ids": [
"sg-8064fdee"
]
},
.
.
}
]
},
main.tf
resource "aws_instance" "webserver-2" {
>_
main.tf
resource "aws_instance" "webserver-2" {
ami = "ami-0edab43b6fa892279"
instance_type = "t2.micro"
key_name = "ws"
vpc_security_group_ids = ["sg-8064fdee"]
>_
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
Multiple Choice Quiz
Terraform Modules
Root Module
>_
$ ls /root/terraform-projects/aws-instance
main.tf variables.tf
/root
main.tf
resource "aws_instance" "webserver" {
terraform-projects
ami = var.ami sss
instance_type = var.instance_type
key_name = var.key
} Root Module
aws-instance
variables.tf
variable ami {
type = string
default sss
= "ami-0edab43b6fa892279"
description = "Ubuntu AMI ID in the ca-
central-1 region"
}
Root Module
>_
/root
$ mkdir /root/terraform-projects/development
main.tf
terraform-projects
main.tf
main.tf
terraform-projects
main.tf
main.tf
terraform-projects
main.tf
main.tf
terraform-projects
main.tf
https://registry.terraform.io/browse/modules
Terraform Registry
Terraform Module
Terraform Module
main.tf
module "security-group_ssh" {
source = "terraform-aws-modules/security-group/aws/modules/ssh"
version = "3.16.0"
# insert the 2 required variables here
vpc_id = "vpc-7d8d215"
ingress_cidr_blocks = [ "10.10.0.0/16"]
name = "ssh-access"
>_
$ terraform apply
Downloading terraform-aws-modules/security-group/aws 3.16.0 for security-group_ssh...
- security-group_ssh in .terraform\modules\security-group_ssh\modules\ssh
https://registry.terraform.io/modules/terraform-aws-modules/security-group/aws/latest/submodules/ssh
Simpler Configuration Files
Lower Risk
Re-Usability
Standardized Configuration
Multiple Choice Quiz
Creating and Using
a Module
default-vpc
http-access-sg
aws_instance
aws_s3_bucket
(payroll_app_server)
(paystub_upload)
*flexIt-payroll-alpha-2201c
aws_dynamodb_table
(payroll_data)
*Simplified Architecture
*Default VPC &subnet /No endpoint considerations
*No IAM role considerations
>_
$ mkdir /root/terraform-projects/modules/payroll-app
terraform-projects
app_server.tf
resource "aws_instance" "app_server" {
ami = var.ami modules
instance_type = "t2.medium"
tags = {
sss
Name = "${var.app_region}-app-server"
} payroll-ap
depends_on = [ aws_dynamodb_table.payroll_db,
aws_s3_bucket.payroll_data
]
} dynamodb_table.tf
resource "aws_dynamodb_table" "payroll_db" {
name = "user_data"
billing_mode = "PAY_PER_REQUEST"
s3_bucket.tf hash_key = "EmployeeID"
$ mkdir /root/terraform-projects/us-payroll-app
modules us-payroll-app
main.tf
module "us_payroll" {
source = "../modules/payroll-app" payroll-ap
sss
app_region = "us-east-1"
ami = "ami-24e140119877avm"
}
>_
$ terraform init
Initializing modules...
- us_payroll in .terraform/modules/us_payroll
.
.
module.us_payroll.aws_dynamodb_table.payroll_db: Creating...
module.us_payroll.aws_s3_bucket.payroll_data: Creating...
>_ /root
$ mkdir /root/terraform-projects/uk-payroll-app
provider.tf
provider "aws" {
region = "eu-west-2"
}
>_
$ terraform apply
.
.
module.us_payroll.aws_dynamodb_table.payroll_db: Creating...
module.us_payroll.aws_s3_bucket.payroll_data: Creating...
module.us_payroll.aws_dynamodb_table.payroll_db: Creation complete after 1s [id=user_data]
.
.
# module.us_payroll.aws_dynamodb_table.payroll_db will be c
+ resource "aws_dynamodb_table" "payroll_db" {
+ arn = (known after apply)
+ billing_mode = "PAY_PER_REQUEST"
+ hash_key = "EmployeeID"
+ name = "user_data"
.
.
# module.us_payroll.aws_instance.app_server will be created
+ resource "aws_instance" "app_server" {
+ ami = "ami-35e140119877avm"
Multiple Choice Quiz
Functions, Operators
& Conditional
Expressions
,
Functions
main.tf >_
$ terraform console
resource "aws_iam_policy" "adminUser" {
name = "AdminUsers" > file("/root/terraform-projects/main.tf)
policy = file("admin-policy.json") resource "aws_instance" "development" {
} ami = "ami-0edab43b6fa892279"
instance_type = "t2.micro"
resource "local_file" "pet" { }
filename = var.filename
count = length(var.filename) > length(var.region)
} 3
> toset(var.region)
main.tf [
"ca-central-1",
resource "local_file" "pet" { "us-east-1",
filename = var.filename
for_each = toset(var.region) ]
>
}
variable region {
type = list
default = ["us-east-1",
"us-east-1",
"ca-central-1"]
description = "A list of AWS Regions"
}
Numeric Functions
variables.tf >_
$ terraform console
variable "num" {
type = set(number) > max (-1, 2, -10, 200, -250)
default = [ 250, 10, 11, 5] 200
description = "A set of numbers"
} > min (-1, 2, -10, 200, -250)
-250
> max(var.num...)
250
> ceil(10.1)
11
> ceil(10.9)
11
> floor(10.1)
10
> floor(10.9)
10
String Functions
variables.tf >_
$ terraform console
variable "ami" {
type = string > split(",", "ami-xyz,AMI-ABC,ami-efg")
default = "ami-xyz,AMI-ABC,ami-efg" [ "ami-xyz","AMI-ABC","ami-efg" ]
description = "A string containing ami ids"
} > split(",", var.ami)
[ "ami-xyz","AMI-ABC","ami-efg“ ]
> lower(var.ami)
ami-xyz,ami-abc,ami-efg
> upper(var.ami)
AMI-XYZ,AMI-ABC,AMI-EFG
> title(var.ami)
Ami-Xyz,AMI-ABC,Ami-Efg
> substr(var.ami, 0, 7)
ami-xyz
> substr(var.ami, 8, 7)
AMI-ABC
variables.tf >_
$ terraform console
variable "ami" {
type = list > join(",", ["ami-xyz", "AMI-ABC", "ami-efg"])
default = ["ami-xyz", "AMI-ABC", "ami-efg"] ami-xyz,AMI-ABC,ami-efg
description = "A list of numbers"
} > join(",", var.ami)
ami-xyz,AMI-ABC,ami-efg
Collection Functions
variables.tf >_
$ terraform console
variable "ami" {
type = list > length(var.ami)
default = ["ami-xyz", "AMI-ABC", "ami-efg"] 3
description = "A list of numbers"
} > index(var.ami, "AMI-ABC")
1
> element(var.ami,2)
ami-efg
variables.tf >_
$ terraform console
variable "ami" {
type = map > keys(var.ami)
default = { "us-east-1" = "ami-xyz", [
"ca-central-1" = "ami-efg", "ap-south-1",
"ap-south-1" = "ami-ABC" "ca-central-1",
} "us-east-1",
description = "A map of AMI ID's for specific regions" ]
}
> values(var.ami)
[
"ami-ABC",
"ami-efg",
"ami-xyz",
]
variables.tf >_
$ terraform console
variable "ami" {
type = map > lookup(var.ami, "us-west-2")
default = { "us-east-1" = "ami-xyz", Error: Error in function call
"ca-central-1" = "ami-efg",
"ap-south-1" = "ami-ABC" on <console-input> line 1:
} (source code not available)
description = "A map of AMI ID's for specific regions" |----------------
} | var.ami is map of string with 3 elements
>_
$ terraform console
> 1 + 2
3
> 5 - 3
2
> 2 * 2
4
> 8 / 2
4
Equality Operators
>_
$ terraform console
> 8 == 8
true
8 == 7
false
> 8 != "8"
true
Comparison Operators
>_
$ terraform console
> 5 > 7
false
> 5 > 4
true
> 5 > 5
False
> 5 >= 5
true
> 4 < 5
true
> 3 <= 4
true
Logical Operators
>_ variables.tf
$ terraform console variable special {
type = bool
> 8 > 7 && 8 < 10 default = true
description = "Set to true to
true use special characters"
}
> 8 > 10 && 8 < 10 variable b {
false type = number
default = 25
> 8 > 9 || 8 < 10 }
True
> var.special
true
> ! var.special
false
>_ variables.tf
$ terraform console variable a {
type = number
> var.a > var.b default = 50
}
true variable b {
type = number
> var.a < var.b default = 25
}
false
Outputs:
password = sjsrW]
variables.tf
variable length { $ if [ $length -lt 8 ] Condition
type = number then
description = "The length of the password" length=8;
echo $length;
If True
}
else
echo $length; If False
fi
# Generate Password
condition If True If False
main.tf
output password {
value = random_password.password-generator.result
}
variables.tf
variable length { $ if [ $length -lt 8 ] Condition
type = number then
description = "The length of the password" length=8;
echo $length;
If True
}
else
echo $length; If False
fi
# Generate Password
>_
$ terraform apply -var=length=5
Terraform will perform the following actions:
Outputs:
password = &(1Beiaq
Outputs:
password = 8B@o}{cUzrZ7
Multiple Choice Quiz
Local Values
main.tf
resource "aws_instance" "web" {
ami = "ami-06178cf087598769c"
instance_type = "t2.medium"
tags = {
Department = "finance"
Project = "cerberus"
}
}
main.tf
resource "aws_instance" "web" {
ami = "ami-06178cf087598769c"
instance_type = "t2.medium"
tags = {
Department = "finance"
Project = "cerberus"
}
}
locals {
common_tags = {
Department = "finance"
Project = "cerberus"
}
}
main.tf
resource "aws_instance" "web" {
ami = "ami-06178cf087598769c"
instance_type = "t2.medium"
local.<NAME>
tags = local.common_tags
locals {
common_tags = {
Department = "finance"
Project = "cerberus"
}
}
>_
$ terraform apply
iac-server $ terraform apply
main.tf
resource "aws_s3_bucket" "finance_bucket" {
acl = "private"
bucket = ?local.bucket-prefix
variable "project"
{ {
default
Department
= "cerberus"
= "finance"
} Project = "cerberus"
}
locals {
bucket-prefix = "${var.project}-${random_string.random-suffix.id}-bucket"
}
>_
$ terraform apply –auto-approve
random_string.random-suffix: Creating...
random_string.random-suffix: Creation complete after 0s [id=dhiabk]
aws_s3_bucket.finance_bucket: Creating...
aws_s3_bucket.finance_bucket: Creation complete after 0s [id=cerberus-dhiabk-bucket]
}
Security Group
Inbound 8080, 22
Private Subnet
10.0.2.0/24
VPC
server1 server2
VPC – 10.0.0.0/16
main.tf
tags = {
Name = "private-subnet"
}
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
main.tf
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
main.tf
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
main.tf variables.tf
variable "ingress_ports" {
resource "aws_security_group" "backend-sg" { type = list
name = "backend-sg" default = [22, 8080]
vpc_id = aws_vpc.backend-vpc.id
}
dynamic "ingress" {
for_each = var.ingress_ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
>_
$ terraform apply –auto-approve
aws_vpc.backend-vpc: Creating...
aws_vpc.backend-vpc: Creation complete after 0s [id=vpc-593470c0]
aws_subnet.private-subnet: Creating...
aws_security_group.backend-sg: Creating...
aws_subnet.private-subnet: Creation complete after 1s [id=subnet-fdd6b762]
aws_security_group.backend-sg: Creation complete after 1s [id=sg-a5aa3b711157d4a2b]
}
main.tf variables.tf
variable "ingress_ports" {
resource "aws_security_group" "backend-sg" { type = list
name = "backend-sg" default = [22, 8080]
vpc_id = aws_vpc.backend-vpc.id
}
dynamic "ingress" {
iterator = port
for_each = var.ingress_ports output "to_ports" {
value = aws_security_group.backend-sg.ingress[*].to_port
content {
from_port = port.value
ingress.value }
to_port = ingress.value
port.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
>_
$ terraform output
to_ports = [
22,
8080,
]
Multiple Choice Quiz
Terraform
Workspaces
main.tf
my-application
resource "aws_instance" "webserver" {
variables.tf ami = var.ami
main.tf instance_type = var.instance_type
tags = {
terraform.tfstate Environment = "Development"
}
}
/root/terraform-projects/webserver
variable.tf
variable "ami" {
default = "ami-24e140119877avm"
}
variable "instance_type" {
default = "t2.micro"
}
variable "region" {
default = "ca-central-1"
}
main.tf
my-application
resource "aws_instance" "webserver" {
variables.tf ami = var.ami
main.tf instance_type = var.instance_type
tags = {
terraform.tfstate Environment = "Development"
}
}
development
variable.tf
AMI: ami-0c2f25c1f66a1ff4d
/root/terraform-projects/webserver
main.tf
my-application
variables.tf resource "aws_instance" "webserver" {
ami = var.ami
main.tf instance_type = var.instance_type
lookup(var.instance_type, terraform.workspace)
tags = {
terraform.tfstate Environment = "Development"
}
}
Region: ca-central-1
AMI: ami-0c2f25c1f66a1ff4d
$ terraform apply
Terraform will perform the following actions:
$ ls
main.tf provider.tf terraform.tfstate.d variables.tf
$ tree terraform.tfstate.d/
terraform.tfstate.d/
|-- development
| `-- terraform.tfstate
`-- production
`-- terraform.tfstate
2 directories, 2 files
local_file aws_s3_bucket
A
A
random_pet aws_dynamodb_table
A A
A A
aws_iam_policy aws_iam_user
Provider Resource Resource
Type
Provider
Resource
I I P I P A D
Multiple Choice Quiz