track contributing instances

Track individual instance drift rather than whole resources which
contributed to the plan. This will allow the output to be more precise,
and we can still use NoKey instances as a proxy for containing resources
when needed.
This commit is contained in:
James Bardin 2022-02-07 09:39:14 -05:00
parent 25f4c0d3dd
commit e2b74247f2
5 changed files with 16 additions and 18 deletions

View File

@ -189,7 +189,7 @@ func TestOperation_planNoChanges(t *testing.T) {
Changes: changes, Changes: changes,
DriftedResources: drs, DriftedResources: drs,
RelevantAttributes: []globalref.ResourceAttr{{ RelevantAttributes: []globalref.ResourceAttr{{
Resource: addr.ContainingResource(), Resource: addr,
Attr: cty.GetAttrPath("id"), Attr: cty.GetAttrPath("id"),
}}, }},
} }

View File

@ -459,7 +459,7 @@ func filterRefreshChange(change *plans.ResourceInstanceChange, contributing []gl
} }
var relevantAttrs []cty.Path var relevantAttrs []cty.Path
resAddr := change.Addr.ContainingResource() resAddr := change.Addr
for _, attr := range contributing { for _, attr := range contributing {
if resAddr.Equal(attr.Resource) { if resAddr.Equal(attr.Resource) {

View File

@ -56,8 +56,8 @@ func (a *Analyzer) MetaReferences(ref Reference) []Reference {
// this latter to distingish these two cases better. // this latter to distingish these two cases better.
return a.metaReferencesModuleCall(moduleAddr, targetAddr.Instance(addrs.NoKey), remaining) return a.metaReferencesModuleCall(moduleAddr, targetAddr.Instance(addrs.NoKey), remaining)
case addrs.CountAttr, addrs.ForEachAttr: case addrs.CountAttr, addrs.ForEachAttr:
if resourceAddr, ok := ref.ResourceAddr(); ok { if resourceAddr, ok := ref.ResourceInstance(); ok {
return a.metaReferencesCountOrEach(resourceAddr) return a.metaReferencesCountOrEach(resourceAddr.ContainingResource())
} }
return nil return nil
case addrs.ResourceInstance: case addrs.ResourceInstance:

View File

@ -80,29 +80,27 @@ func (r Reference) ModuleAddr() addrs.ModuleInstance {
} }
} }
// ResourceAddr returns the address of the resource where the reference // ResourceInstance returns the address of the resource where the reference
// would be resolved, if there is one. // would be resolved, if there is one.
// //
// Because not all references belong to resources, the extra boolean return // Because not all references belong to resources, the extra boolean return
// value indicates whether the returned address is valid. // value indicates whether the returned address is valid.
func (r Reference) ResourceAddr() (addrs.AbsResource, bool) { func (r Reference) ResourceInstance() (addrs.AbsResourceInstance, bool) {
moduleInstance := addrs.RootModuleInstance
switch container := r.ContainerAddr.(type) { switch container := r.ContainerAddr.(type) {
case addrs.ModuleInstance: case addrs.ModuleInstance:
moduleInstance = container moduleInstance := container
switch ref := r.LocalRef.Subject.(type) { switch ref := r.LocalRef.Subject.(type) {
case addrs.Resource: case addrs.Resource:
return ref.Absolute(moduleInstance), true return ref.Instance(addrs.NoKey).Absolute(moduleInstance), true
case addrs.ResourceInstance: case addrs.ResourceInstance:
return ref.ContainingResource().Absolute(moduleInstance), true return ref.Absolute(moduleInstance), true
} }
return addrs.AbsResource{}, false return addrs.AbsResourceInstance{}, false
case addrs.AbsResourceInstance: case addrs.AbsResourceInstance:
return container.ContainingResource(), true return container, true
default: default:
// NOTE: We're intentionally using only a subset of possible // NOTE: We're intentionally using only a subset of possible
// addrs.Targetable implementations here, so anything else // addrs.Targetable implementations here, so anything else
@ -134,7 +132,7 @@ func (r Reference) DebugString() string {
// Because not all references belong to resources, the extra boolean return // Because not all references belong to resources, the extra boolean return
// value indicates whether the returned address is valid. // value indicates whether the returned address is valid.
func (r Reference) ResourceAttr() (ResourceAttr, bool) { func (r Reference) ResourceAttr() (ResourceAttr, bool) {
res, ok := r.ResourceAddr() res, ok := r.ResourceInstance()
if !ok { if !ok {
return ResourceAttr{}, ok return ResourceAttr{}, ok
} }
@ -193,7 +191,7 @@ type referenceAddrKey string
// This is a more specific form of the Reference type since it can only refer // This is a more specific form of the Reference type since it can only refer
// to a specific AbsResource and one of its attributes. // to a specific AbsResource and one of its attributes.
type ResourceAttr struct { type ResourceAttr struct {
Resource addrs.AbsResource Resource addrs.AbsResourceInstance
Attr cty.Path Attr cty.Path
} }

View File

@ -37,9 +37,9 @@ type Plan struct {
ForceReplaceAddrs []addrs.AbsResourceInstance ForceReplaceAddrs []addrs.AbsResourceInstance
Backend Backend Backend Backend
// RelevantAttributes is a set of resource addresses and attributes that are // RelevantAttributes is a set of resource instance addresses and
// either directly affected by proposed changes or may have indirectly // attributes that are either directly affected by proposed changes or may
// contributed to them via references in expressions. // have indirectly contributed to them via references in expressions.
// //
// This is the result of a heuristic and is intended only as a hint to // This is the result of a heuristic and is intended only as a hint to
// the UI layer in case it wants to emphasize or de-emphasize certain // the UI layer in case it wants to emphasize or de-emphasize certain