1package terraform
2
3import (
4	"github.com/hashicorp/terraform-plugin-sdk/internal/configs"
5	"github.com/hashicorp/terraform-plugin-sdk/internal/configs/configschema"
6	"github.com/hashicorp/terraform-plugin-sdk/internal/providers"
7	"github.com/hashicorp/terraform-plugin-sdk/internal/provisioners"
8	"github.com/zclconf/go-cty/cty"
9)
10
11// NodeValidatableResource represents a resource that is used for validation
12// only.
13type NodeValidatableResource struct {
14	*NodeAbstractResource
15}
16
17var (
18	_ GraphNodeSubPath              = (*NodeValidatableResource)(nil)
19	_ GraphNodeEvalable             = (*NodeValidatableResource)(nil)
20	_ GraphNodeReferenceable        = (*NodeValidatableResource)(nil)
21	_ GraphNodeReferencer           = (*NodeValidatableResource)(nil)
22	_ GraphNodeResource             = (*NodeValidatableResource)(nil)
23	_ GraphNodeAttachResourceConfig = (*NodeValidatableResource)(nil)
24)
25
26// GraphNodeEvalable
27func (n *NodeValidatableResource) EvalTree() EvalNode {
28	addr := n.ResourceAddr()
29	config := n.Config
30
31	// Declare the variables will be used are used to pass values along
32	// the evaluation sequence below. These are written to via pointers
33	// passed to the EvalNodes.
34	var provider providers.Interface
35	var providerSchema *ProviderSchema
36	var configVal cty.Value
37
38	seq := &EvalSequence{
39		Nodes: []EvalNode{
40			&EvalGetProvider{
41				Addr:   n.ResolvedProvider,
42				Output: &provider,
43				Schema: &providerSchema,
44			},
45			&EvalValidateResource{
46				Addr:           addr.Resource,
47				Provider:       &provider,
48				ProviderSchema: &providerSchema,
49				Config:         config,
50				ConfigVal:      &configVal,
51			},
52		},
53	}
54
55	if managed := n.Config.Managed; managed != nil {
56		hasCount := n.Config.Count != nil
57		hasForEach := n.Config.ForEach != nil
58
59		// Validate all the provisioners
60		for _, p := range managed.Provisioners {
61			var provisioner provisioners.Interface
62			var provisionerSchema *configschema.Block
63
64			if p.Connection == nil {
65				p.Connection = config.Managed.Connection
66			} else if config.Managed.Connection != nil {
67				p.Connection.Config = configs.MergeBodies(config.Managed.Connection.Config, p.Connection.Config)
68			}
69
70			seq.Nodes = append(
71				seq.Nodes,
72				&EvalGetProvisioner{
73					Name:   p.Type,
74					Output: &provisioner,
75					Schema: &provisionerSchema,
76				},
77				&EvalValidateProvisioner{
78					ResourceAddr:       addr.Resource,
79					Provisioner:        &provisioner,
80					Schema:             &provisionerSchema,
81					Config:             p,
82					ResourceHasCount:   hasCount,
83					ResourceHasForEach: hasForEach,
84				},
85			)
86		}
87	}
88
89	return seq
90}
91