From 4a9cafcd67e62355325341724740b5e0f0e79c49 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 25 Jan 2017 12:39:08 -0800 Subject: [PATCH] terraform: expand count on resources during validation --- terraform/graph_builder_validate.go | 4 +- terraform/node_resource_validate.go | 66 ++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/terraform/graph_builder_validate.go b/terraform/graph_builder_validate.go index 1881f95f2..645ec7be9 100644 --- a/terraform/graph_builder_validate.go +++ b/terraform/graph_builder_validate.go @@ -23,7 +23,9 @@ func ValidateGraphBuilder(p *PlanGraphBuilder) GraphBuilder { p.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex { return &NodeValidatableResource{ - NodeAbstractResource: a, + NodeAbstractCountResource: &NodeAbstractCountResource{ + NodeAbstractResource: a, + }, } } diff --git a/terraform/node_resource_validate.go b/terraform/node_resource_validate.go index bbdc6f544..8e99075c4 100644 --- a/terraform/node_resource_validate.go +++ b/terraform/node_resource_validate.go @@ -1,13 +1,77 @@ package terraform +import ( + "github.com/hashicorp/terraform/dag" +) + // NodeValidatableResource represents a resource that is used for validation // only. type NodeValidatableResource struct { + *NodeAbstractCountResource +} + +// GraphNodeDynamicExpandable +func (n *NodeValidatableResource) DynamicExpand(ctx EvalContext) (*Graph, error) { + // Grab the state which we read + state, lock := ctx.State() + lock.RLock() + defer lock.RUnlock() + + // Expand the resource count which must be available by now from EvalTree + count, err := n.Config.Count() + if err != nil { + return nil, err + } + + // The concrete resource factory we'll use + concreteResource := func(a *NodeAbstractResource) dag.Vertex { + // Add the config and state since we don't do that via transforms + a.Config = n.Config + + return &NodeValidatableResourceInstance{ + NodeAbstractResource: a, + } + } + + // Start creating the steps + steps := []GraphTransformer{ + // Expand the count. + &ResourceCountTransformer{ + Concrete: concreteResource, + Count: count, + Addr: n.ResourceAddr(), + }, + + // Attach the state + &AttachStateTransformer{State: state}, + + // Targeting + &TargetsTransformer{ParsedTargets: n.Targets}, + + // Connect references so ordering is correct + &ReferenceTransformer{}, + + // Make sure there is a single root + &RootTransformer{}, + } + + // Build the graph + b := &BasicGraphBuilder{ + Steps: steps, + Validate: true, + Name: "NodeValidatableResource", + } + + return b.Build(ctx.Path()) +} + +// This represents a _single_ resource instance to validate. +type NodeValidatableResourceInstance struct { *NodeAbstractResource } // GraphNodeEvalable -func (n *NodeValidatableResource) EvalTree() EvalNode { +func (n *NodeValidatableResourceInstance) EvalTree() EvalNode { addr := n.NodeAbstractResource.Addr // Build the resource for eval