While experimenting on managing Terraform Cloud using tfe_*
providers, I’m having an idea to manage Terraform Cloud workspace variable using terraform
, and keep a “meta” workspace to manually add or remove variables. I’m having a difficulty with reusing terraform.tfvars
since you can’t access var
like:
variable "shared_vars" {
default = ["aws_access_key", "aws_secret_key"]
}
resource "tfe_variable" "shared" {
count = "${length(var.shared_vars)}"
workspace_id = tfe_workspace.shared.id
category = "terraform"
key = var.shared_vars[count.index]
# this got error "var object cannot be accessed directly"
#value = "${lookup(var, var.shared_vars[count.index])}"
# this, too, got error "var object cannot be accessed directly"
#value = var[var.shared_vars[count.index]]
# this evaluate as plain "var.variablename"
#value = "${format("var.%s", var.shared_vars[count.index])}"
}
I’ve also tried with defining variables as maps, and using var.map
as opposed to var
:
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "map"
default = {
# this got error "variables not allowed"
aws_access_key = var.aws_access_key
aws_secret_key = var.aws_secret_key
}
}
# later on tfe_variables
value = "${lookup(var.map, var.shared_vars[count.index])}"
A workaround is to just define the map
variable using terraform.tfvars.json
. But this feels ugly and weird to me. I know this is backwards way of thinking, but I’d like to know what can I do with terraform
and Terraform Cloud. I feel like, tfe_workspace
should just accept variables
arguments, instead of making each one it’s own resource.
Any thoughts on this?
Hi @bentinata,
variable
blocks are for declaring data to be passed in from outside of the module, so the default value of a variable must be a constant.
However, you can use Local Values to create re-usable values within a module, in which case you can use references in their expressions like this:
variable "aws_access_key" {}
variable "aws_secret_key" {}
locals {
common_variables = {
aws_access_key = var.aws_access_key
aws_secret_key = var.aws_secret_key
}
}
resource "tfe_variable" "shared" {
for_each = local.common_variables
workspace_id = tfe_workspace.shared.id
category = "terraform"
key = each.key
value = each.value
sensitive = true
}
Please note that we generally recommend representing information about “who” is running Terraform (credentials and other auth-related settings) as environment variables rather than as Terraform variables, because that then keeps them “out of band” of the Terraform configuration and reduces the risk that someone will inadvertently interpolate them into a place that could expose them. So I might suggest the following modification, for that reason:
variable "aws_access_key" {}
variable "aws_secret_key" {}
locals {
environment_variables = {
AWS_ACCESS_KEY_ID = var.aws_access_key
AWS_SECRET_ACCESS_KEY = var.aws_secret_key
}
}
resource "tfe_variable" "shared" {
for_each = local.common_variables
workspace_id = tfe_workspace.shared.id
category = "env"
key = each.key
value = each.value
sensitive = true
}
Although in this case your AWS credential values will be specified as variables on the “meta” workspace (expected, because for that one you want to use them as data in the configuration), all of the other workspaces will see them as environment variables and thus they will be automatically available without the need to explicitly declare variable "aws_access_key"
, pass that into the provider configuration, etc.
1 Like