mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 17:37:46 +08:00
Merge pull request #541 from tonistiigi/json-vars-attrs
bake: allow attributes in global scope
This commit is contained in:
commit
98d337af21
33
bake/hcl.go
33
bake/hcl.go
@ -133,6 +133,8 @@ type StaticConfig struct {
|
|||||||
Variables []*Variable `hcl:"variable,block"`
|
Variables []*Variable `hcl:"variable,block"`
|
||||||
Remain hcl.Body `hcl:",remain"`
|
Remain hcl.Body `hcl:",remain"`
|
||||||
|
|
||||||
|
attrs hcl.Attributes
|
||||||
|
|
||||||
defaults map[string]*hcl.Attribute
|
defaults map[string]*hcl.Attribute
|
||||||
env map[string]string
|
env map[string]string
|
||||||
values map[string]cty.Value
|
values map[string]cty.Value
|
||||||
@ -146,6 +148,9 @@ func mergeStaticConfig(scs []*StaticConfig) *StaticConfig {
|
|||||||
sc := scs[0]
|
sc := scs[0]
|
||||||
for _, s := range scs[1:] {
|
for _, s := range scs[1:] {
|
||||||
sc.Variables = append(sc.Variables, s.Variables...)
|
sc.Variables = append(sc.Variables, s.Variables...)
|
||||||
|
for k, v := range s.attrs {
|
||||||
|
sc.attrs[k] = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return sc
|
return sc
|
||||||
}
|
}
|
||||||
@ -169,6 +174,12 @@ func (sc *StaticConfig) Values(withEnv bool) (map[string]cty.Value, error) {
|
|||||||
sc.values = map[string]cty.Value{}
|
sc.values = map[string]cty.Value{}
|
||||||
sc.progress = map[string]struct{}{}
|
sc.progress = map[string]struct{}{}
|
||||||
|
|
||||||
|
for k := range sc.attrs {
|
||||||
|
if _, err := sc.resolveValue(k); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for k := range sc.defaults {
|
for k := range sc.defaults {
|
||||||
if _, err := sc.resolveValue(k); err != nil {
|
if _, err := sc.resolveValue(k); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -192,10 +203,12 @@ func (sc *StaticConfig) resolveValue(name string) (v *cty.Value, err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
def, ok := sc.defaults[name]
|
def, ok := sc.attrs[name]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.Errorf("undefined variable %q", name)
|
def, ok = sc.defaults[name]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Errorf("undefined variable %q", name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if def == nil {
|
if def == nil {
|
||||||
@ -233,7 +246,9 @@ func (sc *StaticConfig) resolveValue(name string) (v *cty.Value, err error) {
|
|||||||
return nil, diags
|
return nil, diags
|
||||||
}
|
}
|
||||||
|
|
||||||
if envv, ok := sc.env[name]; ok {
|
_, isVar := sc.defaults[name]
|
||||||
|
|
||||||
|
if envv, ok := sc.env[name]; ok && isVar {
|
||||||
if vv.Type().Equals(cty.Bool) {
|
if vv.Type().Equals(cty.Bool) {
|
||||||
b, err := strconv.ParseBool(envv)
|
b, err := strconv.ParseBool(envv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -302,6 +317,16 @@ func parseHCLFile(dt []byte, fn string) (f *hcl.File, _ *StaticConfig, err error
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attrs, diags := f.Body.JustAttributes()
|
||||||
|
if diags.HasErrors() {
|
||||||
|
for _, d := range diags {
|
||||||
|
if d.Detail != "Blocks are not allowed here." {
|
||||||
|
return nil, nil, diags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sc.attrs = attrs
|
||||||
|
|
||||||
return f, &sc, nil
|
return f, &sc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,3 +415,101 @@ func TestHCLVariableCycle(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Contains(t, err.Error(), "variable cycle not allowed")
|
require.Contains(t, err.Error(), "variable cycle not allowed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHCLAttrs(t *testing.T) {
|
||||||
|
dt := []byte(`
|
||||||
|
FOO="abc"
|
||||||
|
BAR="attr-${FOO}def"
|
||||||
|
target "app" {
|
||||||
|
args = {
|
||||||
|
"v1": BAR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
c, err := ParseFile(dt, "docker-bake.hcl")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(c.Targets))
|
||||||
|
require.Equal(t, c.Targets[0].Name, "app")
|
||||||
|
require.Equal(t, "attr-abcdef", c.Targets[0].Args["v1"])
|
||||||
|
|
||||||
|
// env does not apply if no variable
|
||||||
|
os.Setenv("FOO", "bar")
|
||||||
|
c, err = ParseFile(dt, "docker-bake.hcl")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(c.Targets))
|
||||||
|
require.Equal(t, c.Targets[0].Name, "app")
|
||||||
|
require.Equal(t, "attr-abcdef", c.Targets[0].Args["v1"])
|
||||||
|
// attr-multifile
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHCLAttrsCustomType(t *testing.T) {
|
||||||
|
dt := []byte(`
|
||||||
|
platforms=["linux/arm64", "linux/amd64"]
|
||||||
|
target "app" {
|
||||||
|
platforms = platforms
|
||||||
|
args = {
|
||||||
|
"v1": platforms[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
c, err := ParseFile(dt, "docker-bake.hcl")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(c.Targets))
|
||||||
|
require.Equal(t, c.Targets[0].Name, "app")
|
||||||
|
require.Equal(t, []string{"linux/arm64", "linux/amd64"}, c.Targets[0].Platforms)
|
||||||
|
require.Equal(t, "linux/arm64", c.Targets[0].Args["v1"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHCLMultiFileAttrs(t *testing.T) {
|
||||||
|
os.Unsetenv("FOO")
|
||||||
|
dt := []byte(`
|
||||||
|
variable "FOO" {
|
||||||
|
default = "abc"
|
||||||
|
}
|
||||||
|
target "app" {
|
||||||
|
args = {
|
||||||
|
v1 = "pre-${FOO}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
dt2 := []byte(`
|
||||||
|
FOO="def"
|
||||||
|
`)
|
||||||
|
|
||||||
|
c, err := parseFiles([]File{
|
||||||
|
{Data: dt, Name: "c1.hcl"},
|
||||||
|
{Data: dt2, Name: "c2.hcl"},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(c.Targets))
|
||||||
|
require.Equal(t, c.Targets[0].Name, "app")
|
||||||
|
require.Equal(t, "pre-def", c.Targets[0].Args["v1"])
|
||||||
|
|
||||||
|
os.Setenv("FOO", "ghi")
|
||||||
|
|
||||||
|
c, err = parseFiles([]File{
|
||||||
|
{Data: dt, Name: "c1.hcl"},
|
||||||
|
{Data: dt2, Name: "c2.hcl"},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(c.Targets))
|
||||||
|
require.Equal(t, c.Targets[0].Name, "app")
|
||||||
|
require.Equal(t, "pre-ghi", c.Targets[0].Args["v1"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONAttributes(t *testing.T) {
|
||||||
|
dt := []byte(`{"FOO": "abc", "variable": {"BAR": {"default": "def"}}, "target": { "app": { "args": {"v1": "pre-${FOO}-${BAR}"}} } }`)
|
||||||
|
|
||||||
|
c, err := ParseFile(dt, "docker-bake.json")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(c.Targets))
|
||||||
|
require.Equal(t, c.Targets[0].Name, "app")
|
||||||
|
require.Equal(t, "pre-abc-def", c.Targets[0].Args["v1"])
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user