How to reference input variables from template stanza

Hi, I like to use an input variable of map type in the template stanza to transform it into a configuration file. How can I reference that variable from consul-template to iterate over the map content?

I tried the following:

variable "my_props" {
  type = map(string)
  default = { bla = "blu" }
}

...

template {
  destination = "local/application.properties"
  data = <<EOD
{{ range $key, $value := $var.my_props }}
{{ .key }} = {{ .value }}
{{end}}
EOD
 }

This results in an error as ‘var’ is not defined. Also tried slight other variation to reference the input variable, but without success. Is this possible at all or are there other ways t achieve the desired config file?

Thanks in advance.

Hi @MatthiasZerau :wave:

Unfortunately this won’t work like this because its mixing two mechanisms (job file in HCL2 and Consul template) that are not really compatible.

HCL2 is the configuration language used by Nomad to declare job files, and it’s evaluated at the time and environment the job is submitted (for example, when you run nomad job run in your computer). Once it’s registered in the cluster, it won’t update.

It’s not really a templating language, so it’s not ideal in this situation, but it can be done like so:

variable "my_props" {
  type    = map(string)
  default = { bla = "blu" }
}

job "example" {
  # ...
  group "cache" {
    # ...
    task "redis" {
      # ...
      template {
        data        = join("\n", formatlist("%s = %s", keys(var.my_props), values(var.my_props)))
        destination = "local/test.kv"
      }
      # ...
    }
  }
}

Consul template uses the Go template package to render files from dynamic sources (like Consul KV storage paths, or services, or Vault entries etc.) It’s evaluated in the Nomad client right before the task starts, and it will be updated whenever the remote values it depends on changes.

You can accomplish what you are looking for by storing your my_props in Consul and reading it using the key function.

But it may be unnecessary to store the value in Consul if you don’t expect it to change. So the best option here may be to use Levant which is a proper templating tool for Nomad.

For your example, you would need to save the variables declaration in a separate file:

# variables.tf
variable "my_prop" {
  type    = map(string)
  default = { bla = "blu" }
}

Then your job template would look something like this:

job "example" {
  # ...
  group "cache" {
    # ...
    task "redis" {
      # ...
      template {
        data        = <<EOT
[[ range $key, $value := .my_prop ]]
[[ $key ]] = [[ $value ]]
[[ end ]]
EOT
        destination = "local/test.kv"
      }
      # ...
    }
  }
}

You can then submit the job using Levant as well:

$ levant deploy -var-file=variables.tf example.nomad

For more details on these different methods, checkout our Learn guides.

@lgfa29 thanks for this thorough answer. levant looks promising and exactly what I was looking for. I’ll give it a try.

1 Like