How to reference block from locals in task specification?

I would want to share mounts between multiple groups:

locals {
   mount_dir = {
        type = "bind"
        destination = "/some/dir"
        target = "/some/dir"
   }
}
job "test" {
   group "test" {
      task "test" {
         config {
            mount = mount_dir
            mount = mount_else
        }
     } 
  }
}

The code fails nomad run with:

Error getting job struct: Error parsing job file from airflow-dev.nomad.hcl:
test.nomad.hcl:252,9-14: Attribute redefined; The argument "mount" was already set at test.nomad.hcl:251,9-14. Each argument may be set only once., and 1 other diagnostic(s)

How do I fix it?

Hi @Kamilcuk :wave:

You need to use the local scope to reference local values, so it would be something like local.mount_dir in your example.

But there’s another problem in your jobspec, which is that you’re defining two attributes called mount instead of two blocks. This is evidenced by the = (I know, it’s quite confusing :sweat_smile:)

For your example to work you would need to use a dynamic block.

locals {
  mount_dir = [
    {
      type = "bind"
      destination = "/some/dir"
      target = "/some/dir"
     },
  ]
}

job "test" {
  group "test" {
    task "test" {
      config {
        dynamic "mount" {
          for_each = local.mounts
                                      
            content {
              type        = mount.type
              destination = mount.destination
              target      = mount.target
            }
          }
        }
      }
    }
  }
}

But, unfortunately, I found out that this doesn’t work :cry:

One alternative could be to use a tool like Nomad Pack to render the job.

1 Like

Hi, yes, dynamic does not work inside task config.

Yes, missing local. was a typo. The thing is, doing local { myenv = { dictionary = "value } } and task "test" { env = local.myenv works. You can even do env = merge(local.myenv, { additional = "field" }). But I do not know how to assign many same types.

It has always been confusing to me, why isn’t it mounts = [ { array }, { of }, { mounts } ] instead multiple blocks with the same name are concatenated.

The common alternative I use is a real preprocessor, like jinja2, php or m4 or cpp. Overall, for me, it looks simpler to use a common text preprocessor than hcl2.