Define variables as blocks with defaults

Signed-off-by: Patrick Van Stee <patrick@vanstee.me>
pull/192/head
Patrick Van Stee 5 years ago
parent 5185d534bc
commit f10d8dab5e

@ -70,8 +70,9 @@ func ParseFile(fn string) (*Config, error) {
} }
type Config struct { type Config struct {
Groups []*Group `hcl:"group,block"` Variables []*Variable `json:"-" hcl:"variable,block"`
Targets []*Target `hcl:"target,block"` Groups []*Group `json:"groups" hcl:"group,block"`
Targets []*Target `json:"targets" hcl:"target,block"`
} }
func mergeConfig(c1, c2 Config) Config { func mergeConfig(c1, c2 Config) Config {
@ -316,6 +317,11 @@ func (c Config) target(name string, visited map[string]struct{}, overrides map[s
return tt, nil return tt, nil
} }
type Variable struct {
Name string `json:"-" hcl:"name,label"`
Default string `json:"default,omitempty" hcl:"default,optional"`
}
type Group struct { type Group struct {
Name string `json:"-" hcl:"name,label"` Name string `json:"-" hcl:"name,label"`
Targets []string `json:"targets" hcl:"targets"` Targets []string `json:"targets" hcl:"targets"`

@ -11,9 +11,8 @@ import (
"github.com/zclconf/go-cty/cty/function/stdlib" "github.com/zclconf/go-cty/cty/function/stdlib"
) )
// Collection of functions expected to be generally useful in cty-using // Collection of generally useful functions in cty-using applications, which
// applications, which HCL supports. This set of functions will be available to // HCL supports. These functions are available for use in HCL files.
// be called in HCL files.
var ( var (
functions = map[string]function.Function{ functions = map[string]function.Function{
"absolute": stdlib.AbsoluteFunc, "absolute": stdlib.AbsoluteFunc,
@ -64,11 +63,35 @@ var (
} }
) )
// Used in the first pass of decoding instead of the Config struct to disallow
// interpolation while parsing variable blocks.
type staticConfig struct {
Variables []*Variable `hcl:"variable,block"`
Remain hcl.Body `hcl:",remain"`
}
func ParseHCL(dt []byte, fn string) (*Config, error) { func ParseHCL(dt []byte, fn string) (*Config, error) {
var sc staticConfig
// Decode only variable blocks without interpolation.
if err := hclsimple.Decode(fn, dt, nil, &sc); err != nil {
return nil, err
}
variables := make(map[string]cty.Value) variables := make(map[string]cty.Value)
// Set all variables to their default value if defined.
for _, variable := range sc.Variables {
variables[variable.Name] = cty.StringVal(variable.Default)
}
// Override default with values from environment.
for _, env := range os.Environ() { for _, env := range os.Environ() {
parts := strings.SplitN(env, "=", 2) parts := strings.SplitN(env, "=", 2)
variables[parts[0]] = cty.StringVal(parts[1]) name, value := parts[0], parts[1]
if _, ok := variables[name]; ok {
variables[name] = cty.StringVal(value)
}
} }
ctx := &hcl.EvalContext{ ctx := &hcl.EvalContext{
@ -77,6 +100,8 @@ func ParseHCL(dt []byte, fn string) (*Config, error) {
} }
var c Config var c Config
// Decode with variables and functions.
if err := hclsimple.Decode(fn, dt, ctx, &c); err != nil { if err := hclsimple.Decode(fn, dt, ctx, &c); err != nil {
return nil, err return nil, err
} }

@ -8,9 +8,13 @@ import (
) )
func TestParseHCL(t *testing.T) { func TestParseHCL(t *testing.T) {
os.Setenv("IAMCROSS", "true") os.Setenv("BUILD_NUMBER", "456")
var dt = []byte(` var dt = []byte(`
variable "BUILD_NUMBER" {
default = "123"
}
group "default" { group "default" {
targets = ["db", "webapp"] targets = ["db", "webapp"]
} }
@ -24,7 +28,7 @@ func TestParseHCL(t *testing.T) {
context = "./dir" context = "./dir"
dockerfile = "Dockerfile-alternate" dockerfile = "Dockerfile-alternate"
args = { args = {
buildno = "123" buildno = "${BUILD_NUMBER}"
} }
} }
@ -38,7 +42,7 @@ func TestParseHCL(t *testing.T) {
target "webapp-plus" { target "webapp-plus" {
inherits = ["webapp", "cross"] inherits = ["webapp", "cross"]
args = { args = {
IAMCROSS = "${IAMCROSS}" IAMCROSS = "true"
} }
} }
`) `)
@ -56,7 +60,7 @@ func TestParseHCL(t *testing.T) {
require.Equal(t, c.Targets[1].Name, "webapp") require.Equal(t, c.Targets[1].Name, "webapp")
require.Equal(t, 1, len(c.Targets[1].Args)) require.Equal(t, 1, len(c.Targets[1].Args))
require.Equal(t, "123", c.Targets[1].Args["buildno"]) require.Equal(t, "456", c.Targets[1].Args["buildno"])
require.Equal(t, c.Targets[2].Name, "cross") require.Equal(t, c.Targets[2].Name, "cross")
require.Equal(t, 2, len(c.Targets[2].Platforms)) require.Equal(t, 2, len(c.Targets[2].Platforms))

Loading…
Cancel
Save