A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developer.hashicorp.com/terraform/tutorials/configuration-language/expressions below:

Create dynamic expressions | Terraform

The Terraform configuration language supports complex expressions to allow you to compute or generate values for your infrastructure configuration. Expressions can be simple string or integer values, or more complex values to make your configuration more dynamic.

In this tutorial, you will use expressions to configure and deploy EC2 instances and a load balancer. You will use conditionals to determine whether to provision multiple instances for high-availability and the splat expression to return multiple private IPs in your network.

You can complete this tutorial using the same workflow with either Terraform Community Edition or HCP Terraform. HCP Terraform is a platform that you can use to manage and execute your Terraform projects. It includes features like remote state and execution, structured plan output, workspace resource summaries, and more.

Select the HCP Terraform tab to complete this tutorial using HCP Terraform.

Clone the Learn Terraform Expressions repository, which contains configuration for AWS network components, an EC2 instance, and load balancer. You will modify the configuration of these resources using Terraform expressions.

$ git clone https://github.com/hashicorp-education/learn-terraform-expressions

Navigate to the repository in your terminal.

$ cd learn-terraform-expressions

Conditional expressions select a value based on whether the expression evaluates to true or false.

In this configuration, you will use the locals block to create a resource name based on a conditional value and capture that name in a map of resource tags.

Open your main.tf file and paste in the following code snippet.

main.tf

resource "random_id" "id" {
  byte_length = 8
}

locals {
  name  = (var.name != "" ? var.name : random_id.id.hex)
  owner = var.team
  common_tags = {
    Owner = local.owner
    Name  = local.name
  }
}

The syntax of a conditional expression first defines the condition, then the outcomes for true and false evaluations. In this example, if var.name is not empty (!= ""), local.name is set to the var.name value; otherwise, the name is the random_id.

Condition ? true value : false value If the name variable is NOT empty then Assign the var.name value to the local value else Assign random_id.id.hex value to the local value

Next, update the network resources of your configuration and add the local.common_tags expression to your tags attribute.

Note

Use local values with caution. While reusing a local value simplifies your configuration, it can add complexity to your resource lifecycle.

main.tf

resource "aws_vpc" "my_vpc" {
  cidr_block           = var.cidr_vpc
  enable_dns_support   = true
  enable_dns_hostnames = true
  tags                 = local.common_tags
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.my_vpc.id
  tags   = local.common_tags
}

resource "aws_subnet" "subnet_public" {
  vpc_id     = aws_vpc.my_vpc.id
  cidr_block = var.cidr_subnet
  tags       = local.common_tags
}

resource "aws_route_table" "rtb_public" {
  vpc_id = aws_vpc.my_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }
  tags = local.common_tags
}

Update your ELB resource with the tags.

main.tf

## ...
resource "aws_elb" "learn" {
## ...
  instances                   = aws_instance.ubuntu.id
  idle_timeout                = 400
  connection_draining         = true
  connection_draining_timeout = 400
  tags                        = local.common_tags
}

Finally, update your aws_instance resource.

main.tf

resource "aws_instance" "ubuntu" {
  availability_zone = "us-east-1a"
  ami                         = data.aws_ami.ubuntu.id
  instance_type               = "t2.micro"
  associate_public_ip_address = true
  subnet_id                   = aws_subnet.subnet_public.id
  tags                        = local.common_tags
}

Save your changes.

Create a new file called outputs.tf and add the values for your instance tags.

outputs.tf

output "tags" {
  description = "Instance tags"
  value       = aws_instance.ubuntu.tags
}

Initialize this configuration.

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Reusing previous version of hashicorp/random from the dependency lock file
- Installing hashicorp/aws v4.6.0...
- Installed hashicorp/aws v4.6.0 (signed by HashiCorp)
- Installing hashicorp/random v3.1.2...
- Installed hashicorp/random v3.1.2 (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 Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Open your terraform.tf file and uncomment the cloud block. Replace the organization name with your own HCP Terraform organization.

terraform.tf

terraform {
  cloud {
    organization = "organization-name"
    workspaces {
      name = "learn-terraform-expressions"
    }
  }
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.4.0"
    }
  }
  required_version = ">= 1.1"
}

Initialize your configuration. Terraform will automatically create the learn-terraform-expressions workspace in your HCP Terraform organization.

$ terraform init
Initializing HCP Terraform...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Installing hashicorp/aws v4.4.0...
- Installed hashicorp/aws v4.4.0 (signed by HashiCorp)
HCP Terraform has been successfully initialized!
You may now begin working with HCP Terraform. Try running "terraform plan" to
see any changes that are required for your infrastructure.
If you ever set or change modules or Terraform Settings, run "terraform init"
again to reinitialize your working directory.

Run terraform apply. Respond yes to the prompt to confirm the operation.

$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create

Terraform will perform the following actions:
##...
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
##...
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.

Outputs:

tags = tomap({
  "Name" = "terraform"
  "Owner" = "hashicorp"
})

Tip

This tutorial shows the output for Terraform commands run with the Terraform CLI. If you are following the HCP Terraform workflow, the output may differ slightly but the results will be the same.

If you use HCP Terraform to provision your resources, your workspace now displays the list of all of the resources it manages.

The Terraform outputs contain the formatted resource tags.

Open variables.tf and add a new boolean variable for high availability.

