HeadinCloud
HeadinCloud

Reputation: 278

Templating in Terraform module - argument is not expected here

During the creation of the new TF module, I met the issue with templatefile functionality.

In the triggers.tf I declared the module with an argument which is templated config. The module ./modules/trigger is using provided argument (filename).

During the TF plan I'm receiving:

 Error: Unsupported argument
│
│   on triggers.tf line 43, in module "trigger":
│   43:   filename = templatefile("${path.module}/templates/trigger.yaml.tpl", {
│
│ An argument named "filename" is not expected here.

./modules/trigger/main.tf

resource "null_resource" "trigger" {

  filename = var.filename

  provisioner "local-exec" {
    command = <<EOT
      gcloud alpha ... --trigger_config ${self.filename}  \
EOT
  }
}

triggers.tf

locals {
  repos = yamldecode(file("${path.module}/repositories/repos.yaml"))
  repos = {
    for pair in setproduct([local.repos["project"]], local.repos["repos"]) : "${pair[0]}/${pair[1]}" => {
      project = pair[0]
      repo    = pair[1]
    }
  }
}

module "trigger" {
  source   = "./modules/trigger"
  for_each = local.repos

  filename = templatefile("${path.module}/templates/trigger.yaml.tpl", {
    trigger_event           = "push"
    bitbucket_project       = each.value["project"]
    bitbucket_repo          = each.value["repo"]
  })
}

/repositories/repos.yaml

project: test
repos:
  - cloud-test

/templates/trigger.yaml.tpl

name: "${trigger_event}"
project: "${bitbucket_project}"
repo: "${bitbucket_repo}"

Upvotes: 0

Views: 1352

Answers (1)

Marko E
Marko E

Reputation: 18138

Here are the changes that are required for this to work:

  1. Create a file using local_file resource
  2. Update the null_resource in the module to use only the variable and not the non-existent argument (i.e., filename)

Note that renaming local variables is not allowed, so having two repos definitions will cause errors. I suggest changing it to something like:

locals {
  repositories = yamldecode(file("${path.module}/repositories/repos.yaml"))
  repos = {
    for pair in setproduct([local.repositories["project"]], local.repositories["repos"]) : "${pair[0]}/${pair[1]}" => {
      project = pair[0]
      repo    = pair[1]
    }
  }
}

So in the root of the module, here is what part of code you need:

resource "local_file" "trigger_file" {
  for_each = local.repos
  content = templatefile("${path.module}/templates/trigger.yaml.tpl", {
    trigger_event     = "push"
    bitbucket_project = each.value["project"]
    bitbucket_repo    = each.value["repo"]
  })
  filename = "${path.module}/trigger-${each.value["project"]}.yaml"
}

The local_file resource will create as many files as you need, where the names of the files will be different depending on the project name. So for your current example this will crate a file with name trigger-test.yaml in the same directory. Then, in the module you are calling, the null_resource would change to:

resource "null_resource" "trigger" {

  provisioner "local-exec" {
    command = <<EOT
      gcloud alpha ... --trigger_config ${var.filename}  \
EOT
  }
}

This should work if you have defined the variable filename in the module. Lastly, when calling the module, you can use the following code:

module "trigger" {
  source   = "./modules/trigger"
  for_each = local.repos

  filename = "${path.module}/trigger-${each.value["project"]}.yaml"
}

Upvotes: 1

Related Questions