projects/projectconfigs: decode "upstream" block contents

f-workspaces2-prototype
Martin Atkins 7 years ago
parent edd27f4ec2
commit 332fc6ef31

@ -33,6 +33,7 @@ type Config struct {
Context map[string]*ContextValue
Locals map[string]*LocalValue
Workspaces map[string]*Workspace
Upstreams map[string]*Upstream
}
func loadConfigDir(rootDir string) (*Config, tfdiags.Diagnostics) {
@ -187,6 +188,25 @@ func loadConfig(rootDir, filename string, src []byte, body hcl.Body) (*Config, t
config.Workspaces[ws.Name] = ws
}
case "upstream":
u, moreDiags := decodeUpstreamBlock(block)
diags = diags.Append(moreDiags)
if u != nil {
if existing, exists := config.Upstreams[u.Name]; exists {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Duplicate \"upstream\" block",
Detail: fmt.Sprintf("An upstream %q block was already declared at %s.", u.Name, existing.DeclRange.StartString()),
Subject: u.NameRange.ToHCL().Ptr(),
Context: u.DeclRange.ToHCL().Ptr(),
})
continue
}
config.Upstreams[u.Name] = u
}
default:
// No other block types in our schema, so anything else is a bug.
panic(fmt.Sprintf("unexpected block type %q", block.Type))
@ -201,5 +221,6 @@ var rootSchema = &hcl.BodySchema{
{Type: "context", LabelNames: []string{"name"}},
{Type: "locals"},
{Type: "workspace", LabelNames: []string{"name"}},
{Type: "upstream", LabelNames: []string{"name"}},
},
}

@ -0,0 +1,69 @@
package projectconfigs
import (
"fmt"
"github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/terraform/tfdiags"
)
// Upstream represents a remote workspace from another project that this
// project derives values from.
type Upstream struct {
// Name is the name label given in the block header.
//
// It is guaranteed to be a valid HCL identifier.
Name string
// ForEach is the expression given in the for_each argument, or nil if
// that argument wasn't set.
ForEach hcl.Expression
// Remote is the expression given in the "remote" argument.
Remote hcl.Expression
// DeclRange is the source range of the block header of this block,
// for use in diagnostic messages. NameRange is the range of the
// Name string specifically.
DeclRange, NameRange tfdiags.SourceRange
}
func decodeUpstreamBlock(block *hcl.Block) (*Upstream, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
u := &Upstream{
Name: block.Labels[0],
DeclRange: tfdiags.SourceRangeFromHCL(block.DefRange),
NameRange: tfdiags.SourceRangeFromHCL(block.LabelRanges[0]),
}
if !hclsyntax.ValidIdentifier(u.Name) {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid name for \"upstream\" block",
Detail: fmt.Sprintf("The name %q is not a valid name for an \"upstream\" block. Must start with a letter, followed by zero or more letters, digits, and underscores.", u.Name),
Subject: block.LabelRanges[0].Ptr(),
})
}
content, hclDiags := block.Body.Content(workspaceSchema)
diags = diags.Append(hclDiags)
if attr, ok := content.Attributes["for_each"]; ok {
u.ForEach = attr.Expr
}
if attr, ok := content.Attributes["remote"]; ok {
u.Remote = attr.Expr
}
return u, diags
}
var upstreamSchema = &hcl.BodySchema{
Attributes: []hcl.AttributeSchema{
{Name: "for_each"},
{Name: "remote", Required: true},
},
}
Loading…
Cancel
Save