variables.tf

variable "high_availability" {
  type        = bool
  description = "If this is a multiple instance deployment, choose `true` to deploy 3 instances"
  default     = true
}

Save this file.

Next, open main.tf and update the aws_instance resource to use the new high_availability variable.

First, update the count parameter with a conditional expression based on the value of var.high_availability. Then update the associate_public_ip_address parameter so that only the first instance is assigned a public IP address. Finally, merge the tags for the new instances.

main.tf

resource "aws_instance" "ubuntu" {
  count                       = (var.high_availability == true ? 3 : 1)
  ami                         = data.aws_ami.ubuntu.id
  instance_type               = "t2.micro"
  associate_public_ip_address = (count.index == 0 ? true : false)
  subnet_id                   = aws_subnet.subnet_public.id
  tags                        = merge(local.common_tags)
}
Condition ? true value : false value If var.high_availability is set to true then Create three aws_instance resources else Create one aws_instance resource If count.index is 0 then Assign public IP else Do not assign public IP

Save your changes.

The aws_instance resource could now have a count value of 3. To return the private IP addresses of all of the instances, you will use a splat * expression to create an output value.

The splat expression captures all objects in a list that share an attribute. The special * symbol iterates over all of the elements of a given list and returns information based on the shared attribute you define.

Without the splat expression, Terraform would not be able to output the entire array of your instances and would only return the first item in the array.

Create a splat expression

Edit the outputs.tf file to add the new private_addresses output. This output will return the private DNS of all instances created by the aws_instance.ubuntu resource.

outputs.tf

output "private_addresses" {
  description = "Private DNS for AWS instances"
  value       = aws_instance.ubuntu[*].private_dns
}

This expression mirrors capturing a specific element in an array. If you only wanted to return the third instance IP in the array of instances, you could do that by replacing the * with 2.

The current tags output will error because there are multiple instances.

Replace the tags output block with the following first_tags output, which will return the first instance's tags.

outputs.tf

output "first_tags" {
  description = "Instance tags for first instance"
  value       = aws_instance.ubuntu[0].tags
}

Open main.tf to add the new instances to the ELB configuration.

main.tf

resource "aws_elb" "learn" {
##...
  instances                   = aws_instance.ubuntu[*].id
  idle_timeout                = 400
  connection_draining         = true
  connection_draining_timeout = 400
  tags                        = local.common_tags
}

Save your changes.

Apply your changes

Run terraform apply to provision the new instances and update your load balancer configuration. Respond yes to the prompt to confirm the operation.

$ terraform apply
random_id.id: Refreshing state... [id=NfgSYKxrorA]
aws_vpc.my_vpc: Refreshing state... [id=vpc-06e45b1a591e2b96f]
aws_internet_gateway.igw: Refreshing state... [id=igw-05972512ea18f8eb0]
aws_subnet.subnet_public: Refreshing state... [id=subnet-0f0710e956d144ac3]
aws_route_table.rtb_public: Refreshing state... [id=rtb-002b2df72a5eee2ba]
aws_instance.ubuntu[0]: Refreshing state... [id=i-08ff118d23a9cddc4]
aws_route_table_association.rta_subnet_public: Refreshing state... [id=rtbassoc-0d692f2cd308ef864]
aws_elb.learn: Refreshing state... [id=Learn-ELB]

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create
  ~ update in-place

Terraform will perform the following actions:
##...
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
##...

Apply complete! Resources: 2 added, 1 changed, 0 destroyed.

Outputs:

first_tags = tomap({
  "Name" = "terraform"
  "Owner" = "hashicorp"
})
private_addresses = [
  "ip-172-16-10-133.us-east-2.compute.internal",
  "ip-172-16-10-244.us-east-2.compute.internal",
  "ip-172-16-10-63.us-east-2.compute.internal",
]

Terraform's output now contains the entire array of private addresses for all three EC2 instances.

After verifying that the resources were deployed successfully, run terraform destroy to destroy them. Respond yes to the confirmation prompt to confirm the action.

$ terraform destroy
random_id.id: Refreshing state... [id=NfgSYKxrorA]
aws_vpc.my_vpc: Refreshing state... [id=vpc-06e45b1a591e2b96f]
aws_internet_gateway.igw: Refreshing state... [id=igw-05972512ea18f8eb0]
aws_subnet.subnet_public: Refreshing state... [id=subnet-0f0710e956d144ac3]
aws_route_table.rtb_public: Refreshing state... [id=rtb-002b2df72a5eee2ba]
aws_instance.ubuntu[0]: Refreshing state... [id=i-08ff118d23a9cddc4]
aws_instance.ubuntu[1]: Refreshing state... [id=i-0f4ef22bcf35a2632]
aws_instance.ubuntu[2]: Refreshing state... [id=i-0566759e2fd7116d7]
aws_route_table_association.rta_subnet_public: Refreshing state... [id=rtbassoc-0d692f2cd308ef864]
aws_elb.learn: Refreshing state... [id=Learn-ELB]

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  - destroy

Terraform will perform the following actions:
##...
Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes
##...
Destroy complete! Resources: 10 destroyed.

If you used HCP Terraform for this tutorial, after destroying your resources, delete the learn-terraform-expressions workspace from your HCP Terraform organization.

To learn more about how to create more complex, dynamic configuration, review the following resources:


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4