github.com/trawler/terraform@v0.10.8-0.20171106022149-4b1c7a1d9b48/terraform/node_resource_validate.go (about)

     1  package terraform
     2  
     3  import (
     4  	"github.com/hashicorp/terraform/dag"
     5  )
     6  
     7  // NodeValidatableResource represents a resource that is used for validation
     8  // only.
     9  type NodeValidatableResource struct {
    10  	*NodeAbstractCountResource
    11  }
    12  
    13  // GraphNodeEvalable
    14  func (n *NodeValidatableResource) EvalTree() EvalNode {
    15  	// Ensure we're validating
    16  	c := n.NodeAbstractCountResource
    17  	c.Validate = true
    18  	return c.EvalTree()
    19  }
    20  
    21  // GraphNodeDynamicExpandable
    22  func (n *NodeValidatableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
    23  	// Grab the state which we read
    24  	state, lock := ctx.State()
    25  	lock.RLock()
    26  	defer lock.RUnlock()
    27  
    28  	// Expand the resource count which must be available by now from EvalTree
    29  	count := 1
    30  	if n.Config.RawCount.Value() != unknownValue() {
    31  		var err error
    32  		count, err = n.Config.Count()
    33  		if err != nil {
    34  			return nil, err
    35  		}
    36  	}
    37  
    38  	// The concrete resource factory we'll use
    39  	concreteResource := func(a *NodeAbstractResource) dag.Vertex {
    40  		// Add the config and state since we don't do that via transforms
    41  		a.Config = n.Config
    42  		a.ResolvedProvider = n.ResolvedProvider
    43  
    44  		return &NodeValidatableResourceInstance{
    45  			NodeAbstractResource: a,
    46  		}
    47  	}
    48  
    49  	// Start creating the steps
    50  	steps := []GraphTransformer{
    51  		// Expand the count.
    52  		&ResourceCountTransformer{
    53  			Concrete: concreteResource,
    54  			Count:    count,
    55  			Addr:     n.ResourceAddr(),
    56  		},
    57  
    58  		// Attach the state
    59  		&AttachStateTransformer{State: state},
    60  
    61  		// Targeting
    62  		&TargetsTransformer{ParsedTargets: n.Targets},
    63  
    64  		// Connect references so ordering is correct
    65  		&ReferenceTransformer{},
    66  
    67  		// Make sure there is a single root
    68  		&RootTransformer{},
    69  	}
    70  
    71  	// Build the graph
    72  	b := &BasicGraphBuilder{
    73  		Steps:    steps,
    74  		Validate: true,
    75  		Name:     "NodeValidatableResource",
    76  	}
    77  
    78  	return b.Build(ctx.Path())
    79  }
    80  
    81  // This represents a _single_ resource instance to validate.
    82  type NodeValidatableResourceInstance struct {
    83  	*NodeAbstractResource
    84  }
    85  
    86  // GraphNodeEvalable
    87  func (n *NodeValidatableResourceInstance) EvalTree() EvalNode {
    88  	addr := n.NodeAbstractResource.Addr
    89  
    90  	// Build the resource for eval
    91  	resource := &Resource{
    92  		Name:       addr.Name,
    93  		Type:       addr.Type,
    94  		CountIndex: addr.Index,
    95  	}
    96  	if resource.CountIndex < 0 {
    97  		resource.CountIndex = 0
    98  	}
    99  
   100  	// Declare a bunch of variables that are used for state during
   101  	// evaluation. Most of this are written to by-address below.
   102  	var config *ResourceConfig
   103  	var provider ResourceProvider
   104  
   105  	seq := &EvalSequence{
   106  		Nodes: []EvalNode{
   107  			&EvalValidateResourceSelfRef{
   108  				Addr:   &addr,
   109  				Config: &n.Config.RawConfig,
   110  			},
   111  			&EvalGetProvider{
   112  				Name:   n.ResolvedProvider,
   113  				Output: &provider,
   114  			},
   115  			&EvalInterpolate{
   116  				Config:   n.Config.RawConfig.Copy(),
   117  				Resource: resource,
   118  				Output:   &config,
   119  			},
   120  			&EvalValidateResource{
   121  				Provider:     &provider,
   122  				Config:       &config,
   123  				ResourceName: n.Config.Name,
   124  				ResourceType: n.Config.Type,
   125  				ResourceMode: n.Config.Mode,
   126  			},
   127  		},
   128  	}
   129  
   130  	// Validate all the provisioners
   131  	for _, p := range n.Config.Provisioners {
   132  		var provisioner ResourceProvisioner
   133  		var connConfig *ResourceConfig
   134  		seq.Nodes = append(
   135  			seq.Nodes,
   136  			&EvalGetProvisioner{
   137  				Name:   p.Type,
   138  				Output: &provisioner,
   139  			},
   140  			&EvalInterpolate{
   141  				Config:   p.RawConfig.Copy(),
   142  				Resource: resource,
   143  				Output:   &config,
   144  			},
   145  			&EvalInterpolate{
   146  				Config:   p.ConnInfo.Copy(),
   147  				Resource: resource,
   148  				Output:   &connConfig,
   149  			},
   150  			&EvalValidateProvisioner{
   151  				Provisioner: &provisioner,
   152  				Config:      &config,
   153  				ConnConfig:  &connConfig,
   154  			},
   155  		)
   156  	}
   157  
   158  	return seq
   159  }