stackaddrs: Addresses for things inside components

In the stacks model a component is essentially a container for a tree of
normal Terraform modules, and so anything that can appear in a Terraform
module can in principle appear inside a component.

With that in mind here we define a generic type that can represent
anything from package addrs belonging either to a stack configuration
(before instance expansion) or to a stack instance (after instance
expansion), and some aliases for a few combinations that make sense
together, such as stackaddrs.AbsResourceInstance being an
addrs.AbsResourceInstance belonging to a stackaddrs.AbsComponentInstance.

We'll probably add more aliases here later, but this is a starting set
that I expect will arise while implementing the planning-related models
for stacks.
pull/34738/head
Martin Atkins 3 years ago
parent e4d372c490
commit e0797ab913

@ -176,3 +176,11 @@ func (m Module) Ancestors() []Module {
func (m Module) configMoveableSigil() {
// ModuleInstance is moveable
}
type moduleKey string
func (moduleKey) uniqueKeySigil() {}
func (m Module) UniqueKey() UniqueKey {
return moduleKey(m.String())
}

@ -1,6 +1,9 @@
package stackaddrs
import "github.com/hashicorp/terraform/internal/addrs"
import (
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/collections"
)
// Component is the address of a "component" block within a stack config.
type Component struct {
@ -15,6 +18,13 @@ func (c Component) String() string {
return "component." + c.Name
}
func (c Component) UniqueKey() collections.UniqueKey[Component] {
return c
}
// A Component is its own [collections.UniqueKey].
func (Component) IsUniqueKey(Component) {}
// ConfigComponent places a [Component] in the context of a particular [Stack].
type ConfigComponent = InStackConfig[Component]
@ -37,6 +47,13 @@ func (c ComponentInstance) String() string {
return c.Component.String() + c.Key.String()
}
func (c ComponentInstance) UniqueKey() collections.UniqueKey[ComponentInstance] {
return c
}
// A ComponentInstance is its own [collections.UniqueKey].
func (ComponentInstance) IsUniqueKey(ComponentInstance) {}
// ConfigComponentInstance places a [ComponentInstance] in the context of a
// particular [Stack].
type ConfigComponentInstance = InStackConfig[ComponentInstance]

@ -0,0 +1,117 @@
package stackaddrs
import (
"fmt"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/collections"
)
// 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]
// 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
}

@ -1,28 +1,32 @@
package stackaddrs
import "github.com/hashicorp/terraform/internal/collections"
// StackItemConfig is a type set containing all of the address types that make
// sense to consider as belonging statically to a [Stack].
type StackItemConfig interface {
type StackItemConfig[T any] interface {
inStackConfigSigil()
String() string
collections.UniqueKeyer[T]
}
// StackItemDynamic is a type set containing all of the address types that make
// sense to consider as belonging dynamically to a [StackInstance].
type StackItemDynamic interface {
type StackItemDynamic[T any] interface {
inStackInstanceSigil()
String() string
collections.UniqueKeyer[T]
}
// InStackConfig is the generic form of addresses representing configuration
// objects belonging to particular nodes in the static tree of stack
// configurations.
type InStackConfig[T StackItemConfig] struct {
type InStackConfig[T StackItemConfig[T]] struct {
Stack Stack
Item T
}
func Config[T StackItemConfig](stackAddr Stack, relAddr T) InStackConfig[T] {
func Config[T StackItemConfig[T]](stackAddr Stack, relAddr T) InStackConfig[T] {
return InStackConfig[T]{
Stack: stackAddr,
Item: relAddr,
@ -36,14 +40,29 @@ func (ist InStackConfig[T]) String() string {
return ist.Stack.String() + "." + ist.Item.String()
}
func (ist InStackConfig[T]) UniqueKey() collections.UniqueKey[InStackConfig[T]] {
return inStackConfigKey[T]{
stackKey: ist.Stack.UniqueKey(),
itemKey: ist.Item.UniqueKey(),
}
}
type inStackConfigKey[T StackItemConfig[T]] struct {
stackKey collections.UniqueKey[Stack]
itemKey collections.UniqueKey[T]
}
// IsUniqueKey implements collections.UniqueKey.
func (inStackConfigKey[T]) IsUniqueKey(InStackConfig[T]) {}
// InStackInstance is the generic form of addresses representing dynamic
// instances of objects that exist within an instance of a stack.
type InStackInstance[T StackItemDynamic] struct {
type InStackInstance[T StackItemDynamic[T]] struct {
Stack StackInstance
Item T
}
func Absolute[T StackItemDynamic](stackAddr StackInstance, relAddr T) InStackInstance[T] {
func Absolute[T StackItemDynamic[T]](stackAddr StackInstance, relAddr T) InStackInstance[T] {
return InStackInstance[T]{
Stack: stackAddr,
Item: relAddr,
@ -57,12 +76,27 @@ func (ist InStackInstance[T]) String() string {
return ist.Stack.String() + "." + ist.Item.String()
}
func (ist InStackInstance[T]) UniqueKey() collections.UniqueKey[InStackInstance[T]] {
return inStackInstanceKey[T]{
stackKey: ist.Stack.UniqueKey(),
itemKey: ist.Item.UniqueKey(),
}
}
type inStackInstanceKey[T StackItemDynamic[T]] struct {
stackKey collections.UniqueKey[StackInstance]
itemKey collections.UniqueKey[T]
}
// IsUniqueKey implements collections.UniqueKey.
func (inStackInstanceKey[T]) IsUniqueKey(InStackInstance[T]) {}
// ConfigForAbs returns the "in stack config" equivalent of the given
// "in stack instance" (absolute) address by just discarding any
// instance keys from the stack instance steps.
func ConfigForAbs[T interface {
StackItemDynamic
StackItemConfig
StackItemDynamic[T]
StackItemConfig[T]
}](absAddr InStackInstance[T]) InStackConfig[T] {
return Config(absAddr.Stack.ConfigAddr(), absAddr.Item)
}

@ -1,5 +1,7 @@
package stackaddrs
import "github.com/hashicorp/terraform/internal/collections"
type InputVariable struct {
Name string
}
@ -12,6 +14,13 @@ func (v InputVariable) String() string {
return "var." + v.Name
}
func (v InputVariable) UniqueKey() collections.UniqueKey[InputVariable] {
return v
}
// An InputVariable is its own [collections.UniqueKey].
func (InputVariable) IsUniqueKey(InputVariable) {}
// ConfigInputVariable places an [InputVariable] in the context of a particular [Stack].
type ConfigInputVariable = InStackConfig[InputVariable]

@ -1,5 +1,7 @@
package stackaddrs
import "github.com/hashicorp/terraform/internal/collections"
type LocalValue struct {
Name string
}
@ -12,6 +14,13 @@ func (v LocalValue) String() string {
return "local." + v.Name
}
func (v LocalValue) UniqueKey() collections.UniqueKey[LocalValue] {
return v
}
// A LocalValue is its own [collections.UniqueKey].
func (LocalValue) IsUniqueKey(LocalValue) {}
// ConfigLocalValue places a [LocalValue] in the context of a particular [Stack].
type ConfigLocalValue = InStackConfig[LocalValue]

@ -1,5 +1,7 @@
package stackaddrs
import "github.com/hashicorp/terraform/internal/collections"
type OutputValue struct {
Name string
}
@ -11,6 +13,13 @@ func (v OutputValue) String() string {
return "output." + v.Name
}
func (v OutputValue) UniqueKey() collections.UniqueKey[OutputValue] {
return v
}
// An OutputValue is its own [collections.UniqueKey].
func (OutputValue) IsUniqueKey(OutputValue) {}
// ConfigOutputValue places an [OutputValue] in the context of a particular [Stack].
type ConfigOutputValue = InStackConfig[OutputValue]

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/collections"
)
// ProviderConfigRef is a reference-only address type representing a reference
@ -37,6 +38,13 @@ func (c ProviderConfig) String() string {
return fmt.Sprintf("provider[%q].%s", c.Provider, c.Name)
}
func (v ProviderConfig) UniqueKey() collections.UniqueKey[ProviderConfig] {
return v
}
// A ProviderConfig is its own [collections.UniqueKey].
func (ProviderConfig) IsUniqueKey(ProviderConfig) {}
// ConfigProviderConfig places a [ProviderConfig] in the context of a particular [Stack].
type ConfigProviderConfig = InStackConfig[ProviderConfig]
@ -61,6 +69,13 @@ func (c ProviderConfigInstance) String() string {
return c.ProviderConfig.String() + c.Key.String()
}
func (v ProviderConfigInstance) UniqueKey() collections.UniqueKey[ProviderConfigInstance] {
return v
}
// A ProviderConfigInstance is its own [collections.UniqueKey].
func (ProviderConfigInstance) IsUniqueKey(ProviderConfigInstance) {}
// ConfigProviderConfigInstance places a [ProviderConfigInstance] in the context of a particular [Stack].
type ConfigProviderConfigInstance = InStackConfig[ProviderConfigInstance]

@ -4,6 +4,7 @@ import (
"strings"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/collections"
)
// Stack represents the address of a stack within the tree of stacks.
@ -61,6 +62,15 @@ func (s Stack) String() string {
return buf.String()
}
func (s Stack) UniqueKey() collections.UniqueKey[Stack] {
return stackUniqueKey(s.String())
}
type stackUniqueKey string
// IsUniqueKey implements collections.UniqueKey.
func (stackUniqueKey) IsUniqueKey(Stack) {}
// StackInstance represents the address of an instance of a stack within
// the tree of stacks.
//
@ -150,3 +160,12 @@ func (s StackInstance) String() string {
}
return buf.String()
}
func (s StackInstance) UniqueKey() collections.UniqueKey[StackInstance] {
return stackInstanceUniqueKey(s.String())
}
type stackInstanceUniqueKey string
// IsUniqueKey implements collections.UniqueKey.
func (stackInstanceUniqueKey) IsUniqueKey(StackInstance) {}

@ -1,6 +1,9 @@
package stackaddrs
import "github.com/hashicorp/terraform/internal/addrs"
import (
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/collections"
)
// StackCall represents a call to an embedded stack. This is essentially the
// address of a "stack" block in the configuration, before it's been fully
@ -17,6 +20,15 @@ func (c StackCall) String() string {
return "stack." + c.Name
}
func (c StackCall) UniqueKey() collections.UniqueKey[StackCall] {
return stackCallUniqueKey(c.String())
}
type stackCallUniqueKey string
// IsUniqueKey implements collections.UniqueKey.
func (stackCallUniqueKey) IsUniqueKey(StackCall) {}
// ConfigStackCall represents a static stack call inside a particular [Stack].
type ConfigStackCall = InStackConfig[StackCall]

Loading…
Cancel
Save