hashicorp/terraform
Addresses
Active contributors: Martin Atkins, James Bardin.
Purpose
internal/addrs/ provides typed Go values for every kind of object Terraform names: resources, modules, providers, references, output values, input variables, local values, etc. It also handles parsing, formatting, and equality comparisons for those addresses. Every other package in the codebase depends on addrs.
Why a dedicated package
Configuration objects, runtime objects, and persisted state all need stable, parseable identifiers. Pre-0.12 Terraform used strings for these and accumulated a spaghetti of ad-hoc parsing. The rewrite extracted typed addresses so:
- Parsing happens at one boundary (
addrs.ParseAbsResource,addrs.ParseAbsResourceInstanceStr, etc.). - The compiler enforces that callees receive the right kind of address.
- Formatting is consistent across the CLI, JSON output, state files, and plan files.
- Address relationships (a
ResourceInstanceis contained in aResourceis contained in aModuleInstance) are explicit.
Key types
| Type | File | Notes |
|---|---|---|
addrs.Resource |
resource.go |
A resource or data block, identified within its module by mode + type + name. |
addrs.AbsResource |
resource.go |
A Resource qualified with its ModuleInstance. |
addrs.AbsResourceInstance |
resource.go |
An instance produced by count / for_each. The leaf address used in state. |
addrs.Module |
module.go |
A module path (no instance keys) — the static configuration coordinate. |
addrs.ModuleInstance |
module_instance.go |
A module path with count/for_each keys filled in. The runtime coordinate. |
addrs.Provider |
provider.go |
Fully-qualified provider source: hostname/namespace/type. |
addrs.LocalProviderConfig |
provider_config.go |
The user-visible alias (aws, aws.east) within a module. |
addrs.AbsProviderConfig |
provider_config.go |
A LocalProviderConfig qualified with a module instance, plus the Provider it resolves to. |
addrs.Reference |
parse_ref.go |
A parsed expression traversal: Subject (some Referenceable) plus Remaining traversal and source range. |
addrs.OutputValue, LocalValue, InputVariable |
output_value.go, local_value.go, input_variable.go |
The three named-value declaration types. |
addrs.Resource{Mode} enum |
resource_mode.go |
ManagedResourceMode, DataResourceMode, plus newer EphemeralResourceMode, ListResourceMode. |
addrs.Check, Action, EphemeralResourceInstance |
various | Newer top-level addressable kinds added with checks, actions, and ephemerals. |
addrs.RemovedTarget, MoveEndpoint |
remove_target.go, move_endpoint.go |
Targets used by the removed and moved blocks. |
addrs.Targetable |
targetable.go |
Interface implemented by anything that can appear in a -target= flag. |
How it works
The shape of a typical type:
// AbsResourceInstance is the address of a resource instance.
type AbsResourceInstance struct {
Module ModuleInstance
Resource ResourceInstance
}
func (r AbsResourceInstance) String() string { /* ... */ }
func (r AbsResourceInstance) Equal(o AbsResourceInstance) bool { /* ... */ }
func ParseAbsResourceInstance(traversal hcl.Traversal) (AbsResourceInstance, tfdiags.Diagnostics) { /* ... */ }
func ParseAbsResourceInstanceStr(s string) (AbsResourceInstance, tfdiags.Diagnostics) { /* ... */ }Parsers come in two flavors: from an hcl.Traversal (for use during configuration parsing) and from a string (for state files, JSON output, and -target flags). Both produce tfdiags.Diagnostics so callers can surface useful errors with source ranges where available.
Provider addresses
Providers have two representations:
- Local (
addrs.LocalProviderConfig): theawsoraws.eastusers write. Local references are scoped to one module and are resolved againstrequired_providers. - Absolute (
addrs.AbsProviderConfig): the resolved address that includes the module instance, the local name, and the fully-qualified provider source.
Resolution from local→absolute happens during graph building, in the provider transformer (internal/terraform/transform_provider.go). Once resolved, the engine works exclusively with AbsProviderConfig so there's no ambiguity about which provider configuration owns a resource.
Targetable
addrs.Targetable is the interface used by anything -target= can name: AbsResource, AbsResourceInstance, ModuleInstance. The target_addrs.go file holds the parsing logic that lets users type module.web.aws_instance.app[0] on the command line.
Move endpoints
MoveEndpoint represents one side of a moved block (from = X, to = Y). Endpoints know how to bind themselves to either a configuration address or a state address, accommodating users who write from = aws_instance.foo (resource block) versus from = aws_instance.foo[2] (instance).
Sub-packages
addrsitself is flat — there are no sub-packages. The package is intentionally small and dependency-light so that almost every other package in the codebase can import it.
Integration points
- Configuration:
internal/configsproduces addresses for every block it parses. - Language:
internal/lang/langrefs.Referencesreturns[]*addrs.Reference. - Engine: every vertex carries one or more typed addresses. The graph itself is keyed on stringified addresses for printing but Go values for comparisons.
- State:
internal/statesindexes resources byaddrs.AbsResourceand instances byaddrs.AbsResourceInstance. The state file's textual form uses the same parser. - Plans:
internal/plans.ResourceInstanceChange.Addris anaddrs.AbsResourceInstance. - CLI:
-target,state list,state mv,state rm, and many others parse strings via this package.
Entry points for modification
- Adding a new addressable kind (e.g. when "actions" were added): create a new type implementing
Referenceable/Targetableas appropriate, write the parser and printer, and update the engine's vertex types and the language reference resolver. - Changing how a string parses: edit the
Parse...Strfamily of functions. Be careful — many places (state files, JSON output, plan files) depend on the round-trip. - Adding a new mode for resources: extend
addrs.ResourceModeand audit every consumer that switches on it.
The package is intentionally conservative; almost any change here ripples to dozens of files.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.