From fafb234e95d8e701bf56abb60e2f008bd1d43a8b Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Thu, 7 Apr 2022 01:45:50 +0200 Subject: [PATCH] bake: set attribute even if diagnosed as duplicated Signed-off-by: CrazyMax --- bake/hcl_test.go | 23 +++++++++++++++++ bake/hclparser/hclparser.go | 51 +++++++++++++++++++++++++++---------- bake/hclparser/merged.go | 1 - 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/bake/hcl_test.go b/bake/hcl_test.go index dedde357..005b4785 100644 --- a/bake/hcl_test.go +++ b/bake/hcl_test.go @@ -634,6 +634,29 @@ func TestHCLMultiFileAttrs(t *testing.T) { require.Equal(t, ptrstr("pre-ghi"), c.Targets[0].Args["v1"]) } +func TestHCLMultiFileGlobalAttrs(t *testing.T) { + dt := []byte(` + FOO = "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"}, + }, nil) + 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"]) +} + func TestHCLDuplicateTarget(t *testing.T) { dt := []byte(` target "app" { diff --git a/bake/hclparser/hclparser.go b/bake/hclparser/hclparser.go index f29c4a8a..702547c9 100644 --- a/bake/hclparser/hclparser.go +++ b/bake/hclparser/hclparser.go @@ -613,7 +613,7 @@ func Parse(b hcl.Body, opt Opt, val interface{}) (map[string]map[string][]string attrs, diags := b.JustAttributes() if diags.HasErrors() { - if d := removeAttributesDiags(diags, reserved, p.vars); len(d) > 0 { + if d := removeAttributesDiags(diags, reserved, p.vars, attrs); len(d) > 0 { return nil, d } } @@ -854,27 +854,50 @@ func getNameIndex(v reflect.Value) (int, bool) { return 0, false } -func removeAttributesDiags(diags hcl.Diagnostics, reserved map[string]struct{}, vars map[string]*variable) hcl.Diagnostics { +func removeAttributesDiags(diags hcl.Diagnostics, reserved map[string]struct{}, vars map[string]*variable, attrs hcl.Attributes) hcl.Diagnostics { var fdiags hcl.Diagnostics + + alreadySetArg := func(detail string, keys []string) bool { + for _, k := range keys { + if strings.HasPrefix(detail, fmt.Sprintf(`Argument %q was already set at `, k)) { + return true + } + } + return false + } + + var reservedKeys []string + for k := range reserved { + reservedKeys = append(reservedKeys, k) + } + var varsKeys []string + for k := range vars { + varsKeys = append(varsKeys, k) + } + var attrsKeys []string + for k := range attrs { + attrsKeys = append(attrsKeys, k) + } + for _, d := range diags { if fout := func(d *hcl.Diagnostic) bool { // https://github.com/docker/buildx/pull/541 if d.Detail == "Blocks are not allowed here." { return true } - for r := range reserved { - // JSON body objects don't handle repeated blocks like HCL but - // reserved name attributes should be allowed when multi bodies are merged. - // https://github.com/hashicorp/hcl/blob/main/json/spec.md#blocks - if strings.HasPrefix(d.Detail, fmt.Sprintf(`Argument "%s" was already set at `, r)) { - return true - } + // JSON body objects don't handle repeated blocks like HCL but + // reserved name attributes should be allowed when multi bodies are merged. + // https://github.com/hashicorp/hcl/blob/main/json/spec.md#blocks + if alreadySetArg(d.Detail, reservedKeys) { + return true } - for v := range vars { - // Do the same for global variables - if strings.HasPrefix(d.Detail, fmt.Sprintf(`Argument "%s" was already set at `, v)) { - return true - } + // Do the same for global variables + if alreadySetArg(d.Detail, varsKeys) { + return true + } + // Do the same for attributes + if alreadySetArg(d.Detail, attrsKeys) { + return true } return false }(d); !fout { diff --git a/bake/hclparser/merged.go b/bake/hclparser/merged.go index 004b0a63..0ff6ed51 100644 --- a/bake/hclparser/merged.go +++ b/bake/hclparser/merged.go @@ -123,7 +123,6 @@ func (mb mergedBodies) JustAttributes() (hcl.Attributes, hcl.Diagnostics) { ), Subject: &attr.NameRange, }) - continue } attrs[name] = attr