bake: support null arg value

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
pull/1449/head
CrazyMax 2 years ago
parent e21f56e801
commit df4957307f
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7

@ -559,24 +559,24 @@ type Target struct {
Attest []string `json:"attest,omitempty" hcl:"attest,optional" cty:"attest"` Attest []string `json:"attest,omitempty" hcl:"attest,optional" cty:"attest"`
Inherits []string `json:"inherits,omitempty" hcl:"inherits,optional" cty:"inherits"` Inherits []string `json:"inherits,omitempty" hcl:"inherits,optional" cty:"inherits"`
Context *string `json:"context,omitempty" hcl:"context,optional" cty:"context"` Context *string `json:"context,omitempty" hcl:"context,optional" cty:"context"`
Contexts map[string]string `json:"contexts,omitempty" hcl:"contexts,optional" cty:"contexts"` Contexts map[string]string `json:"contexts,omitempty" hcl:"contexts,optional" cty:"contexts"`
Dockerfile *string `json:"dockerfile,omitempty" hcl:"dockerfile,optional" cty:"dockerfile"` Dockerfile *string `json:"dockerfile,omitempty" hcl:"dockerfile,optional" cty:"dockerfile"`
DockerfileInline *string `json:"dockerfile-inline,omitempty" hcl:"dockerfile-inline,optional" cty:"dockerfile-inline"` DockerfileInline *string `json:"dockerfile-inline,omitempty" hcl:"dockerfile-inline,optional" cty:"dockerfile-inline"`
Args map[string]string `json:"args,omitempty" hcl:"args,optional" cty:"args"` Args map[string]*string `json:"args,omitempty" hcl:"args,optional" cty:"args"`
Labels map[string]string `json:"labels,omitempty" hcl:"labels,optional" cty:"labels"` Labels map[string]string `json:"labels,omitempty" hcl:"labels,optional" cty:"labels"`
Tags []string `json:"tags,omitempty" hcl:"tags,optional" cty:"tags"` Tags []string `json:"tags,omitempty" hcl:"tags,optional" cty:"tags"`
CacheFrom []string `json:"cache-from,omitempty" hcl:"cache-from,optional" cty:"cache-from"` CacheFrom []string `json:"cache-from,omitempty" hcl:"cache-from,optional" cty:"cache-from"`
CacheTo []string `json:"cache-to,omitempty" hcl:"cache-to,optional" cty:"cache-to"` CacheTo []string `json:"cache-to,omitempty" hcl:"cache-to,optional" cty:"cache-to"`
Target *string `json:"target,omitempty" hcl:"target,optional" cty:"target"` Target *string `json:"target,omitempty" hcl:"target,optional" cty:"target"`
Secrets []string `json:"secret,omitempty" hcl:"secret,optional" cty:"secret"` Secrets []string `json:"secret,omitempty" hcl:"secret,optional" cty:"secret"`
SSH []string `json:"ssh,omitempty" hcl:"ssh,optional" cty:"ssh"` SSH []string `json:"ssh,omitempty" hcl:"ssh,optional" cty:"ssh"`
Platforms []string `json:"platforms,omitempty" hcl:"platforms,optional" cty:"platforms"` Platforms []string `json:"platforms,omitempty" hcl:"platforms,optional" cty:"platforms"`
Outputs []string `json:"output,omitempty" hcl:"output,optional" cty:"output"` Outputs []string `json:"output,omitempty" hcl:"output,optional" cty:"output"`
Pull *bool `json:"pull,omitempty" hcl:"pull,optional" cty:"pull"` Pull *bool `json:"pull,omitempty" hcl:"pull,optional" cty:"pull"`
NoCache *bool `json:"no-cache,omitempty" hcl:"no-cache,optional" cty:"no-cache"` NoCache *bool `json:"no-cache,omitempty" hcl:"no-cache,optional" cty:"no-cache"`
NetworkMode *string `json:"-" hcl:"-" cty:"-"` NetworkMode *string `json:"-" hcl:"-" cty:"-"`
NoCacheFilter []string `json:"no-cache-filter,omitempty" hcl:"no-cache-filter,optional" cty:"no-cache-filter"` NoCacheFilter []string `json:"no-cache-filter,omitempty" hcl:"no-cache-filter,optional" cty:"no-cache-filter"`
// IMPORTANT: if you add more fields here, do not forget to update newOverrides and docs/manuals/bake/file-definition.md. // IMPORTANT: if you add more fields here, do not forget to update newOverrides and docs/manuals/bake/file-definition.md.
// linked is a private field to mark a target used as a linked one // linked is a private field to mark a target used as a linked one
@ -615,8 +615,11 @@ func (t *Target) Merge(t2 *Target) {
t.DockerfileInline = t2.DockerfileInline t.DockerfileInline = t2.DockerfileInline
} }
for k, v := range t2.Args { for k, v := range t2.Args {
if v == nil {
continue
}
if t.Args == nil { if t.Args == nil {
t.Args = map[string]string{} t.Args = map[string]*string{}
} }
t.Args[k] = v t.Args[k] = v
} }
@ -688,9 +691,9 @@ func (t *Target) AddOverrides(overrides map[string]Override) error {
return errors.Errorf("args require name") return errors.Errorf("args require name")
} }
if t.Args == nil { if t.Args == nil {
t.Args = map[string]string{} t.Args = map[string]*string{}
} }
t.Args[keys[1]] = value t.Args[keys[1]] = &value
case "contexts": case "contexts":
if len(keys) != 2 { if len(keys) != 2 {
return errors.Errorf("contexts require name") return errors.Errorf("contexts require name")
@ -882,6 +885,14 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
dockerfilePath = path.Join(contextPath, dockerfilePath) dockerfilePath = path.Join(contextPath, dockerfilePath)
} }
args := map[string]string{}
for k, v := range t.Args {
if v == nil {
continue
}
args[k] = *v
}
noCache := false noCache := false
if t.NoCache != nil { if t.NoCache != nil {
noCache = *t.NoCache noCache = *t.NoCache
@ -922,7 +933,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
bo := &build.Options{ bo := &build.Options{
Inputs: bi, Inputs: bi,
Tags: t.Tags, Tags: t.Tags,
BuildArgs: t.Args, BuildArgs: args,
Labels: t.Labels, Labels: t.Labels,
NoCache: noCache, NoCache: noCache,
NoCacheFilter: t.NoCacheFilter, NoCacheFilter: t.NoCacheFilter,

@ -2,7 +2,6 @@ package bake
import ( import (
"context" "context"
"os"
"sort" "sort"
"strings" "strings"
"testing" "testing"
@ -42,7 +41,7 @@ target "webapp" {
require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile) require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile)
require.Equal(t, ".", *m["webapp"].Context) require.Equal(t, ".", *m["webapp"].Context)
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"]) require.Equal(t, ptrstr("webDEP"), m["webapp"].Args["VAR_INHERITED"])
require.Equal(t, true, *m["webapp"].NoCache) require.Equal(t, true, *m["webapp"].NoCache)
require.Nil(t, m["webapp"].Pull) require.Nil(t, m["webapp"].Pull)
@ -58,8 +57,7 @@ target "webapp" {
t.Run("ArgsOverrides", func(t *testing.T) { t.Run("ArgsOverrides", func(t *testing.T) {
t.Run("leaf", func(t *testing.T) { t.Run("leaf", func(t *testing.T) {
os.Setenv("VAR_FROMENV"+t.Name(), "fromEnv") t.Setenv("VAR_FROMENV"+t.Name(), "fromEnv")
defer os.Unsetenv("VAR_FROM_ENV" + t.Name())
m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{ m, g, err := ReadTargets(ctx, []File{fp}, []string{"webapp"}, []string{
"webapp.args.VAR_UNSET", "webapp.args.VAR_UNSET",
@ -80,12 +78,12 @@ target "webapp" {
_, isSet = m["webapp"].Args["VAR_EMPTY"] _, isSet = m["webapp"].Args["VAR_EMPTY"]
require.True(t, isSet, m["webapp"].Args["VAR_EMPTY"]) require.True(t, isSet, m["webapp"].Args["VAR_EMPTY"])
require.Equal(t, m["webapp"].Args["VAR_SET"], "bananas") require.Equal(t, ptrstr("bananas"), m["webapp"].Args["VAR_SET"])
require.Equal(t, m["webapp"].Args["VAR_FROMENV"+t.Name()], "fromEnv") require.Equal(t, ptrstr("fromEnv"), m["webapp"].Args["VAR_FROMENV"+t.Name()])
require.Equal(t, m["webapp"].Args["VAR_BOTH"], "webapp") require.Equal(t, ptrstr("webapp"), m["webapp"].Args["VAR_BOTH"])
require.Equal(t, m["webapp"].Args["VAR_INHERITED"], "override") require.Equal(t, ptrstr("override"), m["webapp"].Args["VAR_INHERITED"])
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"webapp"}, g["default"].Targets) require.Equal(t, []string{"webapp"}, g["default"].Targets)
@ -99,8 +97,8 @@ target "webapp" {
}, nil) }, nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, m["webapp"].Args["VAR_INHERITED"], "override") require.Equal(t, ptrstr("override"), m["webapp"].Args["VAR_INHERITED"])
require.Equal(t, m["webapp"].Args["VAR_BOTH"], "webapp") require.Equal(t, ptrstr("webapp"), m["webapp"].Args["VAR_BOTH"])
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"webapp"}, g["default"].Targets) require.Equal(t, []string{"webapp"}, g["default"].Targets)
}) })
@ -139,9 +137,9 @@ target "webapp" {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, len(m)) require.Equal(t, 2, len(m))
require.Equal(t, "foo", *m["webapp"].Dockerfile) require.Equal(t, "foo", *m["webapp"].Dockerfile)
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"]) require.Equal(t, ptrstr("webDEP"), m["webapp"].Args["VAR_INHERITED"])
require.Equal(t, "foo", *m["webDEP"].Dockerfile) require.Equal(t, "foo", *m["webDEP"].Dockerfile)
require.Equal(t, "webDEP", m["webDEP"].Args["VAR_INHERITED"]) require.Equal(t, ptrstr("webDEP"), m["webDEP"].Args["VAR_INHERITED"])
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
sort.Strings(g["default"].Targets) sort.Strings(g["default"].Targets)
require.Equal(t, []string{"webDEP", "webapp"}, g["default"].Targets) require.Equal(t, []string{"webDEP", "webapp"}, g["default"].Targets)
@ -173,7 +171,7 @@ target "webapp" {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(m)) require.Equal(t, 1, len(m))
require.Equal(t, "foo", *m["webapp"].Dockerfile) require.Equal(t, "foo", *m["webapp"].Dockerfile)
require.Equal(t, "webDEP", m["webapp"].Args["VAR_INHERITED"]) require.Equal(t, ptrstr("webDEP"), m["webapp"].Args["VAR_INHERITED"])
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
require.Equal(t, []string{"webapp"}, g["default"].Targets) require.Equal(t, []string{"webapp"}, g["default"].Targets)
}, },
@ -300,8 +298,8 @@ services:
require.True(t, ok) require.True(t, ok)
require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile) require.Equal(t, "Dockerfile.webapp", *m["webapp"].Dockerfile)
require.Equal(t, ".", *m["webapp"].Context) require.Equal(t, ".", *m["webapp"].Context)
require.Equal(t, "1", m["webapp"].Args["buildno"]) require.Equal(t, ptrstr("1"), m["webapp"].Args["buildno"])
require.Equal(t, "12", m["webapp"].Args["buildno2"]) require.Equal(t, ptrstr("12"), m["webapp"].Args["buildno2"])
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
sort.Strings(g["default"].Targets) sort.Strings(g["default"].Targets)
@ -344,7 +342,7 @@ services:
_, ok := m["web_app"] _, ok := m["web_app"]
require.True(t, ok) require.True(t, ok)
require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile) require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile)
require.Equal(t, "1", m["web_app"].Args["buildno"]) require.Equal(t, ptrstr("1"), m["web_app"].Args["buildno"])
m, _, err = ReadTargets(ctx, []File{fp2}, []string{"web_app"}, nil, nil) m, _, err = ReadTargets(ctx, []File{fp2}, []string{"web_app"}, nil, nil)
require.NoError(t, err) require.NoError(t, err)
@ -352,7 +350,7 @@ services:
_, ok = m["web_app"] _, ok = m["web_app"]
require.True(t, ok) require.True(t, ok)
require.Equal(t, "Dockerfile", *m["web_app"].Dockerfile) require.Equal(t, "Dockerfile", *m["web_app"].Dockerfile)
require.Equal(t, "12", m["web_app"].Args["buildno2"]) require.Equal(t, ptrstr("12"), m["web_app"].Args["buildno2"])
m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil) m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil)
require.NoError(t, err) require.NoError(t, err)
@ -361,8 +359,8 @@ services:
require.True(t, ok) require.True(t, ok)
require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile) require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile)
require.Equal(t, ".", *m["web_app"].Context) require.Equal(t, ".", *m["web_app"].Context)
require.Equal(t, "1", m["web_app"].Args["buildno"]) require.Equal(t, ptrstr("1"), m["web_app"].Args["buildno"])
require.Equal(t, "12", m["web_app"].Args["buildno2"]) require.Equal(t, ptrstr("12"), m["web_app"].Args["buildno2"])
require.Equal(t, 1, len(g)) require.Equal(t, 1, len(g))
sort.Strings(g["default"].Targets) sort.Strings(g["default"].Targets)
@ -999,22 +997,22 @@ target "d" {
cases := []struct { cases := []struct {
name string name string
overrides []string overrides []string
want map[string]string want map[string]*string
}{ }{
{ {
name: "nested simple", name: "nested simple",
overrides: nil, overrides: nil,
want: map[string]string{"bar": "234", "baz": "890", "foo": "123"}, want: map[string]*string{"bar": ptrstr("234"), "baz": ptrstr("890"), "foo": ptrstr("123")},
}, },
{ {
name: "nested with overrides first", name: "nested with overrides first",
overrides: []string{"a.args.foo=321", "b.args.bar=432"}, overrides: []string{"a.args.foo=321", "b.args.bar=432"},
want: map[string]string{"bar": "234", "baz": "890", "foo": "321"}, want: map[string]*string{"bar": ptrstr("234"), "baz": ptrstr("890"), "foo": ptrstr("321")},
}, },
{ {
name: "nested with overrides last", name: "nested with overrides last",
overrides: []string{"a.args.foo=321", "c.args.bar=432"}, overrides: []string{"a.args.foo=321", "c.args.bar=432"},
want: map[string]string{"bar": "432", "baz": "890", "foo": "321"}, want: map[string]*string{"bar": ptrstr("432"), "baz": ptrstr("890"), "foo": ptrstr("321")},
}, },
} }
for _, tt := range cases { for _, tt := range cases {
@ -1067,26 +1065,26 @@ group "default" {
cases := []struct { cases := []struct {
name string name string
overrides []string overrides []string
wantch1 map[string]string wantch1 map[string]*string
wantch2 map[string]string wantch2 map[string]*string
}{ }{
{ {
name: "nested simple", name: "nested simple",
overrides: nil, overrides: nil,
wantch1: map[string]string{"BAR": "fuu", "FOO": "bar"}, wantch1: map[string]*string{"BAR": ptrstr("fuu"), "FOO": ptrstr("bar")},
wantch2: map[string]string{"BAR": "fuu", "FOO": "bar", "FOO2": "bar2"}, wantch2: map[string]*string{"BAR": ptrstr("fuu"), "FOO": ptrstr("bar"), "FOO2": ptrstr("bar2")},
}, },
{ {
name: "nested with overrides first", name: "nested with overrides first",
overrides: []string{"grandparent.args.BAR=fii", "child1.args.FOO=baaar"}, overrides: []string{"grandparent.args.BAR=fii", "child1.args.FOO=baaar"},
wantch1: map[string]string{"BAR": "fii", "FOO": "baaar"}, wantch1: map[string]*string{"BAR": ptrstr("fii"), "FOO": ptrstr("baaar")},
wantch2: map[string]string{"BAR": "fii", "FOO": "bar", "FOO2": "bar2"}, wantch2: map[string]*string{"BAR": ptrstr("fii"), "FOO": ptrstr("bar"), "FOO2": ptrstr("bar2")},
}, },
{ {
name: "nested with overrides last", name: "nested with overrides last",
overrides: []string{"grandparent.args.BAR=fii", "child2.args.FOO=baaar"}, overrides: []string{"grandparent.args.BAR=fii", "child2.args.FOO=baaar"},
wantch1: map[string]string{"BAR": "fii", "FOO": "bar"}, wantch1: map[string]*string{"BAR": ptrstr("fii"), "FOO": ptrstr("bar")},
wantch2: map[string]string{"BAR": "fii", "FOO": "baaar", "FOO2": "bar2"}, wantch2: map[string]*string{"BAR": ptrstr("fii"), "FOO": ptrstr("baaar"), "FOO2": ptrstr("bar2")},
}, },
} }
for _, tt := range cases { for _, tt := range cases {
@ -1285,8 +1283,70 @@ services:
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, "app", c.Targets[0].Name) require.Equal(t, "app", c.Targets[0].Name)
require.Equal(t, "foo", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("foo"), c.Targets[0].Args["v1"])
require.Equal(t, "bar", c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("bar"), c.Targets[0].Args["v2"])
require.Equal(t, "dir", *c.Targets[0].Context) require.Equal(t, "dir", *c.Targets[0].Context)
require.Equal(t, "Dockerfile-alternate", *c.Targets[0].Dockerfile) require.Equal(t, "Dockerfile-alternate", *c.Targets[0].Dockerfile)
} }
func TestHCLNullVars(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(
`variable "FOO" {
default = null
}
target "default" {
args = {
foo = FOO
bar = "baz"
}
}`),
}
ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil)
require.NoError(t, err)
require.Equal(t, 1, len(m))
_, ok := m["default"]
require.True(t, ok)
_, err = TargetsToBuildOpt(m, &Input{})
require.NoError(t, err)
require.Equal(t, map[string]*string{"bar": ptrstr("baz")}, m["default"].Args)
}
func TestJSONNullVars(t *testing.T) {
fp := File{
Name: "docker-bake.json",
Data: []byte(
`{
"variable": {
"FOO": {
"default": null
}
},
"target": {
"default": {
"args": {
"foo": "${FOO}",
"bar": "baz"
}
}
}
}`),
}
ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"default"}, nil, nil)
require.NoError(t, err)
require.Equal(t, 1, len(m))
_, ok := m["default"]
require.True(t, ok)
_, err = TargetsToBuildOpt(m, &Input{})
require.NoError(t, err)
require.Equal(t, map[string]*string{"bar": ptrstr("baz")}, m["default"].Args)
}

