Dynamic configuration blocks in Terraform

1 minute read

Terraform


One of the things I had to resolve was the fact that in Terraform there are configuration blocks that, depending on the options may have different parameters or may not even accept the same parameters.

To do that, and by following a code from a community module, I managed to overcome this problem using Terraform’s locals values

Taking an example of this we have the artifacts block of the Terraform aws_codebuild_project resource, which may have some parameters if the type is S3, CODEPIPELINE or NO_ARTIFACTS. For example, if you define a block as follows, it will not be easy to parameterize it:

resource "aws_codebuild_project" "codebuild" {

[...]

  artifacts{
      type           = "${var.codebuild_artifacts_type}"
      location       = "${var.codebuild_artifacts_location}"
      name           = "${var.codebuild_artifacts_name}"
      namespace_type = "${var.codebuild_artifacts_namespace_type}"
      packaging      = "${var.codebuild_artifacts_packaging}"
      path           = "${var.codebuild_artifacts_path}"

  }
}

If we try to place the NO_ARTIFACTS, for example, it will fail because even if “empty” values are placed for the other parameters, these arguments are not supported. To resolve this you have to create a block definition with locals according to the type provided by type and use this as an index:

resource "aws_codebuild_project" "codebuild" {

[...]

  artifacts = ["${local.codebuild_artifacts}"]

}

locals {
  codebuild_artifacts_def = {
    "S3" = [{
      type           = "${var.codebuild_artifacts_type}"
      location       = "${var.codebuild_artifacts_location}"
      name           = "${var.codebuild_artifacts_name}"
      namespace_type = "${var.codebuild_artifacts_namespace_type}"
      packaging      = "${var.codebuild_artifacts_packaging}"
      path           = "${var.codebuild_artifacts_path}"
    }]

    "CODEPIPELINE" = [{
      type           = "${var.codebuild_artifacts_type}"
      location       = "${var.codebuild_artifacts_location}"
      name           = "${var.codebuild_artifacts_name}"
      namespace_type = "${var.codebuild_artifacts_namespace_type}"
      packaging      = "${var.codebuild_artifacts_packaging}"
      path           = "${var.codebuild_artifacts_path}"
    }]

    "NO_ARTIFACTS" = [{
      type = "${var.codebuild_artifacts_type}"
    }]
  }

  # Retuned map
  codebuild_artifacts = "${local.codebuild_artifacts_def[var.codebuild_artifacts_type]}"
}

This creates a different block depending on the type defined in the variable codebuild_artifacts_type.

References:

Leave a Comment