Terraform Error: Reference to undeclared resource

Viewed 9982

I am trying to run s3 replication in terraform which will be cross-regional. Most of my code is good but I am only getting 2 errors which I cannot seem to solve.

Part of my main s3.tf is

resource "aws_kms_key" "s3_replica-us-west-2" {
  description             = "S3 master key replica us-west-2"
  deletion_window_in_days = 30
  enable_key_rotation     = "true"
}

module "s3_replica" {
  source = "git@github.com:xxx"

  providers = {
    aws     = "aws.us-west-2"
  }

  name                  = "s3_replica"
  logging_bucket_prefix = "s3_replica"
  versioning            = var.versioning
  bucket_logging        = var.bucket_logging
  logging_bucket_name   = var.logging_bucket_name

  kms_key_id    = aws_kms_key.s3_replica-us-west-2.key_id
  sse_algorithm = var.sse_algorithm
}

module "s3" {
  source                = "git@github.com:xxxx"
  name                  = "s3"
  logging_bucket_prefix = "s3"
  versioning            = var.versioning
  bucket_logging        = var.bucket_logging
  logging_bucket_name   = var.logging_bucket_name

  kms_key_id    = aws_kms_key.s3.key_id
  sse_algorithm = var.sse_algorithm

  replication_configuration = {
    role = aws_iam_role.s3_replication.arn

      rules = {
         id = "replicate_to_${local.s3_replica}"
         prefix = ""
         status = "Enabled"

        destination = {
          bucket = lookup.module.s3_replica.bucket_arn
          replica_kms_key_id = lookup.s3_replica_arn
          }
        }

      source_selection_criteria = {
          sse_kms_encrypted_objects = {
            enabled = true
          }
        }
  }

and the part of my replication configuration block in the module I use is:

dynamic "replication_configuration" {
    for_each = length(keys(var.replication_configuration)) == 0 ? [] : [var.replication_configuration]

    content {
      role = replication_configuration.value.role

      dynamic "rules" {
        for_each = replication_configuration.value.rules

        content {
          id       = lookup(rules.value, "id", null)
          priority = lookup(rules.value, "priority", null)
          prefix   = lookup(rules.value, "prefix", null)
          status   = lookup(rules.value, "status", null)

          dynamic "destination" {
            for_each = length(keys(lookup(rules.value, "destination", {}))) == 0 ? [] : [lookup(rules.value, "destination", {})]

            content {
              bucket             = lookup(destination.value, "bucket", null)
              storage_class      = lookup(destination.value, "storage_class", null)
              replica_kms_key_id = lookup(destination.value, "replica_kms_key_id", null)
              account_id         = lookup(destination.value, "account_id", null)
            }
          }

          dynamic "source_selection_criteria" {
            for_each = length(keys(lookup(rules.value, "source_selection_criteria", {}))) == 0 ? [] : [lookup(rules.value, "source_selection_criteria", {})]

            content {

              dynamic "sse_kms_encrypted_objects" {
                for_each = length(keys(lookup(source_selection_criteria.value, "sse_kms_encrypted_objects", {}))) == 0 ? [] : [lookup(source_selection_criteria.value, "sse_kms_encrypted_objects", {})]

                content {

                  enabled = sse_kms_encrypted_objects.value.enabled
                }
              }
            }
          }

        }
      }
    }
  }
}

Now when I run terraform init... it works. But when I run terraform plan I get the error:

Error: Reference to undeclared resource

  on s3.tf line 108, in module "s3":
 108:           bucket = lookup.module.s3_replica.bucket_arn

A managed resource "lookup" "module" has not been declared in the root module.


Error: Reference to undeclared resource

  on s3.tf line 109, in module "s3":
 109:           replica_kms_key_id = lookup.s3_replica-us-west-2_arn

A managed resource "lookup" "s3_replica_arn" has not been declared
in the root module.

Now I do not know why I get these errors..

1 Answers

From what I understand, your s3_replica bucket is created in module.s3, and you want to access its ARN to initialize the module.s3. Sadly, you can't do this, as you can't reference module outputs before the module is fully created.

One way to overcome this issue, is to create s3_replica first, and then pass it to module.s3. Below is just an example, probably need many further modifications:

resource "aws_s3_bucket" "s3_replica" {
  bucket = "my-replication-bucket-23223"
  acl    = "private"
}

resource "aws_kms_key" "s3_replica" {
  description             = "KMS for replication"
  deletion_window_in_days = 10
}

module "s3" {

  # 
  #

  replication_configuration = {
    role = aws_iam_role.s3_replication.arn

      rules = {
         id = "replicate_to_${local.s3_replica}"
         prefix = ""
         status = "Enabled"

        destination = {
          bucket             = resource.aws_s3_bucket.s3_replica.arn
          replica_kms_key_id = resource.aws_kms_key.s3_replica.arn
          }
        }

      source_selection_criteria = {
          sse_kms_encrypted_objects = {
            enabled = true
          }
        }
  }

I would recommend having a look at Module Composition in TF docs. It explains, with examples, how to work with modules.

Related