Search code examples
terraformenvironment-variablesterraform-provider-aws

Access Process-Specific Terraform TF_VAR value


I am attempting to grab a value within a Terraform/Python null_resource and make it available to other Terraform processes like so:

print_env.py

import os

# Create TF_VAR key value
param_tfvar = "TF_VAR_helloworld"

# Publish value through TF_VAR value
os.environ[param_tfvar] = "Hey Bob!"

print(param_tfvar, os.getenv(param_tfvar))

The Terraform *.tf files look like this:

variables.tf

variable "helloworld" {
    description = "Display greeting"
    type        = string
    default     = ""
}

main.tf

resource "null_resource" "helloworld" {
    provisioner "local-exec" {
      command = <<EOC
        python3 print_env.py
      EOC
    }
}

resource "null_resource" "echo_helloworld" {
    provisioner "local-exec" {
      command = "echo ${var.helloworld}"
    }
    depends_on = [
      null_resource.helloworld
    ]
}

My issue is that the echo command does not display Hey Bob! but just a blank (the default value of helloworld defined in the variables.tf file.

I was looking at: https://www.terraform.io/language/values/variables#environment-variables on how to craft this solution.

Am I running into some type of scoping issue where the TF_VAR value published in the null_resource.helloworld block is not visible to the null_resource.echo_helloworld block?


Solution

  • Environment variables should be exported in the shell before you invoke terraform. Setting those at run-time like you are doing is not going to work.

    Here's how I would solve your problem:

    main.tf:

    data "external" "get_greeting" {
      program = ["python3", "get_env.py", var.greeting]
    }
    
    variable "greeting" {
      description = "Display greeting"
      type = string
      default = "" 
    }
    
    output "show_greeting" {
      value = data.external.get_greeting.result.greeting
    }
    

    get_env.py:

    import json
    import sys
    
    if len(sys.argv) > 1:
        greeting = f"Hello {sys.argv[1]}"
    else:
        greeting = "Hello"
    
    tf_dict = ({"greeting": greeting})
    
    print(json.dumps(tf_dict))
    

    And this is what you would see if you invoked it with no variable override:

    $ terraform apply
    outputs:
    
    show_greeting = "Hello"
    

    and with override:

    $ terraform apply -var greeting="world"
    
    outputs:
    
    show_greeting = "Hello world"