6 "github.com/hashicorp/hcl2/hcl"
9 // Provisioner represents a "provisioner" block when used within a
10 // "resource" block in a module or file.
11 type Provisioner struct {
14 Connection *Connection
16 OnFailure ProvisionerOnFailure
22 func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) {
24 Type: block.Labels[0],
25 TypeRange: block.LabelRanges[0],
26 DeclRange: block.DefRange,
27 When: ProvisionerWhenCreate,
28 OnFailure: ProvisionerOnFailureFail,
31 content, config, diags := block.Body.PartialContent(provisionerBlockSchema)
34 if attr, exists := content.Attributes["when"]; exists {
35 expr, shimDiags := shimTraversalInString(attr.Expr, true)
36 diags = append(diags, shimDiags...)
38 switch hcl.ExprAsKeyword(expr) {
40 pv.When = ProvisionerWhenCreate
42 pv.When = ProvisionerWhenDestroy
44 diags = append(diags, &hcl.Diagnostic{
45 Severity: hcl.DiagError,
46 Summary: "Invalid \"when\" keyword",
47 Detail: "The \"when\" argument requires one of the following keywords: create or destroy.",
48 Subject: expr.Range().Ptr(),
53 if attr, exists := content.Attributes["on_failure"]; exists {
54 expr, shimDiags := shimTraversalInString(attr.Expr, true)
55 diags = append(diags, shimDiags...)
57 switch hcl.ExprAsKeyword(expr) {
59 pv.OnFailure = ProvisionerOnFailureContinue
61 pv.OnFailure = ProvisionerOnFailureFail
63 diags = append(diags, &hcl.Diagnostic{
64 Severity: hcl.DiagError,
65 Summary: "Invalid \"on_failure\" keyword",
66 Detail: "The \"on_failure\" argument requires one of the following keywords: continue or fail.",
67 Subject: attr.Expr.Range().Ptr(),
72 var seenConnection *hcl.Block
73 for _, block := range content.Blocks {
77 if seenConnection != nil {
78 diags = append(diags, &hcl.Diagnostic{
79 Severity: hcl.DiagError,
80 Summary: "Duplicate connection block",
81 Detail: fmt.Sprintf("This provisioner already has a connection block at %s.", seenConnection.DefRange),
82 Subject: &block.DefRange,
86 seenConnection = block
88 //conn, connDiags := decodeConnectionBlock(block)
89 //diags = append(diags, connDiags...)
90 pv.Connection = &Connection{
92 DeclRange: block.DefRange,
96 // Any other block types are ones we've reserved for future use,
97 // so they get a generic message.
98 diags = append(diags, &hcl.Diagnostic{
99 Severity: hcl.DiagError,
100 Summary: "Reserved block type name in provisioner block",
101 Detail: fmt.Sprintf("The block type name %q is reserved for use by Terraform in a future version.", block.Type),
102 Subject: &block.TypeRange,
110 // Connection represents a "connection" block when used within either a
111 // "resource" or "provisioner" block in a module or file.
112 type Connection struct {
118 // ProvisionerWhen is an enum for valid values for when to run provisioners.
119 type ProvisionerWhen int
121 //go:generate stringer -type ProvisionerWhen
124 ProvisionerWhenInvalid ProvisionerWhen = iota
125 ProvisionerWhenCreate
126 ProvisionerWhenDestroy
129 // ProvisionerOnFailure is an enum for valid values for on_failure options
131 type ProvisionerOnFailure int
133 //go:generate stringer -type ProvisionerOnFailure
136 ProvisionerOnFailureInvalid ProvisionerOnFailure = iota
137 ProvisionerOnFailureContinue
138 ProvisionerOnFailureFail
141 var provisionerBlockSchema = &hcl.BodySchema{
142 Attributes: []hcl.AttributeSchema{
144 {Name: "on_failure"},
146 Blocks: []hcl.BlockHeaderSchema{
147 {Type: "connection"},
148 {Type: "lifecycle"}, // reserved for future use