Shiraaz.M
Shiraaz.M

Reputation: 3191

How to reduce boilerplate provisioning in modules?

So I have two terraform modules that are exactly the same ... the exception is that there is one extra remote-execution step

Module A

  provisioner "remote-exec" {
    inline = [
      "sudo chmod 777 -R ${var.setup_files_destination}",
      "sudo ${var.setup_files_destination}/scripts/setup.sh ${var.setup_files_destination}",
    ]

    connection {
      user        = "ec2-user"
      private_key = "${file(var.private_key_location)}"
    }
  }

Module B - Difference is one extra script to execute

  provisioner "remote-exec" {
    inline = [
      "sudo chmod 777 -R ${var.setup_files_destination}",
      "sudo ${var.setup_files_destination}/scripts/setup.sh ${var.setup_files_destination}",
    ]

    connection {
      user        = "ec2-user"
      private_key = "${file(var.private_key_location)}"
    }
  }

  provisioner "remote-exec" {
    inline = [
      "sudo chmod 777 -R ${var.setup_files_destination}",
      "${var.setup_files_destination}/scripts/setup_special.sh ${var.setup_files_destination}",
    ]

    connection {
      user        = "ec2-user"
      private_key = "${file(var.private_key_location)}"
    }
  }

Other than this script difference, the modules have the exact same steps. The amount of duplicate terraform code is around 50 lines.

What I would like to do in Terraform

So on the Terraform side, I would like to specify the scripts to execute as a list, so something like

Variable

variable "commands_to_execute" {
  type = "list"
}

Common Step

provisioner "remote-exec" {
  inline = "[${var.commands_to_execute}]"

  connection {
    user        = "ec2-user"
    private_key = "${file(var.private_key_location)}"
  }
}

Perceived use of common step

module "instances" {
  ... rest of declaration...
  commands_to_execute = [
    "sudo chmod 777 -R ${var.setup_files_destination}",
    "sudo ${var.setup_files_destination}/scripts/setup.sh ${var.setup_files_destination}",
  ]
}

When I run this, I get

Error: module 'instances': unknown variable referenced: 'setup_files_destination'; define it with a 'variable' block

So setup_files_destination is a variable defined inside the module, but not in the .tf file using the module. It has a default value and is effectively the location to the directory of the shell script on the remote instance.

I would like to keep the setup_files_destination in the module. So what I am looking for is a way to defer the interpolation of the variable until when the module is actually used. Is this possible in terraform?

Upvotes: 0

Views: 155

Answers (1)

Stephen
Stephen

Reputation: 3727

It's not possible to defer the interpolation the way you are trying, you can probably achieve what you are trying to do using a null_resource and count. This will only run the script when you define the variable run_additional_setup = true in the module initialisation

Example:

resource "null_resource" "additional_setup" {
  count      = "${var.run_additional_setup == true ? 1 : 0}"
  depends_on = ["aws_instance.my_instance"]

  connection {
    user        = "ec2-user"
    private_key = "${file(var.private_key_location)}"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo chmod 777 -R ${var.setup_files_destination}",
      "${var.setup_files_destination}/scripts/setup_special.sh ${var.setup_files_destination}",
    ]
  }
}

Upvotes: 1

Related Questions