Search code examples
amazon-web-servicesamazon-s3terraforminfrastructure-as-code

How to reference an id value from another main.tf file residing in a different module in Terraform


Is there a way to reference an id value from another object located in a different main.tf file in a different module?

If the two resources or objects are located in the same file you just do this

resource "aws_s3_bucket" "log_bucket" {
  bucket = "my-tf-log-bucket"
  acl    = "log-delivery-write"
}

resource "aws_s3_bucket" "b" {
  bucket = "my-tf-test-bucket"
  acl    = "private"

  logging {
    target_bucket = aws_s3_bucket.log_bucket.id
    target_prefix = "log/"
  }
}

You can assign the target_bucket for logging to the id of the bucket in resource "aws_s3_bucket"

Now suppose I have two folders named log_module and s3_module with their respective main.tf files.

The main.tf inside the log_module contains

resource "aws_s3_bucket" "log_bucket" {
  bucket = "my-tf-log-bucket"
  acl    = "log-delivery-write"
}

and the main.tf inside the s3_module contains

resource "aws_s3_bucket" "b" {
  bucket = "my-tf-test-bucket"
  acl    = "private"

  logging {
    target_bucket = "target-bucket"
    target_prefix = "log/"
  }
}

How would I assign the id for the bucket in resource "aws_s3_bucket" "log_bucket" to the target_bucket in the main.tf for the s3_module?


Solution

  • You can use Terraform output values to achieve this functionality.

    In your log_module directory, you can create a new file named outputs.tf and define a new output like so:

    output "bucket_id" {
      value = aws_s3_bucket.log_bucket.id
    }
    

    In your s3_module, you would need to create a variables file (e.g., variables.tf) which would be used to assign a value to the target_bucket for the aws_s3_bucket resource.

    For example:

    variable "target_bucket" {
      description = "The name of the bucket that will receive the log objects"
      type        = string
    }
    

    Then you would modify the main.tf file in your s3_module directory like so:

    resource "aws_s3_bucket" "b" {
      bucket = "my-tf-test-bucket"
      acl    = "private"
    
      logging {
        target_bucket = var.target_bucket
        target_prefix = "log/"
      }
    }
    

    Where the value of target_bucket is derived from var.target_bucket.

    You would then have to create a main.tf file in the root of your repository like so:

    module "logging" {
      source = "/path/to/log_module/directory"
    
      // Any inputs to the module defined here
    }
    
    module "s3" {
      source = "/path/to/s3_module/directory"
    
      target_bucket = module.logging.bucket_id
    }
    

    The main.tf file in the root of the repository creates in implicit dependency between the s3 and logging modules. The s3 module becomes dependent on the logging module because the value of target_bucket uses the output of the logging module, which is the ID of the S3 bucket.