mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-01 00:23:56 +08:00 
			
		
		
		
	bake: allow attributes in global scope
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
		
							
								
								
									
										33
									
								
								bake/hcl.go
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								bake/hcl.go
									
									
									
									
									
								
							| @@ -133,6 +133,8 @@ type StaticConfig struct { | ||||
| 	Variables []*Variable `hcl:"variable,block"` | ||||
| 	Remain    hcl.Body    `hcl:",remain"` | ||||
|  | ||||
| 	attrs hcl.Attributes | ||||
|  | ||||
| 	defaults map[string]*hcl.Attribute | ||||
| 	env      map[string]string | ||||
| 	values   map[string]cty.Value | ||||
| @@ -146,6 +148,9 @@ func mergeStaticConfig(scs []*StaticConfig) *StaticConfig { | ||||
| 	sc := scs[0] | ||||
| 	for _, s := range scs[1:] { | ||||
| 		sc.Variables = append(sc.Variables, s.Variables...) | ||||
| 		for k, v := range s.attrs { | ||||
| 			sc.attrs[k] = v | ||||
| 		} | ||||
| 	} | ||||
| 	return sc | ||||
| } | ||||
| @@ -169,6 +174,12 @@ func (sc *StaticConfig) Values(withEnv bool) (map[string]cty.Value, error) { | ||||
| 	sc.values = map[string]cty.Value{} | ||||
| 	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 { | ||||
| 		if _, err := sc.resolveValue(k); err != nil { | ||||
| 			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 { | ||||
| 		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 { | ||||
| @@ -233,7 +246,9 @@ func (sc *StaticConfig) resolveValue(name string) (v *cty.Value, err error) { | ||||
| 		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) { | ||||
| 			b, err := strconv.ParseBool(envv) | ||||
| 			if err != nil { | ||||
| @@ -302,6 +317,16 @@ func parseHCLFile(dt []byte, fn string) (f *hcl.File, _ *StaticConfig, err error | ||||
| 		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 | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -415,3 +415,90 @@ func TestHCLVariableCycle(t *testing.T) { | ||||
| 	require.Error(t, err) | ||||
| 	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"]) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Tonis Tiigi
					Tonis Tiigi