opentofu/internal/addrs/module_call.go
Martin Atkins 4cbe6cabfc addrs: AbsMoveable, ConfigMoveable, and MoveableEndpoint
These three types represent the three different address representations we
need to represent different stages of analysis for "moved" blocks in the
configuration.

The goal here is to encapsulate all of the static address wrangling inside
these types so that users of these types elsewhere would have to work
pretty hard to use them incorrectly.

In particular, the MovableEndpoint type intentionally fully encapsulates
the weird relative addresses we use in configuration so that code
elsewhere in Terraform can never end up holding an address of a type that
suggests absolute when it's actually relative. That situation only occurs
in the internals of MoveableEndpoint where we use not-really-absolute
AbsMoveable address types to represent the not-yet-resolved relative
addresses.

This only takes care of the static address wrangling. There's lots of
other rules for what makes a "moved" block valid which will need to be
checked elsewhere because they require more context than just the content
of the address itself.
2021-07-01 08:28:02 -07:00

149 lines
3.9 KiB
Go

package addrs
import (
"fmt"
)
// ModuleCall is the address of a call from the current module to a child
// module.
type ModuleCall struct {
referenceable
Name string
}
func (c ModuleCall) String() string {
return "module." + c.Name
}
// Instance returns the address of an instance of the receiver identified by
// the given key.
func (c ModuleCall) Instance(key InstanceKey) ModuleCallInstance {
return ModuleCallInstance{
Call: c,
Key: key,
}
}
func (c ModuleCall) Absolute(moduleAddr ModuleInstance) AbsModuleCall {
return AbsModuleCall{
Module: moduleAddr,
Call: c,
}
}
// AbsModuleCall is the address of a "module" block relative to the root
// of the configuration.
//
// This is similar to ModuleInstance alone, but specifically represents
// the module block itself rather than any one of the instances that
// module block declares.
type AbsModuleCall struct {
Module ModuleInstance
Call ModuleCall
}
func (c AbsModuleCall) absMoveableSigil() {
// AbsModuleCall is "moveable".
}
func (c AbsModuleCall) String() string {
return fmt.Sprintf("%s.%s", c.Module, c.Call.Name)
}
func (c AbsModuleCall) Instance(key InstanceKey) ModuleInstance {
ret := make(ModuleInstance, len(c.Module), len(c.Module)+1)
copy(ret, c.Module)
ret = append(ret, ModuleInstanceStep{
Name: c.Call.Name,
InstanceKey: key,
})
return ret
}
// ModuleCallInstance is the address of one instance of a module created from
// a module call, which might create multiple instances using "count" or
// "for_each" arguments.
//
// There is no "Abs" version of ModuleCallInstance because an absolute module
// path is represented by ModuleInstance.
type ModuleCallInstance struct {
referenceable
Call ModuleCall
Key InstanceKey
}
func (c ModuleCallInstance) String() string {
if c.Key == NoKey {
return c.Call.String()
}
return fmt.Sprintf("module.%s%s", c.Call.Name, c.Key)
}
func (c ModuleCallInstance) Absolute(moduleAddr ModuleInstance) ModuleInstance {
ret := make(ModuleInstance, len(moduleAddr), len(moduleAddr)+1)
copy(ret, moduleAddr)
ret = append(ret, ModuleInstanceStep{
Name: c.Call.Name,
InstanceKey: c.Key,
})
return ret
}
// ModuleInstance returns the address of the module instance that corresponds
// to the receiving call instance when resolved in the given calling module.
// In other words, it returns the child module instance that the receving
// call instance creates.
func (c ModuleCallInstance) ModuleInstance(caller ModuleInstance) ModuleInstance {
return caller.Child(c.Call.Name, c.Key)
}
// Output returns the absolute address of an output of the receiver identified by its
// name.
func (c ModuleCallInstance) Output(name string) ModuleCallInstanceOutput {
return ModuleCallInstanceOutput{
Call: c,
Name: name,
}
}
// ModuleCallOutput is the address of a named output and its associated
// ModuleCall, which may expand into multiple module instances
type ModuleCallOutput struct {
referenceable
Call ModuleCall
Name string
}
func (m ModuleCallOutput) String() string {
return fmt.Sprintf("%s.%s", m.Call.String(), m.Name)
}
// ModuleCallInstanceOutput is the address of a particular named output produced by
// an instance of a module call.
type ModuleCallInstanceOutput struct {
referenceable
Call ModuleCallInstance
Name string
}
// ModuleCallOutput returns the referenceable ModuleCallOutput for this
// particular instance.
func (co ModuleCallInstanceOutput) ModuleCallOutput() ModuleCallOutput {
return ModuleCallOutput{
Call: co.Call.Call,
Name: co.Name,
}
}
func (co ModuleCallInstanceOutput) String() string {
return fmt.Sprintf("%s.%s", co.Call.String(), co.Name)
}
// AbsOutputValue returns the absolute output value address that corresponds
// to the receving module call output address, once resolved in the given
// calling module.
func (co ModuleCallInstanceOutput) AbsOutputValue(caller ModuleInstance) AbsOutputValue {
moduleAddr := co.Call.ModuleInstance(caller)
return moduleAddr.OutputValue(co.Name)
}