Skip to content
GantryCD

Resource identity overrides

GantryCD matches AWS resources by resource type, realm, and resource ID. It normally gets the ID from the resource ARN. Use these controls when that identity needs to change.

Override the resource ID

Set gantrycd:resource-identity-id in the resource’s own tags:

resource "aws_sqs_queue" "events" {
  name = "events"

  tags = {
    "gantrycd:resource-identity-id" = "shared-events"
  }
}

This value replaces the ID found by GantryCD. Set it on the resource, not in the AWS provider’s default_tags.

Another stack matches it only if its data source reads those tags back. Some data sources expose no tags at all — aws_s3_bucket and aws_kms_key among them — and there a declared ID or realm on the resource removes the inferred match instead of narrowing it. Declare the dependency with gantrycd:dependency: for those.

Set the realm

A realm separates resources with the same ID in different AWS-compatible endpoints. For example, give every taggable resource managed through this OpenStack S3 endpoint the same realm:

provider "aws" {
  endpoints {
    s3 = "https://s3.openstack.example.com"
  }

  default_tags {
    tags = {
      "gantrycd:resource-identity-realm" = "openstack-eu-1"
    }
  }
}

You can also set gantrycd:resource-identity-realm in one resource’s tags. Resources match only when their realms match.

A realm names the endpoint, not the account or the environment: real AWS, one LocalStack instance, one MotoServer. Accounts need no realm — the account is already part of the ARN, and two accounts on real AWS are the same world. Leave resources on real AWS unscoped and name the emulators, so an ARN minted by LocalStack never reads as the real object it mimics.

Stand in for another resource

A random resource names no cloud object, so it has an identity only when you give it one. Put the identity keys in keepers, and add gantrycd:resource-identity-type to say which kind of object it represents — matching compares types, so without it the resource only ever matches another random one:

resource "random_string" "role" {
  for_each = local.included_environments
  length   = 8

  keepers = {
    "gantrycd:resource-identity-id"   = "arn:aws:iam::${var.aws_accounts[each.value.account_name].id}:role/app-${each.key}"
    "gantrycd:resource-identity-type" = "aws_iam_role"
  }
}

OpenTofu evaluates keepers per instance, so one block covers every key of a for_each with a different identity each — variables, locals and functions all work, because they are resolved before the value reaches state.

Ignore tagged resources

Use the value "null" to remove the identity from a taggable resource:

tags = {
  "gantrycd:resource-identity-id" = "null"
}

Put this tag in default_tags to ignore all taggable resources for that AWS provider.

Set them by address instead

Tags reach a resource only if its schema has them, and a data source carries the object’s tags rather than yours — many expose none at all. Name the address in a comment when a tag cannot reach it:

# gantrycd:resource-identity: resource=data.aws_s3_bucket.shared id=shared-logs realm=localstack-ci

id applies to that address alone — including one instance of a for_each block, addressed by its key:

# gantrycd:resource-identity: resource=aws_iam_role.by_env["prod"] id=arn:aws:iam::12345:role/app

realm also covers everything under the address, so a module prefix gives a whole subtree the same realm:

# gantrycd:resource-identity: resource=module.legacy realm=localstack-ci

When several stacks share the directory

Add stack or stack_regex to apply a comment to one of them, exactly as a dependency does. Others skip it:

# gantrycd:resource-identity: resource=data.aws_s3_bucket.shared stack=shop-ci realm=localstack-ci
# gantrycd:resource-identity: resource=data.aws_s3_bucket.shared stack=shop-prod

Or render the value from the stack with id_tpl / realm_tpl, so a new stack needs no edit:

# gantrycd:resource-identity: resource=data.aws_s3_bucket.shared realm_tpl="{{ .stack.Labels.Endpoint }}"

ignore has no template: an opt-out is a policy, and a policy must not depend on rendered metadata.

Ignore Terraform addresses

Comments also work for data sources and AWS resources without tags:

# gantrycd:resource-identity: ignore=true
data "aws_s3_bucket" "logs" {
  bucket = "external-logs"
}

Set resource=<address> to target another address. Use its full address from the stack root when it is inside a module:

# gantrycd:resource-identity: resource=module.legacy.aws_s3_bucket.logs ignore=true

GantryCD only reads comments in the root module. It does not resolve comments or relative addresses from inside child modules.

Use ignore=false on a more specific address to include it again:

# gantrycd:resource-identity: resource=module.legacy ignore=true
# gantrycd:resource-identity: resource=module.legacy.aws_sqs_queue.keep ignore=false

The nearest comment to an address wins, and ignore=true cannot be combined with id or realm — one disclaims an address, the others assign to it.