I have created the following terraform.tfvars file:
ec2_image = "ami-00035f41c82244dab"
ec2_instance_type = "t2.micro"
And use it as follows in a main.tf file:
resource "aws_instance" "OneServer" {
ami = "${var.ec2_image}"
instance_type = "${var.ec2_instance_type}"
}
Then I execute the 'terraform plan' command and it complains with:
Error: resource 'aws_instance.OneServer' config: unknown variable
referenced: 'ec2_image'; define it with a 'variable' block
So I changed the main.tf file as follows:
variable "ec2_image" {}
variable "ec2_instance_type" {}
resource "aws_instance" "OneServer" {
ami = "${var.ec2_image}"
instance_type = "${var.ec2_instance_type}"
}
Then the command 'terraform plan' works OK.
I don't understand why these variable blocks are required. What's the point for it?
Are you actually using the -var-file command-line switch?
For example, I don't use that switch - I just define my overridable variables in a random tf file (named in my case variable.tf). If the -var-file switch is not used, that means the variable block is required to tell Terraform when a variable is being defined.
Related
I'm following a terraform tutorial on using variables in AWS.
It defines AMI variables like:
variable "amis" {
type = "map"
default = {
"us-east-1" = "ami-b374d5a5"
"us-west-2" = "ami-fc0b939c"
}
}
And then assigns the AMI variable like this:
resource "aws_instance" "example" {
ami = var.amis[var.region]
instance_type = "t2.micro"
}
If I try the example that way I get an error:
Error: Invalid index
on main.tf line 17, in resource "aws_instance" "example":
17: ami = var.amis[var.region]
The given key does not identify an element in this collection value: string
required.
However I can set the variable by hard coding it:
var.amis["us-west-2"] # <-- this works
What can I do to set the variable correctly with ami = var.amis[var.region] ?
you need to define variable var.region or you can pass the value to variable during plan / apply as terraform plan -var 'region=us-west-2' and terraform apply -var 'region=us-west-2'
The terraform code of file - "myec2.tf"
provider "aws" {
region = "eu-west-1"
access_key = "<<access key id>>"
secret_key = "<<secret key id>>"
}
# chosen from the RESOURCE section in Terraform 'Provider' section
resource "aws_instance" "terra_ec2" {
ami = "ami-07d9160fa81ccffb5"
instance_type = "t2.micro"
provider = "https://registry.terraform.io/hashicorp/aws"
}
The ERROR MESSAGES obtained after issuing the "terraform init" command
There are some problems with the configuration, described below.
The Terraform configuration must be valid before initialization so that
Terraform can determine which modules and providers need to be installed.
Warning: Quoted references are deprecated
on first_ec2.tf line 11, in resource "aws_instance" "terra_ec2":
11: provider = "https://registry.terraform.io/hashicorp/aws"
In this context, references are expected literally rather than in quotes.
Terraform 0.11 and earlier required quotes, but quoted references are now
deprecated and will be removed in a future version of Terraform. Remove the
quotes surrounding this reference to silence this warning.
Error: Invalid character
on first_ec2.tf line 11, in resource "aws_instance" "terra_ec2":
11: provider = "https://registry.terraform.io/hashicorp/aws"
Expected an attribute access or an index operator.
You already set the provider in your terraform code.
You do not need the provider key in your resource.
Remove the provider:
resource "aws_instance" "terra_ec2" {
ami = "ami-07d9160fa81ccffb5"
instance_type = "t2.micro"
}
I have terragrunt config where have declared the variables using locals as below at root level. In the child module , have declared the child terragrunt config file called (terragrunt.hcl).
parent terragrunt file has following code :
locals {
location = "East US"
}
child module terragrunt file has below code :
include {
path = find_in_parent_folders()
}
locals {
myvars = read_terragrunt_config(find_in_parent_folders("terragrunt.hcl"))
location = local.myvars.locals.location
}
now, trying to access location variable in the terraform code (main.tf) using following code :
location = "${var.location}"
but it throws error:
Error: Reference to undeclared input variable
on main.tf line 13, in resource "azurerm_resource_group" "example":
13: location = "${var.location}"
Not getting how i can access variables defined in the terragrunt file in the terraform code . please suggest
This error message means that your root module doesn't declare that it is expecting to be given a location value, and so you can't refer to it.
In your root Terraform module you can declare that you are expecting this variable by declaring it with a variable block, as the error message hints:
variable "location" {
type = string
}
This declaration will then make it valid to refer to var.location elsewhere in the root module, and it will also cause Terraform to produce an error if you accidentally run it without providing a value for this location variable.
Here is my setup,
Terraform version - Terraform v0.12.17
OS - OSX 10.15.1
Use Case - define a provider file and access the variables defined in the vars file
Files
main.tf - where the code is
provider "aws" {
}
variable "AWS_REGION" {
type = string
}
variable "AMIS" {
type = map(string)
default = {
us-west-1 = "my ami"
}
}
resource "aws_instance" "awsInstall" {
ami = var.AMIS[var.AWS_REGION]
instance_type = "t2.micro"
}
awsVars.tfvars - where the region is defined
AWS_REGION="eu-region-1"
Execution
$ terraform console
var.AWS_REGION
Error: Result depends on values that cannot be determined until after "terraform apply".
What mistake I have done, I don't see any syntax but have issues in accessing the variables, any pointers would be helpful
Thanks
Terraform does not automatically read a .tfvars file unless its filename ends with .auto.tfvars. Because of that, when you ran terraform console with no arguments Terraform did not know a value for variable AWS_REGION.
To keep your existing filename, you can pass this variables file explicitly on the command line like this:
terraform console -var-file="awsVars.tfvars"
Alternatively, you could rename the file to awsVars.auto.tfvars and then Terraform will read it by default as long as it's in the current working directory when you run Terraform.
There's more information on how you can set values for root module input variables in the Terraform documentation section Assigning Values to Root Module Variables.
Note also that the usual naming convention for input variables and other Terraform-specific objects is to keep the names in lowercase and separate words with underscores. For example, it would be more conventional to name your variables aws_region and amis.
Furthermore, if your goal is to find an AMI for the current region (the one chosen by the AWS_DEFAULT_REGION environment variable, or in the provider configuration), you could use the aws_region data source to allow Terraform to determine that automatically, so you don't have to set it as a variable at all:
variable "amis" {
type = map(string)
default = {
us-west-1 = "my ami"
}
}
data "aws_region" "current" {}
resource "aws_instance" "awsInstall" {
ami = var.amis[data.aws_region.current.name]
instance_type = "t2.micro"
}
I am trying to run a Terraform deployment via a Shell script where within the Shell script I first dynamically collect the access key for my Azure storage account and assign it to a variable. I then want to use the variable in a -var assignment on the terraform command line. This method works great when configuring the backend for remote state but it is not working for doing a deployment. The other variables used in the template are being pulled from a terraform.tfvars file. Below is my Shell script and Terraform template:
Shell script:
#!/bin/bash
set -eo pipefail
subscription_name="Visual Studio Enterprise with MSDN"
tfstate_storage_resource_group="terraform-state-rg"
tfstate_storage_account="terraformtfstatesa"
az account set --subscription "$subscription_name"
tfstate_storage_access_key=$(
az storage account keys list \
--resource-group "$tfstate_storage_resource_group" \
--account-name "$tfstate_storage_account" \
--query '[0].value' -o tsv
)
echo $tfstate_storage_access_key
terraform apply \
-var "access_key=$tfstate_storage_access_key"
Deployment template:
provider "azurerm" {
subscription_id = "${var.sub_id}"
}
data "terraform_remote_state" "rg" {
backend = "azurerm"
config {
storage_account_name = "terraformtfstatesa"
container_name = "terraform-state"
key = "rg.stage.project.terraform.tfstate"
access_key = "${var.access_key}"
}
}
resource "azurerm_storage_account" "my_table" {
name = "${var.storage_account}"
resource_group_name = "${data.terraform_remote_state.rg.rgname}"
location = "${var.region}"
account_tier = "Standard"
account_replication_type = "LRS"
}
I have tried defining the variable in my terraform.tfvars file:
storage_account = "appastagesa"
les_table_name = "appatable
region = "eastus"
sub_id = "abc12345-099c-1234-1234-998899889988"
access_key = ""
The access_key definition appears to get ignored.
I then tried not using a terraform.tfvars file, and created the variables.tf file below:
variable storage_account {
description = "Name of the storage account to create"
default = "appastagesa"
}
variable les_table_name {
description = "Name of the App table to create"
default = "appatable"
}
variable region {
description = "The region where resources will be deployed (ex. eastus, eastus2, etc.)"
default = "eastus"
}
variable sub_id {
description = "The ID of the subscription to deploy into"
default = "abc12345-099c-1234-1234-998899889988"
}
variable access_key {}
I then modified my deploy.sh script to use the line below to run my terraform deployment:
terraform apply \
-var "access_key=$tfstate_storage_access_key" \
-var-file="variables.tf"
This results in the error invalid value "variables.tf" for flag -var-file: multiple map declarations not supported for variables Usage: terraform apply [options] [DIR-OR-PLAN] being thrown.
After playing with this for hours...I am almost embarrassed as to what the problem was but I am also frustrated with Terraform because of the time I wasted on this issue.
I had all of my variables defined in my variables.tf file with all but one having default values. For the one without a default value, I was passing it in as part of the command line. My command line was where the problem was. Because of all of the documentation I read, I thought I had to tell terraform what my variables file was by using the -var-file option. Turns out you don't and when I did it threw the error. Turns out all I had to do was use the -var option for the variable that had no defined default and terraform just automagically saw the variables.tf file. Frustrating. I am in love with Terraform but the one negative I would give it is that the documentation is lacking.