github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/configs/provisioner.go (about) 1 package configs 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/hcl/v2" 7 ) 8 9 // Provisioner represents a "provisioner" block when used within a 10 // "resource" block in a module or file. 11 type Provisioner struct { 12 Type string 13 Config hcl.Body 14 Connection *Connection 15 When ProvisionerWhen 16 OnFailure ProvisionerOnFailure 17 18 DeclRange hcl.Range 19 TypeRange hcl.Range 20 } 21 22 func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) { 23 pv := &Provisioner{ 24 Type: block.Labels[0], 25 TypeRange: block.LabelRanges[0], 26 DeclRange: block.DefRange, 27 When: ProvisionerWhenCreate, 28 OnFailure: ProvisionerOnFailureFail, 29 } 30 31 content, config, diags := block.Body.PartialContent(provisionerBlockSchema) 32 pv.Config = config 33 34 if attr, exists := content.Attributes["when"]; exists { 35 expr, shimDiags := shimTraversalInString(attr.Expr, true) 36 diags = append(diags, shimDiags...) 37 38 switch hcl.ExprAsKeyword(expr) { 39 case "create": 40 pv.When = ProvisionerWhenCreate 41 case "destroy": 42 pv.When = ProvisionerWhenDestroy 43 default: 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(), 49 }) 50 } 51 } 52 53 if attr, exists := content.Attributes["on_failure"]; exists { 54 expr, shimDiags := shimTraversalInString(attr.Expr, true) 55 diags = append(diags, shimDiags...) 56 57 switch hcl.ExprAsKeyword(expr) { 58 case "continue": 59 pv.OnFailure = ProvisionerOnFailureContinue 60 case "fail": 61 pv.OnFailure = ProvisionerOnFailureFail 62 default: 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(), 68 }) 69 } 70 } 71 72 var seenConnection *hcl.Block 73 for _, block := range content.Blocks { 74 switch block.Type { 75 76 case "connection": 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, 83 }) 84 continue 85 } 86 seenConnection = block 87 88 //conn, connDiags := decodeConnectionBlock(block) 89 //diags = append(diags, connDiags...) 90 pv.Connection = &Connection{ 91 Config: block.Body, 92 DeclRange: block.DefRange, 93 } 94 95 default: 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, 103 }) 104 } 105 } 106 107 return pv, diags 108 } 109 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 { 113 Config hcl.Body 114 115 DeclRange hcl.Range 116 } 117 118 // ProvisionerWhen is an enum for valid values for when to run provisioners. 119 type ProvisionerWhen int 120 121 //go:generate go run golang.org/x/tools/cmd/stringer -type ProvisionerWhen 122 123 const ( 124 ProvisionerWhenInvalid ProvisionerWhen = iota 125 ProvisionerWhenCreate 126 ProvisionerWhenDestroy 127 ) 128 129 // ProvisionerOnFailure is an enum for valid values for on_failure options 130 // for provisioners. 131 type ProvisionerOnFailure int 132 133 //go:generate go run golang.org/x/tools/cmd/stringer -type ProvisionerOnFailure 134 135 const ( 136 ProvisionerOnFailureInvalid ProvisionerOnFailure = iota 137 ProvisionerOnFailureContinue 138 ProvisionerOnFailureFail 139 ) 140 141 var provisionerBlockSchema = &hcl.BodySchema{ 142 Attributes: []hcl.AttributeSchema{ 143 {Name: "when"}, 144 {Name: "on_failure"}, 145 }, 146 Blocks: []hcl.BlockHeaderSchema{ 147 {Type: "connection"}, 148 {Type: "lifecycle"}, // reserved for future use 149 }, 150 }