mirror of https://github.com/hashicorp/terraform
This serves a similar purpose to the "addrs" package for Terraform overall, but deals with concepts that are unique to the stacks language.pull/34738/head
parent
3bf1a5cf53
commit
e667352553
@ -0,0 +1,35 @@
|
||||
package stackaddrs
|
||||
|
||||
import "github.com/hashicorp/terraform/internal/addrs"
|
||||
|
||||
// Component is the address of a "component" block within a stack config.
|
||||
type Component struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (Component) referenceableSigil() {}
|
||||
func (Component) inStackConfigSigil() {}
|
||||
func (Component) inStackInstanceSigil() {}
|
||||
|
||||
// ConfigComponent places a [Component] in the context of a particular [Stack].
|
||||
type ConfigComponent = InStackConfig[Component]
|
||||
|
||||
// AbsComponent places a [Component] in the context of a particular [StackInstance].
|
||||
type AbsComponent = InStackInstance[Component]
|
||||
|
||||
// ComponentInstance is the address of a dynamic instance of a component.
|
||||
type ComponentInstance struct {
|
||||
Component Component
|
||||
Key addrs.InstanceKey
|
||||
}
|
||||
|
||||
func (ComponentInstance) inStackConfigSigil() {}
|
||||
func (ComponentInstance) inStackInstanceSigil() {}
|
||||
|
||||
// ConfigComponentInstance places a [ComponentInstance] in the context of a
|
||||
// particular [Stack].
|
||||
type ConfigComponentInstance = InStackConfig[ComponentInstance]
|
||||
|
||||
// AbsComponentInstance places a [ComponentInstance] in the context of a
|
||||
// particular [StackInstance].
|
||||
type AbsComponentInstance = InStackInstance[ComponentInstance]
|
||||
@ -0,0 +1,4 @@
|
||||
// Package stackaddrs builds on the top-level "addrs" package to provide the
|
||||
// addresses for the extra layer of concepts that the stacks configuration
|
||||
// language and its runtime are concerned about.
|
||||
package stackaddrs
|
||||
@ -0,0 +1,42 @@
|
||||
package stackaddrs
|
||||
|
||||
// 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 {
|
||||
inStackConfigSigil()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
inStackInstanceSigil()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
Stack Stack
|
||||
Item T
|
||||
}
|
||||
|
||||
func Config[T StackItemConfig](stackAddr Stack, relAddr T) InStackConfig[T] {
|
||||
return InStackConfig[T]{
|
||||
Stack: stackAddr,
|
||||
Item: relAddr,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
Stack StackInstance
|
||||
Item T
|
||||
}
|
||||
|
||||
func Absolute[T StackItemDynamic](stackAddr StackInstance, relAddr T) InStackInstance[T] {
|
||||
return InStackInstance[T]{
|
||||
Stack: stackAddr,
|
||||
Item: relAddr,
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package stackaddrs
|
||||
|
||||
type InputVariable struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (InputVariable) referenceableSigil() {}
|
||||
func (InputVariable) inStackConfigSigil() {}
|
||||
func (InputVariable) inStackInstanceSigil() {}
|
||||
|
||||
// ConfigInputVariable places an [InputVariable] in the context of a particular [Stack].
|
||||
type ConfigInputVariable = InStackConfig[InputVariable]
|
||||
|
||||
// AbsInputVariable places an [InputVariable] in the context of a particular [StackInstance].
|
||||
type AbsInputVariable = InStackInstance[InputVariable]
|
||||
@ -0,0 +1,15 @@
|
||||
package stackaddrs
|
||||
|
||||
type LocalValue struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (LocalValue) referenceableSigil() {}
|
||||
func (LocalValue) inStackConfigSigil() {}
|
||||
func (LocalValue) inStackInstanceSigil() {}
|
||||
|
||||
// ConfigLocalValue places a [LocalValue] in the context of a particular [Stack].
|
||||
type ConfigLocalValue = InStackConfig[LocalValue]
|
||||
|
||||
// AbsLocalValue places a [LocalValue] in the context of a particular [StackInstance].
|
||||
type AbsLocalValue = InStackInstance[LocalValue]
|
||||
@ -0,0 +1,14 @@
|
||||
package stackaddrs
|
||||
|
||||
type OutputValue struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (OutputValue) inStackConfigSigil() {}
|
||||
func (OutputValue) inStackInstanceSigil() {}
|
||||
|
||||
// ConfigOutputValue places an [OutputValue] in the context of a particular [Stack].
|
||||
type ConfigOutputValue = InStackConfig[OutputValue]
|
||||
|
||||
// AbsOutputValue places an [OutputValue] in the context of a particular [StackInstance].
|
||||
type AbsOutputValue = InStackInstance[OutputValue]
|
||||
@ -0,0 +1,51 @@
|
||||
package stackaddrs
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
)
|
||||
|
||||
// ProviderConfigRef is a reference-only address type representing a reference
|
||||
// to a particular provider configuration using its local name, since local
|
||||
// name is how we refer to providers when they appear in expressions.
|
||||
//
|
||||
// The referent of a ProviderConfigRef is a [ProviderConfig], so resolving
|
||||
// the reference will always require a lookup table from local name to
|
||||
// fully-qualified provider address.
|
||||
type ProviderConfigRef struct {
|
||||
ProviderLocalName string
|
||||
Name string
|
||||
}
|
||||
|
||||
func (ProviderConfigRef) referenceableSigil() {}
|
||||
|
||||
// ProviderConfig is the address of a "provider" block in a stack configuration.
|
||||
type ProviderConfig struct {
|
||||
Provider addrs.Provider
|
||||
Name string
|
||||
}
|
||||
|
||||
func (ProviderConfig) inStackConfigSigil() {}
|
||||
func (ProviderConfig) inStackInstanceSigil() {}
|
||||
|
||||
// ConfigProviderConfig places a [ProviderConfig] in the context of a particular [Stack].
|
||||
type ConfigProviderConfig = InStackConfig[ProviderConfig]
|
||||
|
||||
// AbsProviderConfig places a [ProviderConfig] in the context of a particular [StackInstance].
|
||||
type AbsProviderConfig = InStackInstance[ProviderConfig]
|
||||
|
||||
// ProviderConfigInstance is the address of a specific provider configuration,
|
||||
// of which there might potentially be many associated with a given
|
||||
// [ProviderConfig] if that block uses the "for_each" argument.
|
||||
type ProviderConfigInstance struct {
|
||||
ProviderConfig ProviderConfig
|
||||
Key addrs.InstanceKey
|
||||
}
|
||||
|
||||
func (ProviderConfigInstance) inStackConfigSigil() {}
|
||||
func (ProviderConfigInstance) inStackInstanceSigil() {}
|
||||
|
||||
// ConfigProviderConfigInstance places a [ProviderConfigInstance] in the context of a particular [Stack].
|
||||
type ConfigProviderConfigInstance = InStackConfig[ProviderConfigInstance]
|
||||
|
||||
// AbsProviderConfigInstance places a [ProviderConfigInstance] in the context of a particular [StackInstance].
|
||||
type AbsProviderConfigInstance = InStackInstance[ProviderConfigInstance]
|
||||
@ -0,0 +1,13 @@
|
||||
package stackaddrs
|
||||
|
||||
// Referenceable is a type set containing all address types that can be
|
||||
// the target of an expression-based reference within a particular stack.
|
||||
type Referenceable interface {
|
||||
referenceableSigil()
|
||||
}
|
||||
|
||||
var _ Referenceable = Component{}
|
||||
var _ Referenceable = StackCall{}
|
||||
var _ Referenceable = InputVariable{}
|
||||
var _ Referenceable = LocalValue{}
|
||||
var _ Referenceable = ProviderConfigRef{}
|
||||
@ -0,0 +1,97 @@
|
||||
package stackaddrs
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
)
|
||||
|
||||
// Stack represents the address of a stack within the tree of stacks.
|
||||
//
|
||||
// The root stack [RootStack] represents the top-level stack and then any
|
||||
// other value of this type represents an embedded stack descending from it.
|
||||
type Stack []StackStep
|
||||
|
||||
type StackStep struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
var RootStack Stack
|
||||
|
||||
// IsRoot returns true if this object represents the root stack, or false
|
||||
// otherwise.
|
||||
func (s Stack) IsRoot() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
// Parent returns the parent of the reciever, or panics if the receiver is
|
||||
// representing the root stack.
|
||||
func (s Stack) Parent() Stack {
|
||||
newLen := len(s) - 1
|
||||
if newLen < 0 {
|
||||
panic("root stack has no parent")
|
||||
}
|
||||
return s[:newLen:newLen]
|
||||
}
|
||||
|
||||
// Child constructs the address of an embedded stack that's a child of the
|
||||
// receiver.
|
||||
func (s Stack) Child(name string) Stack {
|
||||
ret := make([]StackStep, len(s), len(s)+1)
|
||||
copy(ret, s)
|
||||
return append(ret, StackStep{name})
|
||||
}
|
||||
|
||||
// StackInstance represents the address of an instance of a stack within
|
||||
// the tree of stacks.
|
||||
//
|
||||
// [RootStackInstance] represents the singleton instance of the top-level stack
|
||||
// and then any other value of this type represents an instance of an embedded
|
||||
// stack descending from it.
|
||||
type StackInstance []StackInstanceStep
|
||||
|
||||
type StackInstanceStep struct {
|
||||
Name string
|
||||
Key addrs.InstanceKey
|
||||
}
|
||||
|
||||
var RootStackInstance StackInstance
|
||||
|
||||
// IsRoot returns true if this object represents the singleton instance of the
|
||||
// root stack, or false otherwise.
|
||||
func (s StackInstance) IsRoot() bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
// Parent returns the parent of the reciever, or panics if the receiver is
|
||||
// representing the root stack.
|
||||
func (s StackInstance) Parent() StackInstance {
|
||||
newLen := len(s) - 1
|
||||
if newLen < 0 {
|
||||
panic("root stack has no parent")
|
||||
}
|
||||
return s[:newLen:newLen]
|
||||
}
|
||||
|
||||
// Child constructs the address of an embedded stack that's a child of the
|
||||
// receiver.
|
||||
func (s StackInstance) Child(name string, key addrs.InstanceKey) StackInstance {
|
||||
ret := make([]StackInstanceStep, len(s), len(s)+1)
|
||||
copy(ret, s)
|
||||
return append(ret, StackInstanceStep{
|
||||
Name: name,
|
||||
Key: key,
|
||||
})
|
||||
}
|
||||
|
||||
// Call returns the address of the embedded stack call that the receiever
|
||||
// belongs to, or panics if the receiver is the root module since the root
|
||||
// module is called only implicitly.
|
||||
func (s StackInstance) Call() AbsStackCall {
|
||||
last := s[len(s)-1]
|
||||
si := s[: len(s)-1 : len(s)-1]
|
||||
return AbsStackCall{
|
||||
Stack: si,
|
||||
Item: StackCall{
|
||||
Name: last.Name,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package stackaddrs
|
||||
|
||||
import "github.com/hashicorp/terraform/internal/addrs"
|
||||
|
||||
// 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
|
||||
// expanded into zero or more instances.
|
||||
type StackCall struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (StackCall) referenceableSigil() {}
|
||||
func (StackCall) inStackConfigSigil() {}
|
||||
func (StackCall) inStackInstanceSigil() {}
|
||||
|
||||
// ConfigStackCall represents a static stack call inside a particular [Stack].
|
||||
type ConfigStackCall = InStackConfig[StackCall]
|
||||
|
||||
// AbsStackCall represents an instance of a stack call inside a particular
|
||||
// [StackInstance[.
|
||||
type AbsStackCall = InStackInstance[StackCall]
|
||||
|
||||
func AbsStackCallInstance(call AbsStackCall, key addrs.InstanceKey) StackInstance {
|
||||
ret := make(StackInstance, len(call.Stack), len(call.Stack)+1)
|
||||
copy(ret, call.Stack)
|
||||
return append(ret, StackInstanceStep{
|
||||
Name: call.Item.Name,
|
||||
Key: key,
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package stackaddrs
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
)
|
||||
|
||||
// Targetable is the stacks analog to [addrs.Targetable], representing something
|
||||
// that can be "targeted" inside a stack configuration.
|
||||
type Targetable interface {
|
||||
targetableSigil()
|
||||
}
|
||||
|
||||
// ComponentTargetable is an adapter type that makes everything that's
|
||||
// targetable in the main Terraform language also targetable through a
|
||||
// component instance when in a stack configuration.
|
||||
//
|
||||
// To represent targeting an entire component, place [addrs.RootModuleInstance]
|
||||
// in field Item to describe targeting the component's root module.
|
||||
type ComponentTargetable[T addrs.Targetable] struct {
|
||||
Component AbsComponentInstance
|
||||
Item T
|
||||
}
|
||||
|
||||
func (ComponentTargetable[T]) targetableSigil() {}
|
||||
Loading…
Reference in new issue