add a way to force depends_on behavior of data

Resources that are not yet created will not be in the graph during
refresh, and therefore cannot be attached to the data source nodes. In
this case we still need to indicate if there are depends_on entries
inherited from the module call, which we can do with the forceDependsOn
field.
This commit is contained in:
James Bardin 2020-06-04 12:39:36 -04:00
parent e74ebe1787
commit 4637be4377
4 changed files with 21 additions and 6 deletions

View File

@ -58,6 +58,9 @@ type evalReadData struct {
// determine if there are any changes that will force this data sources to // determine if there are any changes that will force this data sources to
// be deferred to apply. // be deferred to apply.
dependsOn []addrs.ConfigResource dependsOn []addrs.ConfigResource
// forceDependsOn indicates that resources may be missing from dependsOn,
// but the parent module may have depends_on configured.
forceDependsOn bool
} }
// readDataSource handles everything needed to call ReadDataSource on the provider. // readDataSource handles everything needed to call ReadDataSource on the provider.
@ -302,5 +305,5 @@ func (n *evalReadDataRefresh) Eval(ctx EvalContext) (interface{}, error) {
// immediately reading from the data source where possible, instead forcing us // immediately reading from the data source where possible, instead forcing us
// to generate a plan. // to generate a plan.
func (n *evalReadDataRefresh) forcePlanRead() bool { func (n *evalReadDataRefresh) forcePlanRead() bool {
return len(n.Config.DependsOn) > 0 || len(n.dependsOn) > 0 return len(n.Config.DependsOn) > 0 || len(n.dependsOn) > 0 || n.forceDependsOn
} }

View File

@ -122,6 +122,7 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
a.ResolvedProvider = n.ResolvedProvider a.ResolvedProvider = n.ResolvedProvider
a.ProviderMetas = n.ProviderMetas a.ProviderMetas = n.ProviderMetas
a.dependsOn = n.dependsOn a.dependsOn = n.dependsOn
a.forceDependsOn = n.forceDependsOn
return &NodeRefreshableDataResourceInstance{ return &NodeRefreshableDataResourceInstance{
NodeAbstractResourceInstance: a, NodeAbstractResourceInstance: a,
@ -229,6 +230,7 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
OutputChange: &change, OutputChange: &change,
State: &state, State: &state,
dependsOn: n.dependsOn, dependsOn: n.dependsOn,
forceDependsOn: n.forceDependsOn,
}, },
}, },

View File

@ -61,8 +61,9 @@ type NodeAbstractResource struct {
// Set from GraphNodeTargetable // Set from GraphNodeTargetable
Targets []addrs.Targetable Targets []addrs.Targetable
// Set from GraphNodeDependsOn // Set from AttachResourceDependencies
dependsOn []addrs.ConfigResource dependsOn []addrs.ConfigResource
forceDependsOn bool
// The address of the provider this resource will use // The address of the provider this resource will use
ResolvedProvider addrs.AbsProviderConfig ResolvedProvider addrs.AbsProviderConfig
@ -402,8 +403,9 @@ func (n *NodeAbstractResource) SetTargets(targets []addrs.Targetable) {
} }
// graphNodeAttachResourceDependencies // graphNodeAttachResourceDependencies
func (n *NodeAbstractResource) AttachResourceDependencies(deps []addrs.ConfigResource) { func (n *NodeAbstractResource) AttachResourceDependencies(deps []addrs.ConfigResource, force bool) {
n.dependsOn = deps n.dependsOn = deps
n.forceDependsOn = force
} }
// GraphNodeAttachResourceState // GraphNodeAttachResourceState

View File

@ -62,7 +62,15 @@ type graphNodeDependsOn interface {
type graphNodeAttachResourceDependencies interface { type graphNodeAttachResourceDependencies interface {
GraphNodeConfigResource GraphNodeConfigResource
graphNodeDependsOn graphNodeDependsOn
AttachResourceDependencies([]addrs.ConfigResource)
// AttachResourceDependencies stored the discovered dependencies in the
// resource node for evaluation later.
//
// The force parameter indicates that even if there are no dependencies,
// force the data source to act as though there are for refresh purposes.
// This is needed because yet-to-be-created resources won't be in the
// initial refresh graph, but may still be referenced through depends_on.
AttachResourceDependencies(deps []addrs.ConfigResource, force bool)
} }
// GraphNodeReferenceOutside is an interface that can optionally be implemented. // GraphNodeReferenceOutside is an interface that can optionally be implemented.
@ -186,7 +194,7 @@ func (t attachDataResourceDependenciesTransformer) Transform(g *Graph) error {
} }
log.Printf("[TRACE] attachDataDependenciesTransformer: %s depends on %s", depender.ResourceAddr(), res) log.Printf("[TRACE] attachDataDependenciesTransformer: %s depends on %s", depender.ResourceAddr(), res)
depender.AttachResourceDependencies(res) depender.AttachResourceDependencies(res, false)
} }
return nil return nil