# Terraform

This walkthrough shows you how to pass CloudTruth parameters as Environment Variables to Terraform.

You can also use CloudTruth to externally reference backend [tfstate output as an external parameter](https://docs.cloudtruth.com/parameters/parameter-management/external-values/terraform-state-files#remote-state-with-terraform).

## Prerequisites

* You know basic [Terraform](https://learn.hashicorp.com/terraform).
* You have created a [CloudTruth API Access token](https://docs.cloudtruth.com/org-management/access-control/access-tokens) and installed the [CLI](https://docs.cloudtruth.com/cli-and-api/cloudtruth-cli#installation).

## Terraform deploy with CloudTruth

For this example we will build on top of the [Terraform AWS tutorial](https://learn.hashicorp.com/tutorials/terraform/aws-variables?in=terraform/aws-get-started) to deploy an EC2 instance defining variables with CloudTruth parameters. You can use any target for your deploys.

### Set CloudTruth Terraform Variables

Create a CloudTruth Project called `Terraform`.

```
cloudtruth project set Terraform
```

Now you can create the CloudTruth parameters in the Terraform project that we will pass to Terraform as [environment input variables](https://www.terraform.io/docs/language/values/variables.html#environment-variables) with the `TF_VAR_` convention.

```
cloudtruth --project Terraform parameter set TF_VAR_ami -v ami-830c94e3 
cloudtruth --project Terraform parameter set TF_VAR_instance_type -v t2.micro
cloudtruth --project Terraform parameter set TF_VAR_availability_zone_names -v \[\"us-west-2a\",\ \"us-west-2b\"\]
cloudtruth --project Terraform parameter set TF_VAR_resource_tags -v \{\"Name\":\"Cloudtruth-Instance\",\"project\":\"CloudTruth\ Run\ Terraform\",\"environment\":\"default\"\}
```

### Create Terraform Configuration

From your [Terraform working directory](https://learn.hashicorp.com/tutorials/terraform/aws-build?in=terraform/aws-get-started) update your `main.tf` with the following configuration.

```
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }
}

provider "aws" {
  profile = "default"
  region  = "us-west-2"
}

resource "aws_instance" "cloudtruth" {
  ami           = var.ami
  instance_type = var.instance_type 
  availability_zone = var.availability_zone_names[0]

  tags = var.resource_tags
}

output "zone" {
  value = aws_instance.cloudtruth.availability_zone
}

output "AMI" {
  value = aws_instance.cloudtruth.ami
}

output "instance_type" {
  value = aws_instance.cloudtruth.instance_type
}

output "instance_name" {
  value = aws_instance.cloudtruth.tags.Name
}

#########################
####### VARIABLES #######
#########################

variable "ami" {   
  description = "Value of the Amazon Machine Image"
  type        = string
  }

variable "instance_type" {   
  description = "Value of the Instance Type"
  type        = string
  }
  
variable "availability_zone_names"{
  description = "List of available regions"
  type        = list(string)
 }  
 
variable "resource_tags" {
  description = "Tags to set for all resources"
  type        = map(string)
}
```

This main.tf will deploy an EC2 instance to us-west-2 and [defines four variables](https://learn.hashicorp.com/tutorials/terraform/aws-variables?in=terraform/aws-get-started) that are centrally managed by CloudTruth. It also shows you how to use various Terraform variable [types](https://www.terraform.io/docs/language/expressions/types.html#types) such as a [map](https://www.terraform.io/docs/language/expressions/types.html#map) and [list](https://www.terraform.io/docs/language/expressions/types.html#list).

| Variable                  | Type   | CloudTruth Value                                                                            |
| ------------------------- | ------ | ------------------------------------------------------------------------------------------- |
| ami                       | string | ami-830c94e3                                                                                |
| instance\_type            | string | t2.micro                                                                                    |
| availability\_zone\_names | list   | \["us-west-2a", "us-west-2b"]                                                               |
| resource\_tags            | map    | {"Name":"Cloudtruth-Instance","project":"CloudTruth Run Terraform","environment":"default"} |

### Build Terraform Infrastructure

From your Terraform working directory [initialize the infrastructure](https://learn.hashicorp.com/tutorials/terraform/aws-build?in=terraform/aws-get-started#initialize-the-directory).

```
terraform init
```

Now when executing a `terraform plan` you will notice that you are prompted to enter values for each variable defined.

```
terraform plan
var.ami
  Value of the Amazon Machine Image

  Enter a value: 
```

**CloudTruth Run**

You can manage your Terraform configuration centrally with CloudTruth and pass Terraform [environment input variables](https://www.terraform.io/docs/language/values/variables.html#environment-variables) with the cloudtruth run CLI command.

The following command will pass the variables from the `Terraform` project where we set our input variables directly into `terraform apply`.

```
cloudtruth --project Terraform run -- terraform apply
```

Terraform will show the outputs and deploy the instance with our CloudTruth values.

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

Outputs:

AMI = "ami-830c94e3"
instance_name = "Cloudtruth-Instance"
instance_type = "t2.micro"
zone = "us-west-2a"
```

Couple this method with CloudTruth Environments and you can manage and deploy different instance types with various configuration setting to your Prod, Dev and Staging with a single command.

**Terraform Input Variables**

CloudTruth run injects environment variables into your terraform commands. Terraform searches the environment for variables that contain [`TF_VAR_`](https://www.terraform.io/docs/language/values/variables.html#environment-variables) preceding the variable name defined in your configuration script. The variable is case sensitive so if it is lower case in `main.tf` the variables must have lower case key names in CloudTruth.

Environment input variables have a specific [order of precedence](https://www.terraform.io/docs/language/values/variables.html#variable-definition-precedence) and CloudTruth run can be used with any combination that Terraform allows. Values from CloudTruth run be overridden by a file if the same variable exists in a `terraform.tfvars` or any of the higher precedence methods of passing values.

{% hint style="info" %}
Terraform loads variables in the following order, with later sources taking precedence over earlier ones:

* Environment variables
* The `terraform.tfvars` file, if present.
* The `terraform.tfvars.json` file, if present.
* Any `*.auto.tfvars` or `*.auto.tfvars.json` files, processed in lexical order of their filenames.
* Any `-var` and `-var-file` options on the command line, in the order they are provided. (This includes variables set by a Terraform Cloud workspace.)
  {% endhint %}
