mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-03 20:57:09 -06:00
36fb5b52e7
In our new loader we are changing certain values in configuration to be naked keywords or references rather than quoted strings as before. Since many of these have been shown in books, tutorials, and our own documentation we will make the old forms generate deprecation warnings rather than errors so that newcomers starting from older documentation can be eased into the new syntax, rather than getting blocked. This will also avoid creating a hard compatibility wall for reusable modules that are already published, allowing them to still be used in spite of these warnings and then fixed when the maintainer is able.
174 lines
4.1 KiB
Go
174 lines
4.1 KiB
Go
package configs
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/hcl2/gohcl"
|
|
"github.com/hashicorp/hcl2/hcl"
|
|
)
|
|
|
|
// Provisioner represents a "provisioner" block when used within a
|
|
// "resource" block in a module or file.
|
|
type Provisioner struct {
|
|
Type string
|
|
Config hcl.Body
|
|
Connection *Connection
|
|
When ProvisionerWhen
|
|
OnFailure ProvisionerOnFailure
|
|
|
|
DeclRange hcl.Range
|
|
TypeRange hcl.Range
|
|
}
|
|
|
|
func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) {
|
|
pv := &Provisioner{
|
|
Type: block.Labels[0],
|
|
TypeRange: block.LabelRanges[0],
|
|
DeclRange: block.DefRange,
|
|
When: ProvisionerWhenCreate,
|
|
OnFailure: ProvisionerOnFailureFail,
|
|
}
|
|
|
|
content, config, diags := block.Body.PartialContent(provisionerBlockSchema)
|
|
pv.Config = config
|
|
|
|
if attr, exists := content.Attributes["when"]; exists {
|
|
expr, shimDiags := shimTraversalInString(attr.Expr, true)
|
|
diags = append(diags, shimDiags...)
|
|
|
|
switch hcl.ExprAsKeyword(expr) {
|
|
case "create":
|
|
pv.When = ProvisionerWhenCreate
|
|
case "destroy":
|
|
pv.When = ProvisionerWhenDestroy
|
|
default:
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid \"when\" keyword",
|
|
Detail: "The \"when\" argument requires one of the following keywords: create or destroy.",
|
|
Subject: expr.Range().Ptr(),
|
|
})
|
|
}
|
|
}
|
|
|
|
if attr, exists := content.Attributes["on_failure"]; exists {
|
|
expr, shimDiags := shimTraversalInString(attr.Expr, true)
|
|
diags = append(diags, shimDiags...)
|
|
|
|
switch hcl.ExprAsKeyword(expr) {
|
|
case "continue":
|
|
pv.OnFailure = ProvisionerOnFailureContinue
|
|
case "fail":
|
|
pv.OnFailure = ProvisionerOnFailureFail
|
|
default:
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid \"on_failure\" keyword",
|
|
Detail: "The \"on_failure\" argument requires one of the following keywords: continue or fail.",
|
|
Subject: attr.Expr.Range().Ptr(),
|
|
})
|
|
}
|
|
}
|
|
|
|
var seenConnection *hcl.Block
|
|
for _, block := range content.Blocks {
|
|
switch block.Type {
|
|
|
|
case "connection":
|
|
if seenConnection != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Duplicate connection block",
|
|
Detail: fmt.Sprintf("This provisioner already has a connection block at %s.", seenConnection.DefRange),
|
|
Subject: &block.DefRange,
|
|
})
|
|
continue
|
|
}
|
|
seenConnection = block
|
|
|
|
conn, connDiags := decodeConnectionBlock(block)
|
|
diags = append(diags, connDiags...)
|
|
pv.Connection = conn
|
|
|
|
default:
|
|
// Should never happen because there are no other block types
|
|
// declared in our schema.
|
|
}
|
|
}
|
|
|
|
return pv, diags
|
|
}
|
|
|
|
// Connection represents a "connection" block when used within either a
|
|
// "resource" or "provisioner" block in a module or file.
|
|
type Connection struct {
|
|
Type string
|
|
Config hcl.Body
|
|
|
|
DeclRange hcl.Range
|
|
TypeRange *hcl.Range // nil if type is not set
|
|
}
|
|
|
|
func decodeConnectionBlock(block *hcl.Block) (*Connection, hcl.Diagnostics) {
|
|
content, config, diags := block.Body.PartialContent(&hcl.BodySchema{
|
|
Attributes: []hcl.AttributeSchema{
|
|
{
|
|
Name: "type",
|
|
},
|
|
},
|
|
})
|
|
|
|
conn := &Connection{
|
|
Type: "ssh",
|
|
Config: config,
|
|
DeclRange: block.DefRange,
|
|
}
|
|
|
|
if attr, exists := content.Attributes["type"]; exists {
|
|
valDiags := gohcl.DecodeExpression(attr.Expr, nil, &conn.Type)
|
|
diags = append(diags, valDiags...)
|
|
conn.TypeRange = attr.Expr.Range().Ptr()
|
|
}
|
|
|
|
return conn, diags
|
|
}
|
|
|
|
// ProvisionerWhen is an enum for valid values for when to run provisioners.
|
|
type ProvisionerWhen int
|
|
|
|
//go:generate stringer -type ProvisionerWhen
|
|
|
|
const (
|
|
ProvisionerWhenInvalid ProvisionerWhen = iota
|
|
ProvisionerWhenCreate
|
|
ProvisionerWhenDestroy
|
|
)
|
|
|
|
// ProvisionerOnFailure is an enum for valid values for on_failure options
|
|
// for provisioners.
|
|
type ProvisionerOnFailure int
|
|
|
|
//go:generate stringer -type ProvisionerOnFailure
|
|
|
|
const (
|
|
ProvisionerOnFailureInvalid ProvisionerOnFailure = iota
|
|
ProvisionerOnFailureContinue
|
|
ProvisionerOnFailureFail
|
|
)
|
|
|
|
var provisionerBlockSchema = &hcl.BodySchema{
|
|
Attributes: []hcl.AttributeSchema{
|
|
{
|
|
Name: "when",
|
|
},
|
|
{
|
|
Name: "on_failure",
|
|
},
|
|
},
|
|
Blocks: []hcl.BlockHeaderSchema{
|
|
{
|
|
Type: "connection",
|
|
},
|
|
},
|
|
}
|