When are variables defined in terraform? - terraform

Terraform newbie here. I've a module with variables.tf which creates a resource 'folder' in Google Cloud. The variables are defined as:
variable "folder_name" {
type = "string"
description = "Name of the folder"
}
The calling function of this module is main.tf.
module "folder" {
source = "../<path>/"
}
When I run 'terraform init', it throws the following error-
$ terraform init
Initializing modules...
- module.folder
- module.project
Error: module "folder": missing required argument "folder_name"
I thought variables can be predetermined in a file or included in the command line options while running 'terraform apply'. I'd prefer CLI options, but then why am I seeing an argument error at the 'init' stage?

You provide the value of each module variable when calling the module itself:
module "folder" {
source = "../<path>/"
folder_name = "xyz" # add this line to define the folder_name variable
}
If you'd like to specify folder_name on the command line instead, you can create a variable in your main.tf file and provide that via command line instead:
variable "module_folder_name" {
default = "xyz"
}
module "folder" {
source = "../<path>/"
folder_name = "${var.module_folder_name}"
}
And then provide this variable's value via the command line:
terraform apply -var="module_folder_name=abc"

Related

Terraform interactive input doesn't work with the root module

Terraform Version
Terraform v1.1.2
on windows_amd64
Terraform Configuration Files
child_module1.tf(C1):
# Create Resource Group
resource "aws_resourcegroups_group" "resourcegroups_group" {
name = "test"
resource_query {
query = <<JSON
{
"ResourceTypeFilters": [
"AWS::EC2::Instance"
],
"TagFilters": [
{
"Key": "project",
"Values": ["${var.ProjectName}"]
}
]
}
JSON
}
}
child_module1_variables.tf:
########
variable "ProjectName" {
type = string
description = "This name would be prefixed with the cluster names."
}
Now call this child module in another child module**(C2)**:
child_module2.tf:
module "prepare_aws_cloud" {
source = "./modules/aws/prepare_cloud_copy"
ProjectName = "${var.test.ProjectName}"
}
child_module2_variables.tf:
variable "test" {
type = object({
ProjectName = string
})
}
Now I create a root module(R1)** which calls the child_module2.tf:**
terraform {
backend "local" {
}
}
module "test_deploy" {
source = "D:\\REPO\\installer_v2.2.22.1\\installer\\aws"
test = {
#ProjectName = ""
}
}
So the dependency is as follows:
R1 calls >> C2 calls >> C1
ERROR
PS D:\tkgTest> terraform apply -input=true
╷
│ Error: Invalid value for module argument
│
│ on testing.tf line 21, in module "test_deploy":
│ 21: test= {
│ 22: #ProjectName = ""
│ 23: }
│
│ The given value is not suitable for child module variable "test" defined at .terraform\modules\test_deploy\variables.tf:108,1-15: attribute "ProjectName" is required.
Expected Behavior
I would have expected that the user input would be taken interactively by the console as I am passing the -input=true flag but it doesn't seem to work.
The interactive prompts for input variables are intended only to help with getting started with Terraform (e.g. following a simple tutorial) and so they are limited in the scope of what they support. The typical way to set root module input variables for routine use is to either create a .tfvars file and pass it to Terraform with -var-file or to set a variable directly using -var.
Note also that only root module input variables can be set directly as part of the planning options. Any child module variables are defined exclusively by the expressions written in the module block, and so if you want to be able to set a child module's input variable on a per-run basis you'll need to also declare it as a root module variable and then pass it through to the child module.
For example, in the root module:
variable "test" {
type = object({
ProjectName = string
})
}
module "test_deploy" {
source = "./installer/aws"
test = var.test
}
You can then create an example.tfvars file with the following to set a value for the variable:
test = {
ProjectName = "example"
}
Specify that file when you run Terraform:
terraform apply -var-file=example.tfvars
If you will always set the same values then you can avoid the need for the extra option by naming your file example.auto.tfvars and placing it in the same directory where you will run Terraform. Terraform will load .auto.tfvars files automatically without any explicit -var-file option.

How can I pass the tfvars from another module?

So here's my setup:
main.tf:
module "foo" {
source = "../../../foo-module"
name = "bar"
foo_nets = "${var.foo_nets}"
}
foo-module/terraform.tfvars:
foo_nets = ["1", "2", "3"]
➜ terraform plan -var-file=../../foo-module/terraform.tfvars -target=module.foo
Error: module 'foo': unknown variable referenced: 'foo_nets'; define it with a 'variable' block
Your foo-module/terraform.tfvars doesn't define a variable named foo_nets, it only defines a default value for a variable named foo_nets if that variable happens to exist. You still have to define the variable somewhere in the terraform files in the foo-module folder like this:
variable "foo_nets" {
}

How to access terragrunt variables in terraform code

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.

Import variables from module terraform

please help to understand how I can import variables files from a different location?
I have tried to do this from the module system, but it's not working for me.
My structure :
/
/variables.tf
/my_ec2/main.tf
/my_ec2/variables.tf
How I can import variables from root folder? Need to specify it somehow on main.tf
My /my_ec2/main.tf
module "global_vars" {
source = "../../../"
}
provider "aws" {
region = "module.global_vars.region_aws"
}
my /variables.tf
variable "region_aws" {
default = "eu-central-1"
}
How can I do this?
P.S. Did the same with "${var.region_aws}", but same result
Error: Reference to undeclared input variable
on ../my_ec2/main.tf line 10, in resource "aws_instance" "server":
10: region = "${var.region_aws}"
An input variable with the name "aws_instance" has not been declared. This
variable can be declared with a variable "environment" {} block.
Maybe use :
"${module.global_vars.region_aws}"
Instead of
"module.global_vars.region_aws"

Terraform common variable usage in modules

I am writing terraform script to create ASG on AWS. I tried to create it with terraform module to have a more reusable code. The problem is when I want to use variable from common-variable.tfvars on the module tf files, it keeps saying it is undefined and need to be declared. This way, the module will be less reuseable .
Here is an example
root
|
|___project 1
| |_____ main.tf
| |_____ common-variable.tfvars
|
|___ modules
|
|_____ a-module
|______ main.tf
So inside project 1 common-variable.tfvars, basically it looks like this
variable "a" {
description = "a variable"
default = "a"
}
variable "b" {
description = "a variable"
default = "b"
}
Inside a-module / main.tf looks like this
variable "name" {}
resource "aws_autoscaling_group" "asg-1" {
name = "${var.a}"
...
}
When I do terraform init, it says
resource 'aws_autoscaling_group.asg-1' config: unknown variable
referenced: 'a'. define it with 'variable' blocks
Any idea how i can use this common variable from within the module main .tf?
Update
I managed to pass terraform init by redeclaring the variable in each module. However, when i run terraform plan, this kind of error appears invalid value "common-variable.tfvars" for flag -var-file: multiple map declarations not supported for variables
Wrong tfvars format, should be key / value only, such as:
a = "a"
b = "b"
Second, check how do you refer the module, should be something like this:
source = "../modules/a-module"
You need to declare the variables required by the module within the module, and then pass them in when instantiating the module from your project.
Example stolen from hashicorp documentation
In your project:
module "assets_bucket" {
source = "./publish_bucket"
name = "assets"
}
module "media_bucket" {
source = "./publish_bucket"
name = "media"
}
In your module:
# publish_bucket/bucket-and-cloudfront.tf
variable "name" {} # this is the input parameter of the module
resource "aws_s3_bucket" "the_bucket" {
# ...
}
resource "aws_iam_user" "deploy_user" {
# ...
}

Resources