Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interpolating data source name in Terraform

Tags:

Am trying to write a terraform module for attaching bucket policy to a AWS S3 bucket. Here is the code:

data "aws_iam_policy_document" "make_objects_public" {
  # if policy_name == <this-policy-name>, then generate policy
  count = "${var.policy_name == "make_objects_public" ? 1 : 0}"

  statement {
    ...
  }
}

resource "aws_s3_bucket_policy" "bucket_policy" {
  # if policy_name != "", then add the generated policy
  count = "${var.policy_name != "" ? 1 : 0}"

  bucket = "${var.bucket_name}"
  policy = "${data.aws_iam_policy_document.<policy-name-goes-here>.json}"
}

I want to interpolate the policy_name variable while fetching the policy generated by aws_iam_policy_document. I tried few things but sadly they didn't work. Is this possible in terraform ?

I tried out these hacks:

policy = "${data.aws_iam_policy_document."${var.policy_name}".json}"

policy = "${"${format("%s", "data.aws_iam_policy_document.${var.policy_name}.json")}"}"

policy = "${format("%s", "$${data.aws_iam_policy_document.${var.policy_name}.json}")}"

Thanks.

like image 778
arunvelsriram Avatar asked Aug 19 '17 14:08

arunvelsriram


People also ask

How do you interpolate in Terraform?

Embedded within strings in Terraform, whether you're using the Terraform syntax or JSON syntax, you can interpolate other values. These interpolations are wrapped in ${} , such as ${var. foo} . The interpolation syntax is powerful and allows you to reference variables, attributes of resources, call functions, etc.

What is the difference between a variable and data source in Terraform?

Variable Provides predefined values as variables on our IAC. Used by resource for provisioning. Data Source: Fetch values from our infra/provider and and provides data for our resource to provision infra/resource.

What are Terraform data sources?

What are Terraform data sources? Data sources in Terraform are used to get information about resources external to Terraform, and use them to set up your Terraform resources. For example, a list of IP addresses a cloud provider exposes.

During which phase Terraform read from data sources?

Terraform reads data resources during the planning phase when possible, but announces in the plan when it must defer reading resources until the apply phase to preserve the order of operations.


1 Answers

Dynamic resource names are not supported because Terraform must construct the dependency graph before it begins dealing with interpolations, and thus these relationships must be explicit.

A recommended approach for this sort of setup is to break the system down into small modules, which can then be used together by a calling module to produce the desired result without duplicating all of the details.

In this particular situation, you could for example split each policy out into its own re-usable module, and then write one more re-usable module that creates an S3 bucket and associates a given policy with it. Then a calling configuration may selectively instantiate one policy module appropriate to its needs along with the general S3 bucket module, to create the desired result:

module "policy" {
  # policy-specific module; only contains the policy data source
  source = "../policies/make_objects_public"

  # (any other arguments the policy needs...)
}

module "s3_bucket" {
  # S3 bucket module creates a bucket and attaches a policy to it
  source = "../s3_bucket" # general resource for S3 buckets with attached policies

  name   = "example"
  policy = "${module.policy.policy_json}" # an output from the policy module above
}

As well as avoiding the need for dynamic resource selection, this also increases flexibility by decoupling policy generation from the S3 bucket creation, and in principle allowing a calling module with unusual needs to skip instantiating a policy module altogether and just use aws_iam_policy_document directly.

The above pattern is somewhat analogous to the dependency injection technique, where the system is split into small components (modules, in this case) and then the root config "wires up" these components in a manner appropriate for a specific use-case. This approach has very similar advantages and disadvantages as the general technique.

like image 105
Martin Atkins Avatar answered Sep 30 '22 13:09

Martin Atkins