lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
package globalref
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2022-02-04 18:58:07 +01:00
|
|
|
"github.com/hashicorp/hcl/v2"
|
lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
"github.com/hashicorp/terraform/internal/addrs"
|
2022-02-04 18:58:07 +01:00
|
|
|
"github.com/hashicorp/terraform/internal/tfdiags"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// Reference combines an addrs.Reference with the address of the module
|
|
|
|
// instance or resource instance where it was found.
|
|
|
|
//
|
|
|
|
// Because of the design of the Terraform language, our main model of
|
|
|
|
// references only captures the module-local part of the reference and assumes
|
|
|
|
// that it's always clear from context which module a reference belongs to.
|
|
|
|
// That's not true for globalref because our whole purpose is to work across
|
|
|
|
// module boundaries, and so this package in particular has its own
|
|
|
|
// representation of references.
|
|
|
|
type Reference struct {
|
|
|
|
// ContainerAddr is always either addrs.ModuleInstance or
|
|
|
|
// addrs.AbsResourceInstance. The latter is required if LocalRef's
|
|
|
|
// subject is either an addrs.CountAddr or addrs.ForEachAddr, so
|
|
|
|
// we can know which resource's repetition expression it's
|
|
|
|
// referring to.
|
|
|
|
ContainerAddr addrs.Targetable
|
|
|
|
|
|
|
|
// LocalRef is a reference that would be resolved in the context
|
|
|
|
// of the module instance or resource instance given in ContainerAddr.
|
|
|
|
LocalRef *addrs.Reference
|
|
|
|
}
|
|
|
|
|
|
|
|
func absoluteRef(containerAddr addrs.Targetable, localRef *addrs.Reference) Reference {
|
|
|
|
ret := Reference{
|
|
|
|
ContainerAddr: containerAddr,
|
|
|
|
LocalRef: localRef,
|
|
|
|
}
|
|
|
|
// For simplicity's sake, we always reduce the ContainerAddr to be
|
|
|
|
// just the module address unless it's a count.index, each.key, or
|
|
|
|
// each.value reference, because for anything else it's immaterial
|
|
|
|
// which resource it belongs to.
|
|
|
|
switch localRef.Subject.(type) {
|
|
|
|
case addrs.CountAttr, addrs.ForEachAttr:
|
|
|
|
// nothing to do
|
|
|
|
default:
|
|
|
|
ret.ContainerAddr = ret.ModuleAddr()
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
func absoluteRefs(containerAddr addrs.Targetable, refs []*addrs.Reference) []Reference {
|
|
|
|
if len(refs) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ret := make([]Reference, len(refs))
|
|
|
|
for i, ref := range refs {
|
|
|
|
ret[i] = absoluteRef(containerAddr, ref)
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// ModuleAddr returns the address of the module where the reference would
|
|
|
|
// be resolved.
|
|
|
|
//
|
|
|
|
// This is either ContainerAddr directly if it's already just a module
|
|
|
|
// instance, or the module instance part of it if it's a resource instance.
|
|
|
|
func (r Reference) ModuleAddr() addrs.ModuleInstance {
|
|
|
|
switch addr := r.ContainerAddr.(type) {
|
|
|
|
case addrs.ModuleInstance:
|
|
|
|
return addr
|
|
|
|
case addrs.AbsResourceInstance:
|
|
|
|
return addr.Module
|
|
|
|
default:
|
|
|
|
// NOTE: We're intentionally using only a subset of possible
|
|
|
|
// addrs.Targetable implementations here, so anything else
|
|
|
|
// is invalid.
|
|
|
|
panic(fmt.Sprintf("reference has invalid container address type %T", addr))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 15:39:14 +01:00
|
|
|
// ResourceInstance returns the address of the resource where the reference
|
lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
// would be resolved, if there is one.
|
|
|
|
//
|
|
|
|
// Because not all references belong to resources, the extra boolean return
|
|
|
|
// value indicates whether the returned address is valid.
|
2022-02-07 15:39:14 +01:00
|
|
|
func (r Reference) ResourceInstance() (addrs.AbsResourceInstance, bool) {
|
2022-02-04 18:39:08 +01:00
|
|
|
switch container := r.ContainerAddr.(type) {
|
lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
case addrs.ModuleInstance:
|
2022-02-07 15:39:14 +01:00
|
|
|
moduleInstance := container
|
2022-02-04 18:39:08 +01:00
|
|
|
|
|
|
|
switch ref := r.LocalRef.Subject.(type) {
|
|
|
|
case addrs.Resource:
|
2022-02-07 15:39:14 +01:00
|
|
|
return ref.Instance(addrs.NoKey).Absolute(moduleInstance), true
|
2022-02-04 18:39:08 +01:00
|
|
|
case addrs.ResourceInstance:
|
2022-02-07 15:39:14 +01:00
|
|
|
return ref.Absolute(moduleInstance), true
|
2022-02-04 18:39:08 +01:00
|
|
|
}
|
|
|
|
|
2022-02-07 15:39:14 +01:00
|
|
|
return addrs.AbsResourceInstance{}, false
|
2022-02-04 18:39:08 +01:00
|
|
|
|
lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
case addrs.AbsResourceInstance:
|
2022-02-07 15:39:14 +01:00
|
|
|
return container, true
|
lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
default:
|
|
|
|
// NOTE: We're intentionally using only a subset of possible
|
|
|
|
// addrs.Targetable implementations here, so anything else
|
|
|
|
// is invalid.
|
2022-02-04 18:39:08 +01:00
|
|
|
panic(fmt.Sprintf("reference has invalid container address type %T", container))
|
lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// DebugString returns an internal (but still somewhat Terraform-language-like)
|
|
|
|
// compact string representation of the reciever, which isn't an address that
|
|
|
|
// any of our usual address parsers could accept but still captures the
|
|
|
|
// essence of what the reference represents.
|
|
|
|
//
|
|
|
|
// The DebugString result is not suitable for end-user-oriented messages.
|
|
|
|
//
|
|
|
|
// DebugString is also not suitable for use as a unique key for a reference,
|
|
|
|
// because it's ambiguous (between a no-key resource instance and a resource)
|
|
|
|
// and because it discards the source location information in the LocalRef.
|
|
|
|
func (r Reference) DebugString() string {
|
|
|
|
// As the doc comment insinuates, we don't have any real syntax for
|
|
|
|
// "absolute references": references are always local, and targets are
|
|
|
|
// always absolute but only include modules and resources.
|
|
|
|
return r.ContainerAddr.String() + "::" + r.LocalRef.DisplayString()
|
|
|
|
}
|
|
|
|
|
2022-02-04 18:58:07 +01:00
|
|
|
// ResourceAttr converts the Reference value to a more specific ResourceAttr
|
|
|
|
// value.
|
|
|
|
//
|
|
|
|
// Because not all references belong to resources, the extra boolean return
|
|
|
|
// value indicates whether the returned address is valid.
|
|
|
|
func (r Reference) ResourceAttr() (ResourceAttr, bool) {
|
2022-02-07 15:39:14 +01:00
|
|
|
res, ok := r.ResourceInstance()
|
2022-02-04 18:58:07 +01:00
|
|
|
if !ok {
|
|
|
|
return ResourceAttr{}, ok
|
|
|
|
}
|
|
|
|
|
|
|
|
traversal := r.LocalRef.Remaining
|
|
|
|
|
|
|
|
path := make(cty.Path, len(traversal))
|
|
|
|
for si, step := range traversal {
|
|
|
|
switch ts := step.(type) {
|
|
|
|
case hcl.TraverseRoot:
|
|
|
|
path[si] = cty.GetAttrStep{
|
|
|
|
Name: ts.Name,
|
|
|
|
}
|
|
|
|
case hcl.TraverseAttr:
|
|
|
|
path[si] = cty.GetAttrStep{
|
|
|
|
Name: ts.Name,
|
|
|
|
}
|
|
|
|
case hcl.TraverseIndex:
|
|
|
|
path[si] = cty.IndexStep{
|
|
|
|
Key: ts.Key,
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("unsupported traversal step %#v", step))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ResourceAttr{
|
|
|
|
Resource: res,
|
|
|
|
Attr: path,
|
|
|
|
}, true
|
|
|
|
}
|
|
|
|
|
lang/globalref: Global reference analysis utilities
Our existing functionality for dealing with references generally only has
to concern itself with one level of references at a time, and only within
one module, because we use it to draw a dependency graph which then ends
up reflecting the broader context.
However, there are some situations where it's handy to be able to ask
questions about the indirect contributions to a particular expression in
the configuration, particularly for additional hints in the user interface
where we're just providing some extra context rather than changing
behavior.
This new "globalref" package therefore aims to be the home for algorithms
for use-cases like this. It introduces its own special "Reference" type
that wraps addrs.Reference to annotate it also with the usually-implied
context about where the references would be evaluated.
With that building block we can therefore ask questions whose answers
might involve discussing references in multiple packages at once, such as
"which resources directly or indirectly contribute to this expression?",
including indirect hops through input variables or output values which
would therefore change the evaluation context.
The current implementations of this are around mapping references onto the
static configuration expressions that they refer to, which is a pretty
broad and conservative approach that unfortunately therefore loses
accuracy when confronted with complex expressions that might take dynamic
actions on the contents of an object. My hunch is that this'll be good
enough to get some initial small use-cases solved, though there's plenty
room for improvement in accuracy.
It's somewhat ironic that this sort of "what is this value built from?"
question is the use-case I had in mind when I designed the "marks" feature
in cty, yet we've ended up putting it to an unexpected but still valid
use in Terraform for sensitivity analysis and our currently handling of
that isn't really tight enough to permit other concurrent uses of marks
for other use-cases. I expect we can address that later and so maybe we'll
try for a more accurate version of these analyses at a later date, but my
hunch is that this'll be good enough for us to still get some good use out
of it in the near future, particular related to helping understand where
unknown values came from and in tailoring our refresh results in plan
output to deemphasize detected changes that couldn't possibly have
contributed to the proposed plan.
2021-06-09 21:11:44 +02:00
|
|
|
// addrKey returns the referenceAddrKey value for the item that
|
|
|
|
// this reference refers to, discarding any source location information.
|
|
|
|
//
|
|
|
|
// See the referenceAddrKey doc comment for more information on what this
|
|
|
|
// is suitable for.
|
|
|
|
func (r Reference) addrKey() referenceAddrKey {
|
|
|
|
// This is a pretty arbitrary bunch of stuff. We include the type here
|
|
|
|
// just to differentiate between no-key resource instances and resources.
|
|
|
|
return referenceAddrKey(fmt.Sprintf("%s(%T)%s", r.ContainerAddr.String(), r.LocalRef.Subject, r.LocalRef.DisplayString()))
|
|
|
|
}
|
|
|
|
|
|
|
|
// referenceAddrKey is a special string type which conventionally contains
|
|
|
|
// a unique string representation of the object that a reference refers to,
|
|
|
|
// although not of the reference itself because it ignores the information
|
|
|
|
// that would differentiate two different references to the same object.
|
|
|
|
//
|
|
|
|
// The actual content of a referenceAddrKey is arbitrary, for internal use
|
|
|
|
// only. and subject to change in future. We use a named type here only to
|
|
|
|
// make it easier to see when we're intentionally using strings to uniquely
|
|
|
|
// identify absolute reference addresses.
|
|
|
|
type referenceAddrKey string
|
2022-02-04 18:58:07 +01:00
|
|
|
|
|
|
|
// ResourceAttr represents a global resource and attribute reference.
|
|
|
|
// This is a more specific form of the Reference type since it can only refer
|
|
|
|
// to a specific AbsResource and one of its attributes.
|
|
|
|
type ResourceAttr struct {
|
2022-02-07 15:39:14 +01:00
|
|
|
Resource addrs.AbsResourceInstance
|
2022-02-04 18:58:07 +01:00
|
|
|
Attr cty.Path
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r ResourceAttr) DebugString() string {
|
|
|
|
return r.Resource.String() + tfdiags.FormatCtyPath(r.Attr)
|
|
|
|
}
|