@ -193,16 +193,16 @@ func loadDotEnv(curenv map[string]string, workingDir string) (map[string]string,
return curenv, nil return curenv, nil
} }
func flatten(in compose.MappingWithEquals) compose.Mapping { func flatten(in compose.MappingWithEquals) map[string]*string {
if len(in) == 0 { if len(in) == 0 {
return nil return nil
} }
out := compose.Mapping{} out := map[string]*string{}
for k, v := range in { for k, v := range in {
if v == nil { if v == nil {
continue continue
} }
out[k] = *v out[k] = v
} }
return out return out
} }

@ -60,7 +60,7 @@ secrets:
require.Equal(t, "./dir", *c.Targets[1].Context) require.Equal(t, "./dir", *c.Targets[1].Context)
require.Equal(t, "Dockerfile-alternate", *c.Targets[1].Dockerfile) require.Equal(t, "Dockerfile-alternate", *c.Targets[1].Dockerfile)
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, ptrstr("123"), c.Targets[1].Args["buildno"])
require.Equal(t, []string{"type=local,src=path/to/cache"}, c.Targets[1].CacheFrom) require.Equal(t, []string{"type=local,src=path/to/cache"}, c.Targets[1].CacheFrom)
require.Equal(t, []string{"type=local,dest=path/to/cache"}, c.Targets[1].CacheTo) require.Equal(t, []string{"type=local,dest=path/to/cache"}, c.Targets[1].CacheTo)
require.Equal(t, "none", *c.Targets[1].NetworkMode) require.Equal(t, "none", *c.Targets[1].NetworkMode)
@ -149,18 +149,15 @@ services:
BRB: FOO BRB: FOO
`) `)
os.Setenv("FOO", "bar") t.Setenv("FOO", "bar")
defer os.Unsetenv("FOO") t.Setenv("BAR", "foo")
os.Setenv("BAR", "foo") t.Setenv("ZZZ_BAR", "zzz_foo")
defer os.Unsetenv("BAR")
os.Setenv("ZZZ_BAR", "zzz_foo")
defer os.Unsetenv("ZZZ_BAR")
c, err := ParseCompose([]compose.ConfigFile{{Content: dt}}, sliceToMap(os.Environ())) c, err := ParseCompose([]compose.ConfigFile{{Content: dt}}, sliceToMap(os.Environ()))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "bar", c.Targets[0].Args["FOO"]) require.Equal(t, ptrstr("bar"), c.Targets[0].Args["FOO"])
require.Equal(t, "zzz_foo", c.Targets[0].Args["BAR"]) require.Equal(t, ptrstr("zzz_foo"), c.Targets[0].Args["BAR"])
require.Equal(t, "FOO", c.Targets[0].Args["BRB"]) require.Equal(t, ptrstr("FOO"), c.Targets[0].Args["BRB"])
} }
func TestInconsistentComposeFile(t *testing.T) { func TestInconsistentComposeFile(t *testing.T) {
@ -308,7 +305,7 @@ services:
sort.Slice(c.Targets, func(i, j int) bool { sort.Slice(c.Targets, func(i, j int) bool {
return c.Targets[i].Name < c.Targets[j].Name return c.Targets[i].Name < c.Targets[j].Name
}) })
require.Equal(t, map[string]string{"CT_ECR": "foo", "CT_TAG": "bar"}, c.Targets[0].Args) require.Equal(t, map[string]*string{"CT_ECR": ptrstr("foo"), "CT_TAG": ptrstr("bar")}, c.Targets[0].Args)
require.Equal(t, []string{"ct-addon:baz", "ct-addon:foo", "ct-addon:alp"}, c.Targets[0].Tags) require.Equal(t, []string{"ct-addon:baz", "ct-addon:foo", "ct-addon:alp"}, c.Targets[0].Tags)
require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[0].Platforms) require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[0].Platforms)
require.Equal(t, []string{"user/app:cache", "type=local,src=path/to/cache"}, c.Targets[0].CacheFrom) require.Equal(t, []string{"user/app:cache", "type=local,src=path/to/cache"}, c.Targets[0].CacheFrom)
@ -381,7 +378,7 @@ services:
c, err := ParseCompose([]compose.ConfigFile{{Content: dt}}, nil) c, err := ParseCompose([]compose.ConfigFile{{Content: dt}}, nil)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, map[string]string{"CT_ECR": "foo", "FOO": "bsdf -csdf", "NODE_ENV": "test"}, c.Targets[0].Args) require.Equal(t, map[string]*string{"CT_ECR": ptrstr("foo"), "FOO": ptrstr("bsdf -csdf"), "NODE_ENV": ptrstr("test")}, c.Targets[0].Args)
} }
func TestDotEnv(t *testing.T) { func TestDotEnv(t *testing.T) {
@ -405,7 +402,7 @@ services:
Data: dt, Data: dt,
}}) }})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, map[string]string{"FOO": "bar"}, c.Targets[0].Args) require.Equal(t, map[string]*string{"FOO": ptrstr("bar")}, c.Targets[0].Args)
} }
func TestPorts(t *testing.T) { func TestPorts(t *testing.T) {
@ -629,6 +626,22 @@ target "default" {
} }
} }
func TestComposeNullArgs(t *testing.T) {
var dt = []byte(`
services:
scratch:
build:
context: .
args:
FOO: null
bar: "baz"
`)
c, err := ParseCompose([]compose.ConfigFile{{Content: dt}}, nil)
require.NoError(t, err)
require.Equal(t, map[string]*string{"bar": ptrstr("baz")}, c.Targets[0].Args)
}
// chdir changes the current working directory to the named directory, // chdir changes the current working directory to the named directory,
// and then restore the original working directory at the end of the test. // and then restore the original working directory at the end of the test.
func chdir(t *testing.T, dir string) { func chdir(t *testing.T, dir string) {

@ -1,7 +1,7 @@
package bake package bake
import ( import (
"os" "reflect"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -54,7 +54,7 @@ func TestHCLBasic(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, ptrstr("123"), 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))
@ -62,7 +62,7 @@ func TestHCLBasic(t *testing.T) {
require.Equal(t, c.Targets[3].Name, "webapp-plus") require.Equal(t, c.Targets[3].Name, "webapp-plus")
require.Equal(t, 1, len(c.Targets[3].Args)) require.Equal(t, 1, len(c.Targets[3].Args))
require.Equal(t, map[string]string{"IAMCROSS": "true"}, c.Targets[3].Args) require.Equal(t, map[string]*string{"IAMCROSS": ptrstr("true")}, c.Targets[3].Args)
} }
func TestHCLBasicInJSON(t *testing.T) { func TestHCLBasicInJSON(t *testing.T) {
@ -114,7 +114,7 @@ func TestHCLBasicInJSON(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, ptrstr("123"), 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))
@ -122,7 +122,7 @@ func TestHCLBasicInJSON(t *testing.T) {
require.Equal(t, c.Targets[3].Name, "webapp-plus") require.Equal(t, c.Targets[3].Name, "webapp-plus")
require.Equal(t, 1, len(c.Targets[3].Args)) require.Equal(t, 1, len(c.Targets[3].Args))
require.Equal(t, map[string]string{"IAMCROSS": "true"}, c.Targets[3].Args) require.Equal(t, map[string]*string{"IAMCROSS": ptrstr("true")}, c.Targets[3].Args)
} }
func TestHCLWithFunctions(t *testing.T) { func TestHCLWithFunctions(t *testing.T) {
@ -147,7 +147,7 @@ func TestHCLWithFunctions(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, c.Targets[0].Name, "webapp")
require.Equal(t, "124", c.Targets[0].Args["buildno"]) require.Equal(t, ptrstr("124"), c.Targets[0].Args["buildno"])
} }
func TestHCLWithUserDefinedFunctions(t *testing.T) { func TestHCLWithUserDefinedFunctions(t *testing.T) {
@ -177,7 +177,7 @@ func TestHCLWithUserDefinedFunctions(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, c.Targets[0].Name, "webapp")
require.Equal(t, "124", c.Targets[0].Args["buildno"]) require.Equal(t, ptrstr("124"), c.Targets[0].Args["buildno"])
} }
func TestHCLWithVariables(t *testing.T) { func TestHCLWithVariables(t *testing.T) {
@ -206,9 +206,9 @@ func TestHCLWithVariables(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, c.Targets[0].Name, "webapp")
require.Equal(t, "123", c.Targets[0].Args["buildno"]) require.Equal(t, ptrstr("123"), c.Targets[0].Args["buildno"])
os.Setenv("BUILD_NUMBER", "456") t.Setenv("BUILD_NUMBER", "456")
c, err = ParseFile(dt, "docker-bake.hcl") c, err = ParseFile(dt, "docker-bake.hcl")
require.NoError(t, err) require.NoError(t, err)
@ -219,7 +219,7 @@ func TestHCLWithVariables(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, c.Targets[0].Name, "webapp")
require.Equal(t, "456", c.Targets[0].Args["buildno"]) require.Equal(t, ptrstr("456"), c.Targets[0].Args["buildno"])
} }
func TestHCLWithVariablesInFunctions(t *testing.T) { func TestHCLWithVariablesInFunctions(t *testing.T) {
@ -244,7 +244,7 @@ func TestHCLWithVariablesInFunctions(t *testing.T) {
require.Equal(t, c.Targets[0].Name, "webapp") require.Equal(t, c.Targets[0].Name, "webapp")
require.Equal(t, []string{"user/repo:v1"}, c.Targets[0].Tags) require.Equal(t, []string{"user/repo:v1"}, c.Targets[0].Tags)
os.Setenv("REPO", "docker/buildx") t.Setenv("REPO", "docker/buildx")
c, err = ParseFile(dt, "docker-bake.hcl") c, err = ParseFile(dt, "docker-bake.hcl")
require.NoError(t, err) require.NoError(t, err)
@ -280,10 +280,10 @@ func TestHCLMultiFileSharedVariables(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "pre-abc", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-abc"), c.Targets[0].Args["v1"])
require.Equal(t, "abc-post", c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("abc-post"), c.Targets[0].Args["v2"])
os.Setenv("FOO", "def") t.Setenv("FOO", "def")
c, err = ParseFiles([]File{ c, err = ParseFiles([]File{
{Data: dt, Name: "c1.hcl"}, {Data: dt, Name: "c1.hcl"},
@ -293,12 +293,11 @@ func TestHCLMultiFileSharedVariables(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "pre-def", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-def"), c.Targets[0].Args["v1"])
require.Equal(t, "def-post", c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("def-post"), c.Targets[0].Args["v2"])
} }
func TestHCLVarsWithVars(t *testing.T) { func TestHCLVarsWithVars(t *testing.T) {
os.Unsetenv("FOO")
dt := []byte(` dt := []byte(`
variable "FOO" { variable "FOO" {
default = upper("${BASE}def") default = upper("${BASE}def")
@ -330,10 +329,10 @@ func TestHCLVarsWithVars(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "pre--ABCDEF-", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre--ABCDEF-"), c.Targets[0].Args["v1"])
require.Equal(t, "ABCDEF-post", c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("ABCDEF-post"), c.Targets[0].Args["v2"])
os.Setenv("BASE", "new") t.Setenv("BASE", "new")
c, err = ParseFiles([]File{ c, err = ParseFiles([]File{
{Data: dt, Name: "c1.hcl"}, {Data: dt, Name: "c1.hcl"},
@ -343,12 +342,11 @@ func TestHCLVarsWithVars(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "pre--NEWDEF-", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre--NEWDEF-"), c.Targets[0].Args["v1"])
require.Equal(t, "NEWDEF-post", c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("NEWDEF-post"), c.Targets[0].Args["v2"])
} }
func TestHCLTypedVariables(t *testing.T) { func TestHCLTypedVariables(t *testing.T) {
os.Unsetenv("FOO")
dt := []byte(` dt := []byte(`
variable "FOO" { variable "FOO" {
default = 3 default = 3
@ -369,33 +367,80 @@ func TestHCLTypedVariables(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "lower", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("lower"), c.Targets[0].Args["v1"])
require.Equal(t, "yes", c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("yes"), c.Targets[0].Args["v2"])
os.Setenv("FOO", "5.1") t.Setenv("FOO", "5.1")
os.Setenv("IS_FOO", "0") t.Setenv("IS_FOO", "0")
c, err = ParseFile(dt, "docker-bake.hcl") c, err = ParseFile(dt, "docker-bake.hcl")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "higher", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("higher"), c.Targets[0].Args["v1"])
require.Equal(t, "no", c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("no"), c.Targets[0].Args["v2"])
os.Setenv("FOO", "NaN") t.Setenv("FOO", "NaN")
_, err = ParseFile(dt, "docker-bake.hcl") _, err = ParseFile(dt, "docker-bake.hcl")
require.Error(t, err) require.Error(t, err)
require.Contains(t, err.Error(), "failed to parse FOO as number") require.Contains(t, err.Error(), "failed to parse FOO as number")
os.Setenv("FOO", "0") t.Setenv("FOO", "0")
os.Setenv("IS_FOO", "maybe") t.Setenv("IS_FOO", "maybe")
_, err = ParseFile(dt, "docker-bake.hcl") _, err = ParseFile(dt, "docker-bake.hcl")
require.Error(t, err) require.Error(t, err)
require.Contains(t, err.Error(), "failed to parse IS_FOO as bool") require.Contains(t, err.Error(), "failed to parse IS_FOO as bool")
} }
func TestHCLNullVariables(t *testing.T) {
dt := []byte(`
variable "FOO" {
default = null
}
target "default" {
args = {
foo = FOO
}
}`)
c, err := ParseFile(dt, "docker-bake.hcl")
require.NoError(t, err)
require.Equal(t, ptrstr(nil), c.Targets[0].Args["foo"])
t.Setenv("FOO", "bar")
c, err = ParseFile(dt, "docker-bake.hcl")
require.NoError(t, err)
require.Equal(t, ptrstr("bar"), c.Targets[0].Args["foo"])
}
func TestJSONNullVariables(t *testing.T) {
dt := []byte(`{
"variable": {
"FOO": {
"default": null
}
},
"target": {
"default": {
"args": {
"foo": "${FOO}"
}
}
}
}`)
c, err := ParseFile(dt, "docker-bake.json")
require.NoError(t, err)
require.Equal(t, ptrstr(nil), c.Targets[0].Args["foo"])
t.Setenv("FOO", "bar")
c, err = ParseFile(dt, "docker-bake.json")
require.NoError(t, err)
require.Equal(t, ptrstr("bar"), c.Targets[0].Args["foo"])
}
func TestHCLVariableCycle(t *testing.T) { func TestHCLVariableCycle(t *testing.T) {
dt := []byte(` dt := []byte(`
variable "FOO" { variable "FOO" {
@ -431,16 +476,16 @@ func TestHCLAttrs(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "attr-abcdef", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("attr-abcdef"), c.Targets[0].Args["v1"])
// env does not apply if no variable // env does not apply if no variable
os.Setenv("FOO", "bar") t.Setenv("FOO", "bar")
c, err = ParseFile(dt, "docker-bake.hcl") c, err = ParseFile(dt, "docker-bake.hcl")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "attr-abcdef", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("attr-abcdef"), c.Targets[0].Args["v1"])
// attr-multifile // attr-multifile
} }
@ -549,11 +594,10 @@ func TestHCLAttrsCustomType(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, []string{"linux/arm64", "linux/amd64"}, c.Targets[0].Platforms) require.Equal(t, []string{"linux/arm64", "linux/amd64"}, c.Targets[0].Platforms)
require.Equal(t, "linux/arm64", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("linux/arm64"), c.Targets[0].Args["v1"])
} }
func TestHCLMultiFileAttrs(t *testing.T) { func TestHCLMultiFileAttrs(t *testing.T) {
os.Unsetenv("FOO")
dt := []byte(` dt := []byte(`
variable "FOO" { variable "FOO" {
default = "abc" default = "abc"
@ -575,9 +619,9 @@ func TestHCLMultiFileAttrs(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "pre-def", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-def"), c.Targets[0].Args["v1"])
os.Setenv("FOO", "ghi") t.Setenv("FOO", "ghi")
c, err = ParseFiles([]File{ c, err = ParseFiles([]File{
{Data: dt, Name: "c1.hcl"}, {Data: dt, Name: "c1.hcl"},
@ -587,7 +631,7 @@ func TestHCLMultiFileAttrs(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "pre-ghi", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-ghi"), c.Targets[0].Args["v1"])
} }
func TestJSONAttributes(t *testing.T) { func TestJSONAttributes(t *testing.T) {
@ -598,7 +642,7 @@ func TestJSONAttributes(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "pre-abc-def", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-abc-def"), c.Targets[0].Args["v1"])
} }
func TestJSONFunctions(t *testing.T) { func TestJSONFunctions(t *testing.T) {
@ -623,7 +667,7 @@ func TestJSONFunctions(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "pre-<FOO-abc>", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("pre-<FOO-abc>"), c.Targets[0].Args["v1"])
} }
func TestHCLFunctionInAttr(t *testing.T) { func TestHCLFunctionInAttr(t *testing.T) {
@ -651,7 +695,7 @@ func TestHCLFunctionInAttr(t *testing.T) {
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "FOO <> [baz]", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("FOO <> [baz]"), c.Targets[0].Args["v1"])
} }
func TestHCLCombineCompose(t *testing.T) { func TestHCLCombineCompose(t *testing.T) {
@ -682,8 +726,8 @@ services:
require.Equal(t, 1, len(c.Targets)) require.Equal(t, 1, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "app") require.Equal(t, c.Targets[0].Name, "app")
require.Equal(t, "foo", c.Targets[0].Args["v1"]) require.Equal(t, ptrstr("foo"), c.Targets[0].Args["v1"])
require.Equal(t, "bar", c.Targets[0].Args["v2"]) require.Equal(t, ptrstr("bar"), c.Targets[0].Args["v2"])
require.Equal(t, "dir", *c.Targets[0].Context) require.Equal(t, "dir", *c.Targets[0].Context)
require.Equal(t, "Dockerfile-alternate", *c.Targets[0].Dockerfile) require.Equal(t, "Dockerfile-alternate", *c.Targets[0].Dockerfile)
} }
@ -828,10 +872,10 @@ target "two" {
require.Equal(t, 2, len(c.Targets)) require.Equal(t, 2, len(c.Targets))
require.Equal(t, c.Targets[0].Name, "one") require.Equal(t, c.Targets[0].Name, "one")
require.Equal(t, map[string]string{"a": "pre-ghi-jkl"}, c.Targets[0].Args) require.Equal(t, map[string]*string{"a": ptrstr("pre-ghi-jkl")}, c.Targets[0].Args)
require.Equal(t, c.Targets[1].Name, "two") require.Equal(t, c.Targets[1].Name, "two")
require.Equal(t, map[string]string{"b": "pre-jkl"}, c.Targets[1].Args) require.Equal(t, map[string]*string{"b": ptrstr("pre-jkl")}, c.Targets[1].Args)
} }
func TestEmptyVariableJSON(t *testing.T) { func TestEmptyVariableJSON(t *testing.T) {
@ -882,3 +926,12 @@ func TestVarUnsupportedType(t *testing.T) {
_, err := ParseFile(dt, "docker-bake.hcl") _, err := ParseFile(dt, "docker-bake.hcl")
require.Error(t, err) require.Error(t, err)
} }
func ptrstr(s interface{}) *string {
var n *string = nil
if reflect.ValueOf(s).Kind() == reflect.String {
ss := s.(string)
n = &ss
}
return n
}

@ -83,7 +83,7 @@ func appendJSONFuncCalls(exp hcl.Expression, m map[string]struct{}) error {
// hcl/v2/json/ast#stringVal // hcl/v2/json/ast#stringVal
val := src.FieldByName("Value") val := src.FieldByName("Value")
if val.IsZero() { if !val.IsValid() || val.IsZero() {
return nil return nil
} }
rng := src.FieldByName("SrcRange") rng := src.FieldByName("SrcRange")

@ -281,19 +281,16 @@ func (p *parser) resolveValue(name string) (err error) {
_, isVar := p.vars[name] _, isVar := p.vars[name]
if envv, ok := p.opt.LookupVar(name); ok && isVar { if envv, ok := p.opt.LookupVar(name); ok && isVar {
if vv.Type().Equals(cty.Bool) { switch {
case vv.Type().Equals(cty.Bool):
b, err := strconv.ParseBool(envv) b, err := strconv.ParseBool(envv)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to parse %s as bool", name) return errors.Wrapf(err, "failed to parse %s as bool", name)
} }
vv := cty.BoolVal(b) vv = cty.BoolVal(b)
v = &vv case vv.Type().Equals(cty.String), vv.Type().Equals(cty.DynamicPseudoType):
return nil vv = cty.StringVal(envv)
} else if vv.Type().Equals(cty.String) { case vv.Type().Equals(cty.Number):
vv := cty.StringVal(envv)
v = &vv
return nil
} else if vv.Type().Equals(cty.Number) {
n, err := strconv.ParseFloat(envv, 64) n, err := strconv.ParseFloat(envv, 64)
if err == nil && (math.IsNaN(n) || math.IsInf(n, 0)) { if err == nil && (math.IsNaN(n) || math.IsInf(n, 0)) {
err = errors.Errorf("invalid number value") err = errors.Errorf("invalid number value")
@ -301,10 +298,8 @@ func (p *parser) resolveValue(name string) (err error) {
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to parse %s as number", name) return errors.Wrapf(err, "failed to parse %s as number", name)
} }
vv := cty.NumberVal(big.NewFloat(n)) vv = cty.NumberVal(big.NewFloat(n))
v = &vv default:
return nil
} else {
// TODO: support lists with csv values // TODO: support lists with csv values
return errors.Errorf("unsupported type %s for variable %s", vv.Type().FriendlyName(), name) return errors.Errorf("unsupported type %s for variable %s", vv.Type().FriendlyName(), name)
} }

Loading…
Cancel
Save