mirror of https://github.com/hashicorp/packer
* hcl2template/addrs.ParseRef will parse a reference and tell for example if we are referring to a variable and its name, for now it can only do that and in the future it improved when we need to most of it is from the TF code. This is used to tell wether a variable vas referenced in a variable validation condition; for now. * Added Validations blocks to the hcl2 Variable struct and code to parse/validate that.pull/10206/head
parent
69312458c4
commit
91d7332471
@ -0,0 +1,11 @@
|
||||
package addrs
|
||||
|
||||
// InputVariable is the address of an input variable.
|
||||
type InputVariable struct {
|
||||
referenceable
|
||||
Name string
|
||||
}
|
||||
|
||||
func (v InputVariable) String() string {
|
||||
return "var." + v.Name
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package addrs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
)
|
||||
|
||||
// Reference describes a reference to an address with source location
|
||||
// information.
|
||||
type Reference struct {
|
||||
Subject Referenceable
|
||||
SourceRange hcl.Range
|
||||
Remaining hcl.Traversal
|
||||
}
|
||||
|
||||
// ParseRef attempts to extract a referencable address from the prefix of the
|
||||
// given traversal, which must be an absolute traversal or this function
|
||||
// will panic.
|
||||
//
|
||||
// If no error diagnostics are returned, the returned reference includes the
|
||||
// address that was extracted, the source range it was extracted from, and any
|
||||
// remaining relative traversal that was not consumed as part of the
|
||||
// reference.
|
||||
//
|
||||
// If error diagnostics are returned then the Reference value is invalid and
|
||||
// must not be used.
|
||||
func ParseRef(traversal hcl.Traversal) (*Reference, hcl.Diagnostics) {
|
||||
ref, diags := parseRef(traversal)
|
||||
|
||||
// Normalize a little to make life easier for callers.
|
||||
if ref != nil {
|
||||
if len(ref.Remaining) == 0 {
|
||||
ref.Remaining = nil
|
||||
}
|
||||
}
|
||||
|
||||
return ref, diags
|
||||
}
|
||||
|
||||
func parseRef(traversal hcl.Traversal) (*Reference, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
root := traversal.RootName()
|
||||
rootRange := traversal[0].SourceRange()
|
||||
|
||||
switch root {
|
||||
|
||||
case "var":
|
||||
name, rng, remain, diags := parseSingleAttrRef(traversal)
|
||||
return &Reference{
|
||||
Subject: InputVariable{Name: name},
|
||||
SourceRange: rng,
|
||||
Remaining: remain,
|
||||
}, diags
|
||||
|
||||
default:
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Unhandled reference type",
|
||||
Detail: `Currently parseRef can only parse "var" references.`,
|
||||
Subject: &rootRange,
|
||||
})
|
||||
}
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
func parseSingleAttrRef(traversal hcl.Traversal) (string, hcl.Range, hcl.Traversal, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
root := traversal.RootName()
|
||||
rootRange := traversal[0].SourceRange()
|
||||
|
||||
if len(traversal) < 2 {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid reference",
|
||||
Detail: fmt.Sprintf("The %q object cannot be accessed directly. Instead, access one of its attributes.", root),
|
||||
Subject: &rootRange,
|
||||
})
|
||||
return "", hcl.Range{}, nil, diags
|
||||
}
|
||||
if attrTrav, ok := traversal[1].(hcl.TraverseAttr); ok {
|
||||
return attrTrav.Name, hcl.RangeBetween(rootRange, attrTrav.SrcRange), traversal[2:], diags
|
||||
}
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid reference",
|
||||
Detail: fmt.Sprintf("The %q object does not support this operation.", root),
|
||||
Subject: traversal[1].SourceRange().Ptr(),
|
||||
})
|
||||
return "", hcl.Range{}, nil, diags
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package addrs
|
||||
|
||||
// Referenceable is an interface implemented by all address types that can
|
||||
// appear as references in configuration language expressions.
|
||||
type Referenceable interface {
|
||||
referenceableSigil()
|
||||
|
||||
// String produces a string representation of the address that could be
|
||||
// parsed as a HCL traversal and passed to ParseRef to produce an identical
|
||||
// result.
|
||||
String() string
|
||||
}
|
||||
|
||||
type referenceable struct {
|
||||
}
|
||||
|
||||
func (r referenceable) referenceableSigil() {
|
||||
}
|
||||
Loading…
Reference in new issue