mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 01:53:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			1489 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1489 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package bake
 | 
						|
 | 
						|
import (
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/stretchr/testify/require"
 | 
						|
)
 | 
						|
 | 
						|
func TestHCLBasic(t *testing.T) {
 | 
						|
	t.Parallel()
 | 
						|
	dt := []byte(`
 | 
						|
		group "default" {
 | 
						|
			targets = ["db", "webapp"]
 | 
						|
		}
 | 
						|
 | 
						|
		target "db" {
 | 
						|
			context = "./db"
 | 
						|
			tags = ["docker.io/tonistiigi/db"]
 | 
						|
		}
 | 
						|
 | 
						|
		target "webapp" {
 | 
						|
			context = "./dir"
 | 
						|
			dockerfile = "Dockerfile-alternate"
 | 
						|
			args = {
 | 
						|
				buildno = "123"
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		target "cross" {
 | 
						|
			platforms = [
 | 
						|
				"linux/amd64",
 | 
						|
				"linux/arm64"
 | 
						|
			]
 | 
						|
		}
 | 
						|
 | 
						|
		target "webapp-plus" {
 | 
						|
			inherits = ["webapp", "cross"]
 | 
						|
			args = {
 | 
						|
				IAMCROSS = "true"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"db", "webapp"}, c.Groups[0].Targets)
 | 
						|
 | 
						|
	require.Equal(t, 4, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "db")
 | 
						|
	require.Equal(t, "./db", *c.Targets[0].Context)
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[1].Name, "webapp")
 | 
						|
	require.Equal(t, 1, len(c.Targets[1].Args))
 | 
						|
	require.Equal(t, ptrstr("123"), c.Targets[1].Args["buildno"])
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[2].Name, "cross")
 | 
						|
	require.Equal(t, 2, len(c.Targets[2].Platforms))
 | 
						|
	require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[2].Platforms)
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[3].Name, "webapp-plus")
 | 
						|
	require.Equal(t, 1, len(c.Targets[3].Args))
 | 
						|
	require.Equal(t, map[string]*string{"IAMCROSS": ptrstr("true")}, c.Targets[3].Args)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLBasicInJSON(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		{
 | 
						|
			"group": {
 | 
						|
				"default": {
 | 
						|
					"targets": ["db", "webapp"]
 | 
						|
				}
 | 
						|
			},
 | 
						|
			"target": {
 | 
						|
				"db": {
 | 
						|
					"context": "./db",
 | 
						|
					"tags": ["docker.io/tonistiigi/db"]
 | 
						|
				},
 | 
						|
				"webapp": {
 | 
						|
					"context": "./dir",
 | 
						|
					"dockerfile": "Dockerfile-alternate",
 | 
						|
					"args": {
 | 
						|
						"buildno": "123"
 | 
						|
					}
 | 
						|
				},
 | 
						|
				"cross": {
 | 
						|
					"platforms": [
 | 
						|
						"linux/amd64",
 | 
						|
						"linux/arm64"
 | 
						|
					]
 | 
						|
				},
 | 
						|
				"webapp-plus": {
 | 
						|
					"inherits": ["webapp", "cross"],
 | 
						|
					"args": {
 | 
						|
						"IAMCROSS": "true"
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.json")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"db", "webapp"}, c.Groups[0].Targets)
 | 
						|
 | 
						|
	require.Equal(t, 4, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "db")
 | 
						|
	require.Equal(t, "./db", *c.Targets[0].Context)
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[1].Name, "webapp")
 | 
						|
	require.Equal(t, 1, len(c.Targets[1].Args))
 | 
						|
	require.Equal(t, ptrstr("123"), c.Targets[1].Args["buildno"])
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[2].Name, "cross")
 | 
						|
	require.Equal(t, 2, len(c.Targets[2].Platforms))
 | 
						|
	require.Equal(t, []string{"linux/amd64", "linux/arm64"}, c.Targets[2].Platforms)
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[3].Name, "webapp-plus")
 | 
						|
	require.Equal(t, 1, len(c.Targets[3].Args))
 | 
						|
	require.Equal(t, map[string]*string{"IAMCROSS": ptrstr("true")}, c.Targets[3].Args)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLWithFunctions(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		group "default" {
 | 
						|
			targets = ["webapp"]
 | 
						|
		}
 | 
						|
 | 
						|
		target "webapp" {
 | 
						|
			args = {
 | 
						|
				buildno = "${add(123, 1)}"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"webapp"}, c.Groups[0].Targets)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "webapp")
 | 
						|
	require.Equal(t, ptrstr("124"), c.Targets[0].Args["buildno"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLWithUserDefinedFunctions(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		function "increment" {
 | 
						|
			params = [number]
 | 
						|
			result = number + 1
 | 
						|
		}
 | 
						|
 | 
						|
		group "default" {
 | 
						|
			targets = ["webapp"]
 | 
						|
		}
 | 
						|
 | 
						|
		target "webapp" {
 | 
						|
			args = {
 | 
						|
				buildno = "${increment(123)}"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"webapp"}, c.Groups[0].Targets)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "webapp")
 | 
						|
	require.Equal(t, ptrstr("124"), c.Targets[0].Args["buildno"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLWithVariables(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		variable "BUILD_NUMBER" {
 | 
						|
			default = "123"
 | 
						|
		}
 | 
						|
 | 
						|
		group "default" {
 | 
						|
			targets = ["webapp"]
 | 
						|
		}
 | 
						|
 | 
						|
		target "webapp" {
 | 
						|
			args = {
 | 
						|
				buildno = "${BUILD_NUMBER}"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"webapp"}, c.Groups[0].Targets)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "webapp")
 | 
						|
	require.Equal(t, ptrstr("123"), c.Targets[0].Args["buildno"])
 | 
						|
 | 
						|
	t.Setenv("BUILD_NUMBER", "456")
 | 
						|
 | 
						|
	c, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"webapp"}, c.Groups[0].Targets)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "webapp")
 | 
						|
	require.Equal(t, ptrstr("456"), c.Targets[0].Args["buildno"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLWithVariablesInFunctions(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		variable "REPO" {
 | 
						|
			default = "user/repo"
 | 
						|
		}
 | 
						|
		function "tag" {
 | 
						|
			params = [tag]
 | 
						|
			result = ["${REPO}:${tag}"]
 | 
						|
		}
 | 
						|
 | 
						|
		target "webapp" {
 | 
						|
			tags = tag("v1")
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	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, "webapp")
 | 
						|
	require.Equal(t, []string{"user/repo:v1"}, c.Targets[0].Tags)
 | 
						|
 | 
						|
	t.Setenv("REPO", "docker/buildx")
 | 
						|
 | 
						|
	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, "webapp")
 | 
						|
	require.Equal(t, []string{"docker/buildx:v1"}, c.Targets[0].Tags)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMultiFileSharedVariables(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		variable "FOO" {
 | 
						|
			default = "abc"
 | 
						|
		}
 | 
						|
		target "app" {
 | 
						|
			args = {
 | 
						|
				v1 = "pre-${FOO}"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	dt2 := []byte(`
 | 
						|
		target "app" {
 | 
						|
			args = {
 | 
						|
				v2 = "${FOO}-post"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	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, ptrstr("pre-abc"), c.Targets[0].Args["v1"])
 | 
						|
	require.Equal(t, ptrstr("abc-post"), c.Targets[0].Args["v2"])
 | 
						|
 | 
						|
	t.Setenv("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, ptrstr("pre-def"), c.Targets[0].Args["v1"])
 | 
						|
	require.Equal(t, ptrstr("def-post"), c.Targets[0].Args["v2"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLVarsWithVars(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		variable "FOO" {
 | 
						|
			default = upper("${BASE}def")
 | 
						|
		}
 | 
						|
		variable "BAR" {
 | 
						|
			default = "-${FOO}-"
 | 
						|
		}
 | 
						|
		target "app" {
 | 
						|
			args = {
 | 
						|
				v1 = "pre-${BAR}"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	dt2 := []byte(`
 | 
						|
		variable "BASE" {
 | 
						|
			default = "abc"
 | 
						|
		}
 | 
						|
		target "app" {
 | 
						|
			args = {
 | 
						|
				v2 = "${FOO}-post"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	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, ptrstr("pre--ABCDEF-"), c.Targets[0].Args["v1"])
 | 
						|
	require.Equal(t, ptrstr("ABCDEF-post"), c.Targets[0].Args["v2"])
 | 
						|
 | 
						|
	t.Setenv("BASE", "new")
 | 
						|
 | 
						|
	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, ptrstr("pre--NEWDEF-"), c.Targets[0].Args["v1"])
 | 
						|
	require.Equal(t, ptrstr("NEWDEF-post"), c.Targets[0].Args["v2"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLTypedVariables(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		variable "FOO" {
 | 
						|
			default = 3
 | 
						|
		}
 | 
						|
		variable "IS_FOO" {
 | 
						|
			default = true
 | 
						|
		}
 | 
						|
		target "app" {
 | 
						|
			args = {
 | 
						|
				v1 = FOO > 5 ? "higher" : "lower" 
 | 
						|
				v2 = IS_FOO ? "yes" : "no"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	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, ptrstr("lower"), c.Targets[0].Args["v1"])
 | 
						|
	require.Equal(t, ptrstr("yes"), c.Targets[0].Args["v2"])
 | 
						|
 | 
						|
	t.Setenv("FOO", "5.1")
 | 
						|
	t.Setenv("IS_FOO", "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, ptrstr("higher"), c.Targets[0].Args["v1"])
 | 
						|
	require.Equal(t, ptrstr("no"), c.Targets[0].Args["v2"])
 | 
						|
 | 
						|
	t.Setenv("FOO", "NaN")
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
	require.Contains(t, err.Error(), "failed to parse FOO as number")
 | 
						|
 | 
						|
	t.Setenv("FOO", "0")
 | 
						|
	t.Setenv("IS_FOO", "maybe")
 | 
						|
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
	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) {
 | 
						|
	dt := []byte(`
 | 
						|
		variable "FOO" {
 | 
						|
			default = BAR
 | 
						|
		}
 | 
						|
		variable "FOO2" {
 | 
						|
			default = FOO
 | 
						|
		}
 | 
						|
		variable "BAR" {
 | 
						|
			default = FOO
 | 
						|
		}
 | 
						|
		target "app" {}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	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, ptrstr("attr-abcdef"), c.Targets[0].Args["v1"])
 | 
						|
 | 
						|
	// env does not apply if no variable
 | 
						|
	t.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, ptrstr("attr-abcdef"), c.Targets[0].Args["v1"])
 | 
						|
	// attr-multifile
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLTargetAttrs(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "foo" {
 | 
						|
			dockerfile = "xxx"
 | 
						|
			context = target.bar.context
 | 
						|
			target = target.foo.dockerfile
 | 
						|
		}
 | 
						|
		
 | 
						|
		target "bar" {
 | 
						|
			dockerfile = target.foo.dockerfile
 | 
						|
			context = "yyy"
 | 
						|
			target = target.bar.context
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "foo", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "bar", c.Targets[1].Name)
 | 
						|
 | 
						|
	require.Equal(t, "xxx", *c.Targets[0].Dockerfile)
 | 
						|
	require.Equal(t, "yyy", *c.Targets[0].Context)
 | 
						|
	require.Equal(t, "xxx", *c.Targets[0].Target)
 | 
						|
 | 
						|
	require.Equal(t, "xxx", *c.Targets[1].Dockerfile)
 | 
						|
	require.Equal(t, "yyy", *c.Targets[1].Context)
 | 
						|
	require.Equal(t, "yyy", *c.Targets[1].Target)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLTargetGlobal(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "foo" {
 | 
						|
			dockerfile = "x"
 | 
						|
		}
 | 
						|
		x = target.foo.dockerfile
 | 
						|
		y = x
 | 
						|
		target "bar" {
 | 
						|
			dockerfile = y
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "foo", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "bar", c.Targets[1].Name)
 | 
						|
 | 
						|
	require.Equal(t, "x", *c.Targets[0].Dockerfile)
 | 
						|
	require.Equal(t, "x", *c.Targets[1].Dockerfile)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLTargetAttrName(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "foo" {
 | 
						|
			dockerfile = target.foo.name
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, "foo", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "foo", *c.Targets[0].Dockerfile)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLTargetAttrEmptyChain(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "foo" {
 | 
						|
			# dockerfile = Dockerfile
 | 
						|
			context = target.foo.dockerfile
 | 
						|
			target = target.foo.context
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, "foo", c.Targets[0].Name)
 | 
						|
	require.Nil(t, c.Targets[0].Dockerfile)
 | 
						|
	require.Nil(t, c.Targets[0].Context)
 | 
						|
	require.Nil(t, c.Targets[0].Target)
 | 
						|
}
 | 
						|
 | 
						|
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, ptrstr("linux/arm64"), c.Targets[0].Args["v1"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMultiFileAttrs(t *testing.T) {
 | 
						|
	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"},
 | 
						|
	}, nil)
 | 
						|
	require.NoError(t, err)
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "app")
 | 
						|
	require.Equal(t, ptrstr("pre-def"), c.Targets[0].Args["v1"])
 | 
						|
 | 
						|
	t.Setenv("FOO", "ghi")
 | 
						|
 | 
						|
	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, 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" {
 | 
						|
			dockerfile = "x"
 | 
						|
		}
 | 
						|
		target "app" {
 | 
						|
			dockerfile = "y"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, "app", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "y", *c.Targets[0].Dockerfile)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLRenameTarget(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "abc" {
 | 
						|
			name = "xyz"
 | 
						|
			dockerfile = "foo"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.ErrorContains(t, err, "requires matrix")
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLRenameGroup(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		group "foo" {
 | 
						|
			name = "bar"
 | 
						|
			targets = ["x", "y"]
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.ErrorContains(t, err, "not supported")
 | 
						|
 | 
						|
	dt = []byte(`
 | 
						|
		group "foo" {
 | 
						|
			matrix = {
 | 
						|
				name = ["x", "y"]
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.ErrorContains(t, err, "not supported")
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLRenameTargetAttrs(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "abc" {
 | 
						|
			name = "xyz"
 | 
						|
			matrix = {}
 | 
						|
			dockerfile = "foo"
 | 
						|
		}
 | 
						|
 | 
						|
		target "def" {
 | 
						|
			dockerfile = target.xyz.dockerfile
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "xyz", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "foo", *c.Targets[0].Dockerfile)
 | 
						|
	require.Equal(t, "def", c.Targets[1].Name)
 | 
						|
	require.Equal(t, "foo", *c.Targets[1].Dockerfile)
 | 
						|
 | 
						|
	dt = []byte(`
 | 
						|
		target "def" {
 | 
						|
			dockerfile = target.xyz.dockerfile
 | 
						|
		}
 | 
						|
 | 
						|
		target "abc" {
 | 
						|
			name = "xyz"
 | 
						|
			matrix = {}
 | 
						|
			dockerfile = "foo"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "def", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "foo", *c.Targets[0].Dockerfile)
 | 
						|
	require.Equal(t, "xyz", c.Targets[1].Name)
 | 
						|
	require.Equal(t, "foo", *c.Targets[1].Dockerfile)
 | 
						|
 | 
						|
	dt = []byte(`
 | 
						|
		target "abc" {
 | 
						|
			name = "xyz"
 | 
						|
			matrix  = {}
 | 
						|
			dockerfile = "foo"
 | 
						|
		}
 | 
						|
 | 
						|
		target "def" {
 | 
						|
			dockerfile = target.abc.dockerfile
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.ErrorContains(t, err, "abc")
 | 
						|
 | 
						|
	dt = []byte(`
 | 
						|
		target "def" {
 | 
						|
			dockerfile = target.abc.dockerfile
 | 
						|
		}
 | 
						|
 | 
						|
		target "abc" {
 | 
						|
			name = "xyz"
 | 
						|
			matrix = {}
 | 
						|
			dockerfile = "foo"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.ErrorContains(t, err, "abc")
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLRenameSplit(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "x" {
 | 
						|
			name = "y"
 | 
						|
			matrix = {}
 | 
						|
			dockerfile = "foo"
 | 
						|
		}
 | 
						|
 | 
						|
		target "x" {
 | 
						|
			name = "z"
 | 
						|
			matrix = {}
 | 
						|
			dockerfile = "bar"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "y", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "foo", *c.Targets[0].Dockerfile)
 | 
						|
	require.Equal(t, "z", c.Targets[1].Name)
 | 
						|
	require.Equal(t, "bar", *c.Targets[1].Dockerfile)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "x", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"y", "z"}, c.Groups[0].Targets)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLRenameMultiFile(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "foo" {
 | 
						|
			name = "bar"
 | 
						|
			matrix = {}
 | 
						|
			dockerfile = "x"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	dt2 := []byte(`
 | 
						|
		target "foo" {
 | 
						|
			context = "y"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	dt3 := []byte(`
 | 
						|
		target "bar" {
 | 
						|
			target = "z"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFiles([]File{
 | 
						|
		{Data: dt, Name: "c1.hcl"},
 | 
						|
		{Data: dt2, Name: "c2.hcl"},
 | 
						|
		{Data: dt3, Name: "c3.hcl"},
 | 
						|
	}, nil)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[0].Name, "bar")
 | 
						|
	require.Equal(t, *c.Targets[0].Dockerfile, "x")
 | 
						|
	require.Equal(t, *c.Targets[0].Target, "z")
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[1].Name, "foo")
 | 
						|
	require.Equal(t, *c.Targets[1].Context, "y")
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixBasic(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "default" {
 | 
						|
			matrix = {
 | 
						|
				foo = ["x", "y"]
 | 
						|
			}
 | 
						|
			name = foo
 | 
						|
			dockerfile = "${foo}.Dockerfile"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "x")
 | 
						|
	require.Equal(t, c.Targets[1].Name, "y")
 | 
						|
	require.Equal(t, *c.Targets[0].Dockerfile, "x.Dockerfile")
 | 
						|
	require.Equal(t, *c.Targets[1].Dockerfile, "y.Dockerfile")
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"x", "y"}, c.Groups[0].Targets)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixMultipleKeys(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "default" {
 | 
						|
			matrix = {
 | 
						|
				foo = ["a"]
 | 
						|
				bar = ["b", "c"]
 | 
						|
				baz = ["d", "e", "f"]
 | 
						|
			}
 | 
						|
			name = "${foo}-${bar}-${baz}"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 6, len(c.Targets))
 | 
						|
	names := make([]string, len(c.Targets))
 | 
						|
	for i, t := range c.Targets {
 | 
						|
		names[i] = t.Name
 | 
						|
	}
 | 
						|
	require.ElementsMatch(t, []string{"a-b-d", "a-b-e", "a-b-f", "a-c-d", "a-c-e", "a-c-f"}, names)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.ElementsMatch(t, []string{"a-b-d", "a-b-e", "a-b-f", "a-c-d", "a-c-e", "a-c-f"}, c.Groups[0].Targets)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixLists(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
	target "foo" {
 | 
						|
		matrix = {
 | 
						|
			aa = [["aa", "bb"], ["cc", "dd"]]
 | 
						|
		}
 | 
						|
		name = aa[0]
 | 
						|
		args = {
 | 
						|
			target = "val${aa[1]}"
 | 
						|
		}
 | 
						|
	}
 | 
						|
	`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "aa", c.Targets[0].Name)
 | 
						|
	require.Equal(t, ptrstr("valbb"), c.Targets[0].Args["target"])
 | 
						|
	require.Equal(t, "cc", c.Targets[1].Name)
 | 
						|
	require.Equal(t, ptrstr("valdd"), c.Targets[1].Args["target"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixMaps(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
	target "foo" {
 | 
						|
		matrix = {
 | 
						|
			aa = [
 | 
						|
				{
 | 
						|
					foo = "aa"
 | 
						|
					bar = "bb"
 | 
						|
				},
 | 
						|
				{
 | 
						|
					foo = "cc"
 | 
						|
					bar = "dd"
 | 
						|
				}
 | 
						|
			]
 | 
						|
		}
 | 
						|
		name = aa.foo
 | 
						|
		args = {
 | 
						|
			target = "val${aa.bar}"
 | 
						|
		}
 | 
						|
	}
 | 
						|
	`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "aa")
 | 
						|
	require.Equal(t, c.Targets[0].Args["target"], ptrstr("valbb"))
 | 
						|
	require.Equal(t, c.Targets[1].Name, "cc")
 | 
						|
	require.Equal(t, c.Targets[1].Args["target"], ptrstr("valdd"))
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixMultipleTargets(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "x" {
 | 
						|
			matrix = {
 | 
						|
				foo = ["a", "b"]
 | 
						|
			}
 | 
						|
			name = foo
 | 
						|
		}
 | 
						|
		target "y" {
 | 
						|
			matrix = {
 | 
						|
				bar = ["c", "d"]
 | 
						|
			}
 | 
						|
			name = bar
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 4, len(c.Targets))
 | 
						|
	names := make([]string, len(c.Targets))
 | 
						|
	for i, t := range c.Targets {
 | 
						|
		names[i] = t.Name
 | 
						|
	}
 | 
						|
	require.ElementsMatch(t, []string{"a", "b", "c", "d"}, names)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Groups))
 | 
						|
	names = make([]string, len(c.Groups))
 | 
						|
	for i, c := range c.Groups {
 | 
						|
		names[i] = c.Name
 | 
						|
	}
 | 
						|
	require.ElementsMatch(t, []string{"x", "y"}, names)
 | 
						|
 | 
						|
	for _, g := range c.Groups {
 | 
						|
		switch g.Name {
 | 
						|
		case "x":
 | 
						|
			require.Equal(t, []string{"a", "b"}, g.Targets)
 | 
						|
		case "y":
 | 
						|
			require.Equal(t, []string{"c", "d"}, g.Targets)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixDuplicateNames(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "default" {
 | 
						|
			matrix = {
 | 
						|
				foo = ["a", "b"]
 | 
						|
			}
 | 
						|
			name = "c"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixArgs(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		a = 1
 | 
						|
		variable "b" {
 | 
						|
			default = 2
 | 
						|
		}
 | 
						|
		target "default" {
 | 
						|
			matrix = {
 | 
						|
				foo = [a, b]
 | 
						|
			}
 | 
						|
			name = foo
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "1", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "2", c.Targets[1].Name)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixArgsOverride(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
	variable "ABC" {
 | 
						|
		default = "def"
 | 
						|
	}
 | 
						|
 | 
						|
	target "bar" {
 | 
						|
		matrix = {
 | 
						|
			aa = split(",", ABC)
 | 
						|
		}
 | 
						|
		name = "bar-${aa}"
 | 
						|
		args = {
 | 
						|
			foo = aa
 | 
						|
		}
 | 
						|
	}
 | 
						|
	`)
 | 
						|
 | 
						|
	c, err := ParseFiles([]File{
 | 
						|
		{Data: dt, Name: "docker-bake.hcl"},
 | 
						|
	}, map[string]string{"ABC": "11,22,33"})
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 3, len(c.Targets))
 | 
						|
	require.Equal(t, "bar-11", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "bar-22", c.Targets[1].Name)
 | 
						|
	require.Equal(t, "bar-33", c.Targets[2].Name)
 | 
						|
 | 
						|
	require.Equal(t, ptrstr("11"), c.Targets[0].Args["foo"])
 | 
						|
	require.Equal(t, ptrstr("22"), c.Targets[1].Args["foo"])
 | 
						|
	require.Equal(t, ptrstr("33"), c.Targets[2].Args["foo"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixBadTypes(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "default" {
 | 
						|
			matrix = "test"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	_, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
 | 
						|
	dt = []byte(`
 | 
						|
		target "default" {
 | 
						|
			matrix = ["test"]
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
 | 
						|
	dt = []byte(`
 | 
						|
		target "default" {
 | 
						|
			matrix = {
 | 
						|
				["a"] = ["b"]
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
 | 
						|
	dt = []byte(`
 | 
						|
		target "default" {
 | 
						|
			matrix = {
 | 
						|
				1 = 2
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
 | 
						|
	dt = []byte(`
 | 
						|
		target "default" {
 | 
						|
			matrix = {
 | 
						|
				a = "b"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	_, err = ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLMatrixWithGlobalTarget(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "x" {
 | 
						|
			tags = ["a", "b"]
 | 
						|
		}
 | 
						|
		
 | 
						|
		target "default" {
 | 
						|
			tags = target.x.tags
 | 
						|
			matrix = {
 | 
						|
				dummy = [""]
 | 
						|
			}
 | 
						|
		}
 | 
						|
	`)
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "x", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "default", c.Targets[1].Name)
 | 
						|
	require.Equal(t, []string{"a", "b"}, c.Targets[1].Tags)
 | 
						|
}
 | 
						|
 | 
						|
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, ptrstr("pre-abc-def"), c.Targets[0].Args["v1"])
 | 
						|
}
 | 
						|
 | 
						|
func TestJSONFunctions(t *testing.T) {
 | 
						|
	dt := []byte(`{
 | 
						|
	"FOO": "abc",
 | 
						|
	"function": {
 | 
						|
		"myfunc": {
 | 
						|
			"params": ["inp"],
 | 
						|
			"result": "<${upper(inp)}-${FOO}>"
 | 
						|
		}
 | 
						|
	},
 | 
						|
	"target": {
 | 
						|
		"app": {
 | 
						|
			"args": {
 | 
						|
				"v1": "pre-${myfunc(\"foo\")}"
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}}`)
 | 
						|
 | 
						|
	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, ptrstr("pre-<FOO-abc>"), c.Targets[0].Args["v1"])
 | 
						|
}
 | 
						|
 | 
						|
func TestJSONInvalidFunctions(t *testing.T) {
 | 
						|
	dt := []byte(`{
 | 
						|
	"target": {
 | 
						|
		"app": {
 | 
						|
			"args": {
 | 
						|
				"v1": "myfunc(\"foo\")"
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}}`)
 | 
						|
 | 
						|
	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, ptrstr(`myfunc("foo")`), c.Targets[0].Args["v1"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLFunctionInAttr(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
	function "brace" {
 | 
						|
		params = [inp]
 | 
						|
		result = "[${inp}]"
 | 
						|
	}
 | 
						|
	function "myupper" {
 | 
						|
		params = [val]
 | 
						|
		result = "${upper(val)} <> ${brace(v2)}"
 | 
						|
	}
 | 
						|
 | 
						|
		v1=myupper("foo")
 | 
						|
		v2=lower("BAZ")
 | 
						|
		target "app" {
 | 
						|
			args = {
 | 
						|
				"v1": v1
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	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, ptrstr("FOO <> [baz]"), c.Targets[0].Args["v1"])
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLCombineCompose(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "app" {
 | 
						|
			context = "dir"
 | 
						|
			args = {
 | 
						|
				v1 = "foo"
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
	dt2 := []byte(`
 | 
						|
version: "3"
 | 
						|
 | 
						|
services:
 | 
						|
  app:
 | 
						|
    build:
 | 
						|
      dockerfile: Dockerfile-alternate
 | 
						|
      args:
 | 
						|
        v2: "bar"
 | 
						|
`)
 | 
						|
 | 
						|
	c, err := ParseFiles([]File{
 | 
						|
		{Data: dt, Name: "c1.hcl"},
 | 
						|
		{Data: dt2, Name: "c2.yml"},
 | 
						|
	}, nil)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "app")
 | 
						|
	require.Equal(t, ptrstr("foo"), c.Targets[0].Args["v1"])
 | 
						|
	require.Equal(t, ptrstr("bar"), c.Targets[0].Args["v2"])
 | 
						|
	require.Equal(t, "dir", *c.Targets[0].Context)
 | 
						|
	require.Equal(t, "Dockerfile-alternate", *c.Targets[0].Dockerfile)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLBuiltinVars(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		target "app" {
 | 
						|
			context = BAKE_CMD_CONTEXT
 | 
						|
			dockerfile = "test"
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFiles([]File{
 | 
						|
		{Data: dt, Name: "c1.hcl"},
 | 
						|
	}, map[string]string{
 | 
						|
		"BAKE_CMD_CONTEXT": "foo",
 | 
						|
	})
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Targets))
 | 
						|
	require.Equal(t, c.Targets[0].Name, "app")
 | 
						|
	require.Equal(t, "foo", *c.Targets[0].Context)
 | 
						|
	require.Equal(t, "test", *c.Targets[0].Dockerfile)
 | 
						|
}
 | 
						|
 | 
						|
func TestCombineHCLAndJSONTargets(t *testing.T) {
 | 
						|
	c, err := ParseFiles([]File{
 | 
						|
		{
 | 
						|
			Name: "docker-bake.hcl",
 | 
						|
			Data: []byte(`
 | 
						|
group "default" {
 | 
						|
  targets = ["a"]
 | 
						|
}
 | 
						|
 | 
						|
target "metadata-a" {}
 | 
						|
target "metadata-b" {}
 | 
						|
 | 
						|
target "a" {
 | 
						|
  inherits = ["metadata-a"]
 | 
						|
  context = "."
 | 
						|
  target = "a"
 | 
						|
}
 | 
						|
 | 
						|
target "b" {
 | 
						|
  inherits = ["metadata-b"]
 | 
						|
  context = "."
 | 
						|
  target = "b"
 | 
						|
}`),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name: "metadata-a.json",
 | 
						|
			Data: []byte(`
 | 
						|
{
 | 
						|
  "target": [{
 | 
						|
    "metadata-a": [{
 | 
						|
      "tags": [
 | 
						|
        "app/a:1.0.0",
 | 
						|
        "app/a:latest"
 | 
						|
      ]
 | 
						|
    }]
 | 
						|
  }]
 | 
						|
}`),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name: "metadata-b.json",
 | 
						|
			Data: []byte(`
 | 
						|
{
 | 
						|
  "target": [{
 | 
						|
    "metadata-b": [{
 | 
						|
      "tags": [
 | 
						|
        "app/b:1.0.0",
 | 
						|
        "app/b:latest"
 | 
						|
      ]
 | 
						|
    }]
 | 
						|
  }]
 | 
						|
}`),
 | 
						|
		},
 | 
						|
	}, nil)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"a"}, c.Groups[0].Targets)
 | 
						|
 | 
						|
	require.Equal(t, 4, len(c.Targets))
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[0].Name, "metadata-a")
 | 
						|
	require.Equal(t, []string{"app/a:1.0.0", "app/a:latest"}, c.Targets[0].Tags)
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[1].Name, "metadata-b")
 | 
						|
	require.Equal(t, []string{"app/b:1.0.0", "app/b:latest"}, c.Targets[1].Tags)
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[2].Name, "a")
 | 
						|
	require.Equal(t, ".", *c.Targets[2].Context)
 | 
						|
	require.Equal(t, "a", *c.Targets[2].Target)
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[3].Name, "b")
 | 
						|
	require.Equal(t, ".", *c.Targets[3].Context)
 | 
						|
	require.Equal(t, "b", *c.Targets[3].Target)
 | 
						|
}
 | 
						|
 | 
						|
func TestCombineHCLAndJSONVars(t *testing.T) {
 | 
						|
	c, err := ParseFiles([]File{
 | 
						|
		{
 | 
						|
			Name: "docker-bake.hcl",
 | 
						|
			Data: []byte(`
 | 
						|
variable "ABC" {
 | 
						|
  default = "foo"
 | 
						|
}
 | 
						|
variable "DEF" {
 | 
						|
  default = ""
 | 
						|
}
 | 
						|
group "default" {
 | 
						|
  targets = ["one"]
 | 
						|
}
 | 
						|
target "one" {
 | 
						|
  args = {
 | 
						|
    a = "pre-${ABC}"
 | 
						|
  }
 | 
						|
}
 | 
						|
target "two" {
 | 
						|
  args = {
 | 
						|
    b = "pre-${DEF}"
 | 
						|
  }
 | 
						|
}`),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name: "foo.json",
 | 
						|
			Data: []byte(`{"variable": {"DEF": {"default": "bar"}}, "target": { "one": { "args": {"a": "pre-${ABC}-${DEF}"}} } }`),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name: "bar.json",
 | 
						|
			Data: []byte(`{"ABC": "ghi", "DEF": "jkl"}`),
 | 
						|
		},
 | 
						|
	}, nil)
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 1, len(c.Groups))
 | 
						|
	require.Equal(t, "default", c.Groups[0].Name)
 | 
						|
	require.Equal(t, []string{"one"}, c.Groups[0].Targets)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
 | 
						|
	require.Equal(t, c.Targets[0].Name, "one")
 | 
						|
	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, map[string]*string{"b": ptrstr("pre-jkl")}, c.Targets[1].Args)
 | 
						|
}
 | 
						|
 | 
						|
func TestEmptyVariableJSON(t *testing.T) {
 | 
						|
	dt := []byte(`{
 | 
						|
	  "variable": {
 | 
						|
	    "VAR": {}
 | 
						|
	  }
 | 
						|
	}`)
 | 
						|
	_, err := ParseFile(dt, "docker-bake.json")
 | 
						|
	require.NoError(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestFunctionNoParams(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		function "foo" {
 | 
						|
			result = "bar"
 | 
						|
		}
 | 
						|
		target "foo_target" {
 | 
						|
			args = {
 | 
						|
				test = foo()
 | 
						|
			}
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestFunctionNoResult(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		function "foo" {
 | 
						|
			params = ["a"]
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	_, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestVarUnsupportedType(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		variable "FOO" {
 | 
						|
			default = []
 | 
						|
		}
 | 
						|
		target "default" {}`)
 | 
						|
 | 
						|
	t.Setenv("FOO", "bar")
 | 
						|
	_, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.Error(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestHCLIndexOfFunc(t *testing.T) {
 | 
						|
	dt := []byte(`
 | 
						|
		variable "APP_VERSIONS" {
 | 
						|
		  default = [
 | 
						|
			"1.42.4",
 | 
						|
			"1.42.3"
 | 
						|
		  ]
 | 
						|
		}
 | 
						|
		target "default" {
 | 
						|
			args = {
 | 
						|
				APP_VERSION = app_version
 | 
						|
			}
 | 
						|
			matrix = {
 | 
						|
				app_version = APP_VERSIONS
 | 
						|
			}
 | 
						|
			name="app-${replace(app_version, ".", "-")}"
 | 
						|
			tags = [
 | 
						|
				"app:${app_version}",
 | 
						|
				indexof(APP_VERSIONS, app_version) == 0 ? "app:latest" : "",
 | 
						|
			]
 | 
						|
		}
 | 
						|
		`)
 | 
						|
 | 
						|
	c, err := ParseFile(dt, "docker-bake.hcl")
 | 
						|
	require.NoError(t, err)
 | 
						|
 | 
						|
	require.Equal(t, 2, len(c.Targets))
 | 
						|
	require.Equal(t, "app-1-42-4", c.Targets[0].Name)
 | 
						|
	require.Equal(t, "app:latest", c.Targets[0].Tags[1])
 | 
						|
	require.Equal(t, "app-1-42-3", c.Targets[1].Name)
 | 
						|
	require.Empty(t, c.Targets[1].Tags[1])
 | 
						|
}
 | 
						|
 | 
						|
func ptrstr(s interface{}) *string {
 | 
						|
	var n *string
 | 
						|
	if reflect.ValueOf(s).Kind() == reflect.String {
 | 
						|
		ss := s.(string)
 | 
						|
		n = &ss
 | 
						|
	}
 | 
						|
	return n
 | 
						|
}
 |