From 4637be437786670dc5cd2a7649043530c0c27857 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 4 Jun 2020 12:39:36 -0400 Subject: [PATCH] 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. --- terraform/eval_read_data.go | 5 ++++- terraform/node_data_refresh.go | 2 ++ terraform/node_resource_abstract.go | 8 +++++--- terraform/transform_reference.go | 12 ++++++++++-- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/terraform/eval_read_data.go b/terraform/eval_read_data.go index 4630841b7..9235130bd 100644 --- a/terraform/eval_read_data.go +++ b/terraform/eval_read_data.go @@ -58,6 +58,9 @@ type evalReadData struct { // determine if there are any changes that will force this data sources to // be deferred to apply. 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. @@ -302,5 +305,5 @@ func (n *evalReadDataRefresh) Eval(ctx EvalContext) (interface{}, error) { // immediately reading from the data source where possible, instead forcing us // to generate a plan. 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 } diff --git a/terraform/node_data_refresh.go b/terraform/node_data_refresh.go index 0c191d272..135bcb2a2 100644 --- a/terraform/node_data_refresh.go +++ b/terraform/node_data_refresh.go @@ -122,6 +122,7 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er a.ResolvedProvider = n.ResolvedProvider a.ProviderMetas = n.ProviderMetas a.dependsOn = n.dependsOn + a.forceDependsOn = n.forceDependsOn return &NodeRefreshableDataResourceInstance{ NodeAbstractResourceInstance: a, @@ -229,6 +230,7 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode { OutputChange: &change, State: &state, dependsOn: n.dependsOn, + forceDependsOn: n.forceDependsOn, }, }, diff --git a/terraform/node_resource_abstract.go b/terraform/node_resource_abstract.go index 11eca0d96..aada8d09c 100644 --- a/terraform/node_resource_abstract.go +++ b/terraform/node_resource_abstract.go @@ -61,8 +61,9 @@ type NodeAbstractResource struct { // Set from GraphNodeTargetable Targets []addrs.Targetable - // Set from GraphNodeDependsOn - dependsOn []addrs.ConfigResource + // Set from AttachResourceDependencies + dependsOn []addrs.ConfigResource + forceDependsOn bool // The address of the provider this resource will use ResolvedProvider addrs.AbsProviderConfig @@ -402,8 +403,9 @@ func (n *NodeAbstractResource) SetTargets(targets []addrs.Targetable) { } // graphNodeAttachResourceDependencies -func (n *NodeAbstractResource) AttachResourceDependencies(deps []addrs.ConfigResource) { +func (n *NodeAbstractResource) AttachResourceDependencies(deps []addrs.ConfigResource, force bool) { n.dependsOn = deps + n.forceDependsOn = force } // GraphNodeAttachResourceState diff --git a/terraform/transform_reference.go b/terraform/transform_reference.go index ba5fc2b51..34f214319 100644 --- a/terraform/transform_reference.go +++ b/terraform/transform_reference.go @@ -62,7 +62,15 @@ type graphNodeDependsOn interface { type graphNodeAttachResourceDependencies interface { GraphNodeConfigResource 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. @@ -186,7 +194,7 @@ func (t attachDataResourceDependenciesTransformer) Transform(g *Graph) error { } log.Printf("[TRACE] attachDataDependenciesTransformer: %s depends on %s", depender.ResourceAddr(), res) - depender.AttachResourceDependencies(res) + depender.AttachResourceDependencies(res, false) } return nil