Trouble passing variable in terraform apply - terraform

I am using Terraform Cloud for my Backend with version 1.1
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
cloud {
hostname = "app.terraform.io"
organization = "MyOrg"
workspaces {
name = "MyWorkspace"
}
}
}
I have a variable in my HCL
variable "app_version" {
description = "The application version to deploy"
type = string
}
I am attempting to set it when I call terraform apply like so:-
terraform apply -var="app_version=v0.0.1"
I get the following error though.
1 error occurred:
* Invalid HCL in variable "app_version": At 1:15: Unknown token: 1:15 IDENT v0.0.1
What does this mean?

I think the Terraform docs for command line variables do a poor job of explaining that, but you basically need to wrap the value in double quotes. As the value passed after = is interpreted as Terraform expression, not constant (which opens up for other possibilities).
So, try:
terraform apply -var 'app_version="v0.0.1"'
Also notice there should be no = after -var

Grzegorz was correct but if you are on a windows machine you will need to escape the double quotes but adding a \ before each double quote.

Related

Terraform: ignore changes to a certain environment variable

I have an AWS Lambda function I created using terraform. Code-changes are auto-deployed from our CI-server and the commit-sha is passed as an environment variable (GIT_COMMIT_HASH) - so this changes the Lambda function outside of the Terraform-scope (because people were asking...).
This works good so far. But now I wanted to update the function's node-version and terraform tries to reset the env var to the initial value of "unknown".
I tried to use the ignore_changes block but couldn't get terraform to ignore the changes made elsewhere ...
resource "aws_lambda_function" "test" {
filename = data.archive_file.helloworld.output_path
function_name = "TestName_${var.environment}"
role = aws_iam_role.test.arn
handler = "src/index.handler"
runtime = "nodejs14.x"
timeout = 1
memory_size = 128
environment {
variables = {
GIT_COMMIT_HASH = "unknown"
}
}
lifecycle {
ignore_changes = [
environment.0.variables["GIT_COMMIT_HASH"],
]
}
}
Is this possible? How do I have to reference the variable?
** edit **
Plan output looks like this:
# aws_lambda_function.test will be updated in-place
~ resource "aws_lambda_function" "test" {
# ... removed some lines
source_code_size = 48012865
tags = {}
timeout = 1
version = "12"
~ environment {
~ variables = {
~ "GIT_COMMIT_HASH" = "b7a77d0" -> "unknown"
}
}
tracing_config {
mode = "PassThrough"
}
}
I tried to replicate the issue and in my tests it works exactly as expected. I can only suspect that you are using an old version of TF, where this issue occurs. There has been numerous GitHub Issues reported regarding the limitations of ignore_changes. For example, here, here or here.
I performed tests using Terraform v0.15.3 with aws v3.31.0, and I can confirm that ignore_changes works as it should. Since this is a TF internal problem, the only way to rectify the problem, to the best of my knowledge, would be to upgrade your TF.

terraform variable default value interpolation from locals

I have a use case where I need two AWS providers for different resources. The default aws provider is configured in the main module which uses another module that defines the additional aws provider.
By default, I'd like both providers to use the same AWS credentials unless explicitly overridden.
I figured I could do something like this. In the main module:
locals {
foo_cloud_access_key = aws.access_key
foo_cloud_secret_key = aws.secret_key
}
variable "foo_cloud_access_key" {
type = string
default = local.foo_cloud_access_key
}
variable "foo_cloud_secret_key" {
type = string
default = local.foo_cloud_secret_key
}
where variables foo_cloud_secret_key and foo_cloud_access_key would then be passed down to the child module like this:
module foobar {
...
foobar_access_key = var.foo_cloud_access_key
foobar_secret_key = var.foo_cloud_secret_key
...
}
Where module foobar would then configure its additional was provide with these variables:
provider "aws" {
alias = "foobar_aws"
access_key = var.foobar_access_key
secret_key = var.foobar_secret_key
}
When I run the init terraform spits out this error (for both variables):
Error: Variables not allowed
on variables.tf line 66, in variable "foo_cloud_access_key":
66: default = local.foo_cloud_access_key
Variables may not be used here.
Is it possible to achieve something like this in terraform or is there any other way to go about this?
Having complex, computed default values of variables is possible, but only with a workaround:
define a dummy default value for the variable, e.g. null
define a local variable, its value is either the value of the variable or the actual default value
variable "something" {
default = null
}
locals {
some_computation = ... # based on whatever data you want
something = var.something == null ? local.some_computation : var.something
}
And then only only use local.something instead of var.something in the rest of the terraform files.

Jenkins Parameterised Job with Terraform map variable

I'm trying to feed user-defined parameters from Jenkins into a job which runs terraform. I have a set of simple key/value vars, which I'm passing into the Terraform like this:
sh "terraform plan -var 'var1=${params.Var1}' -var 'var2=${params.Var2}' ...."
However, I also have a map var:
tags = {
Cluster = "mycluster"
Environment = "myenv"
Owner = "owner"
Product = "myproduct"
}
and I would like to feed some String Parameters into this map var. It looks like I need to define a groovy map and then render the map as JSON, so that I can have e.g. terraform -var 'tags={"Cluster":"mycluster","Environment":"dev"...}
My job is currently of the form:
pipeline {
agent {
...
}
options {
...
}
environment {
...
}
stages {
stage('MyStage') {
steps {
script {
sh "terraform ..."
}
}
}
}
}
I'me very new to Jenkinsfiles, so where would I define a map, if that's what was needed..?
Your attempt in the question is close, but Maps in Groovy are constructed with [:]. Therefore, you can construct a Jenkins Pipeline Map type output in JSON to be passed to a Terraform Map type like the following:
terraform -var "tags=${JsonOutput.toJson(['Cluster':'mycluster', 'Environment':'dev'...])}"
Given your use of the sh step method above, you will also need to escape your quotes to properly cast your strings appropriately as well.

Adding a long content using End of text string(EOT) in terraform is throwing error

I want to add a content to the file using terraform using a local provider. Here is the example script which I am using
terraform {
required_version = "~>0.13"
required_providers {
local = "~>1.4"
}
}
resource "local_file" "literature" {
filename = "art_of_war.txt"
content = <<EOT
Hello
world
EOT
}
I am getting the following error Expected the start of an expression, but found an invalid expression token. .Can you please point what might be error.
It seems that in your example you were using tabs instead of spaces (or you have it configured in your editor). I recreated your example with using only spaces and it worked. Here's the code snippet that works:
resource "local_file" "literature" {
filename = "art_of_war.txt"
content = <<EOT
Hello
World
EOT
}
Note that EOT is left-aligned to the same level as resource.
EDIT: Actually, it seems there's a whitespace after the <<EOT, if you delete it it should work.

Getting Module Loading or Input variable error

I've configured the following variable in module/variables.tf
variable "instance_name" {
type = string
default = "instance-1"
description = "Name of the instance."
}
I refer to the variable in the same module module/main.tf as below
resource "google_compute_instance" "cloud_instance" {
name = var.instance_name
}
However, when I run terraform init, I get the following error-
Error: Error parsing /module/main.tf: At 15:12: Unknown token: 15:12 IDENT var.instance_name
Any idea why this is happening?
You need to refer variable as below to ensure expansion works correctly -
resource "google_compute_instance" "cloud_instance" {
name = "${var.instance_name}"
}
Using terraform 0.12.9 - I do not get this error on init or plan or validate, only on 0.12upgrade.
Also the documentation shows that if the variable is not in a string, it is possible to pass it without quotation marks and curly braces.
So which is correct?

Resources