// Copyright IBM Corp. 2014, 2026 // SPDX-License-Identifier: BUSL-1.1 package stackaddrs import ( "fmt" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/collections" "github.com/hashicorp/terraform/internal/tfdiags" ) // InConfigComponent represents addresses of objects that belong to the modules // associated with a particular component. // // Although the type parameter is rather unconstrained, it doesn't make sense to // use this for types other than those from package addrs that represent // configuration constructs, like [addrs.ConfigResource], etc. type InConfigComponent[T InComponentable] struct { Component ConfigComponent Item T } // ConfigResource represents a resource configuration from inside a // particular component. type ConfigResource = InConfigComponent[addrs.ConfigResource] // ConfigModule represents a module from inside a particular component. // // Note that the string representation of the address of the root module of // a component is identical to the string representation of the component // address alone. type ConfigModule = InConfigComponent[addrs.Module] func (c InConfigComponent[T]) String() string { itemStr := c.Item.String() componentStr := c.Component.String() if itemStr == "" { return componentStr } return componentStr + "." + itemStr } // UniqueKey implements collections.UniqueKeyer. func (c InConfigComponent[T]) UniqueKey() collections.UniqueKey[InConfigComponent[T]] { return inConfigComponentKey[T]{ componentKey: c.Component.UniqueKey(), itemKey: c.Item.UniqueKey(), } } type inConfigComponentKey[T InComponentable] struct { componentKey collections.UniqueKey[ConfigComponent] itemKey addrs.UniqueKey } // IsUniqueKey implements collections.UniqueKey. func (inConfigComponentKey[T]) IsUniqueKey(InConfigComponent[T]) {} // InAbsComponentInstance represents addresses of objects that belong to the module // instances associated with a particular component instance. // // Although the type parameter is rather unconstrained, it doesn't make sense to // use this for types other than those from package addrs that represent // objects that can belong to Terraform modules, like // [addrs.AbsResourceInstance], etc. type InAbsComponentInstance[T InComponentable] struct { Component AbsComponentInstance Item T } // AbsResource represents a not-yet-expanded resource from inside a particular // component instance. type AbsResource = InAbsComponentInstance[addrs.AbsResource] var _ collections.UniqueKeyer[AbsResource] = AbsResource{} // AbsResourceInstance represents an instance of a resource from inside a // particular component instance. type AbsResourceInstance = InAbsComponentInstance[addrs.AbsResourceInstance] // AbsResourceInstanceObject represents an object associated with an instance // of a resource from inside a particular component instance. type AbsResourceInstanceObject = InAbsComponentInstance[addrs.AbsResourceInstanceObject] // AbsActionInvocationInstance represents an instance of an action from inside a // particular component instance. type AbsActionInvocationInstance = InAbsComponentInstance[addrs.AbsActionInstance] // AbsModuleInstance represents an instance of a module from inside a // particular component instance. // // Note that the string representation of the address of the root module of // a component instance is identical to the string representation of the // component instance address alone. type AbsModuleInstance = InAbsComponentInstance[addrs.ModuleInstance] func (c InAbsComponentInstance[T]) String() string { itemStr := c.Item.String() componentStr := c.Component.String() if itemStr == "" { return componentStr } return componentStr + "." + itemStr } // UniqueKey implements collections.UniqueKeyer. func (c InAbsComponentInstance[T]) UniqueKey() collections.UniqueKey[InAbsComponentInstance[T]] { return inAbsComponentInstanceKey[T]{ componentKey: c.Component.UniqueKey(), itemKey: c.Item.UniqueKey(), } } type inAbsComponentInstanceKey[T InComponentable] struct { componentKey collections.UniqueKey[AbsComponentInstance] itemKey addrs.UniqueKey } // IsUniqueKey implements collections.UniqueKey. func (inAbsComponentInstanceKey[T]) IsUniqueKey(InAbsComponentInstance[T]) {} // InComponentable just embeds the interfaces that we require for the type // parameters of both the [InConfigComponent] and [InAbsComponent] types. type InComponentable interface { addrs.UniqueKeyer fmt.Stringer } func ParseAbsResourceInstanceObject(traversal hcl.Traversal) (AbsResourceInstanceObject, tfdiags.Diagnostics) { stack, remain, diags := ParseAbsComponentInstanceOnly(traversal) if diags.HasErrors() { return AbsResourceInstanceObject{}, diags } resource, diags := addrs.ParseAbsResourceInstance(remain) if diags.HasErrors() { return AbsResourceInstanceObject{}, diags } return AbsResourceInstanceObject{ Component: stack, Item: addrs.AbsResourceInstanceObject{ ResourceInstance: resource, }, }, diags } func ParseAbsResourceInstanceObjectStr(s string) (AbsResourceInstanceObject, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics traversal, hclDiags := hclsyntax.ParseTraversalAbs([]byte(s), "", hcl.InitialPos) diags = diags.Append(hclDiags) if diags.HasErrors() { return AbsResourceInstanceObject{}, diags } ret, moreDiags := ParseAbsResourceInstanceObject(traversal) diags = diags.Append(moreDiags) return ret, diags }