mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 09:17:49 +08:00
bake: support null arg value
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
parent
e21f56e801
commit
df4957307f
55
bake/bake.go
55
bake/bake.go
@ -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) {
|
||||||
|
147
bake/hcl_test.go
147
bake/hcl_test.go
@ -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…
x
Reference in New Issue
Block a user