Skip to content

Commit

Permalink
bake: fix output handling for push and load
Browse files Browse the repository at this point in the history
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
  • Loading branch information
crazy-max committed Mar 12, 2024
1 parent 4327ee7 commit 5af9738
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 7 deletions.
39 changes: 34 additions & 5 deletions bake/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,27 @@ func (t *Target) AddOverrides(overrides map[string]Override) error {
}
}
}
case "load":
load, err := strconv.ParseBool(value)
if err != nil {
return errors.Errorf("invalid value %s for boolean key load", value)
}
if load {
var loadUsed bool
for _, output := range t.Outputs {
if typ := parseOutputType(output); typ == "docker" {
if v := parseOutput(output); v != nil {
if _, ok := v["dest"]; !ok {
loadUsed = true
break
}
}
}
}
if !loadUsed {
t.Outputs = append(t.Outputs, "type=docker")
}
}
default:
return errors.Errorf("unknown key: %s", keys[0])
}
Expand Down Expand Up @@ -1394,18 +1415,26 @@ func removeAttestDupes(s []string) []string {
return res
}

func parseOutputType(str string) string {
func parseOutput(str string) map[string]string {
csvReader := csv.NewReader(strings.NewReader(str))
fields, err := csvReader.Read()
if err != nil {
return ""
return nil
}
res := map[string]string{}
for _, field := range fields {
parts := strings.SplitN(field, "=", 2)
if len(parts) == 2 {
if parts[0] == "type" {
return parts[1]
}
res[parts[0]] = parts[1]
}
}
return res
}

func parseOutputType(str string) string {
if out := parseOutput(str); out != nil {
if v, ok := out["type"]; ok {
return v
}
}
return ""
Expand Down
83 changes: 83 additions & 0 deletions bake/bake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,89 @@ func TestPushOverride(t *testing.T) {

require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, "type=image,push=true", m["app"].Outputs[0])

fp = File{
Name: "docker-bake.hcl",
Data: []byte(
`target "foo" {
output = [ "type=local,dest=out" ]
}
target "bar" {
}`),
}
ctx = context.TODO()
m, _, err = ReadTargets(ctx, []File{fp}, []string{"foo", "bar"}, []string{"*.push=true"}, nil)
require.NoError(t, err)

require.Equal(t, 2, len(m))
require.Equal(t, 1, len(m["foo"].Outputs))
require.Equal(t, []string{"type=local,dest=out"}, m["foo"].Outputs)
require.Equal(t, 1, len(m["bar"].Outputs))
require.Equal(t, []string{"type=image,push=true"}, m["bar"].Outputs)
}

func TestLoadOverride(t *testing.T) {
t.Parallel()

fp := File{
Name: "docker-bake.hcl",
Data: []byte(
`target "app" {
}`),
}
ctx := context.TODO()
m, _, err := ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"*.load=true"}, nil)
require.NoError(t, err)

require.Equal(t, 1, len(m["app"].Outputs))
require.Equal(t, "type=docker", m["app"].Outputs[0])

fp = File{
Name: "docker-bake.hcl",
Data: []byte(
`target "app" {
output = ["type=image"]
}`),
}
ctx = context.TODO()
m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"*.load=true"}, nil)
require.NoError(t, err)

require.Equal(t, 2, len(m["app"].Outputs))
require.Equal(t, []string{"type=image", "type=docker"}, m["app"].Outputs)

fp = File{
Name: "docker-bake.hcl",
Data: []byte(
`target "app" {
output = ["type=docker,dest=out"]
}`),
}
ctx = context.TODO()
m, _, err = ReadTargets(ctx, []File{fp}, []string{"app"}, []string{"*.load=true"}, nil)
require.NoError(t, err)

require.Equal(t, 2, len(m["app"].Outputs))
require.Equal(t, []string{"type=docker,dest=out", "type=docker"}, m["app"].Outputs)

fp = File{
Name: "docker-bake.hcl",
Data: []byte(
`target "foo" {
output = [ "type=local,dest=out" ]
}
target "bar" {
}`),
}
ctx = context.TODO()
m, _, err = ReadTargets(ctx, []File{fp}, []string{"foo", "bar"}, []string{"*.load=true"}, nil)
require.NoError(t, err)

require.Equal(t, 2, len(m))
require.Equal(t, 2, len(m["foo"].Outputs))
require.Equal(t, []string{"type=local,dest=out", "type=docker"}, m["foo"].Outputs)
require.Equal(t, 1, len(m["bar"].Outputs))
require.Equal(t, []string{"type=docker"}, m["bar"].Outputs)
}

func TestReadTargetsCompose(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions commands/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba

overrides := in.overrides
if in.exportPush {
overrides = append(overrides, "*.output=type=registry")
overrides = append(overrides, "*.push=true")
}
if in.exportLoad {
overrides = append(overrides, "*.output=type=docker")
overrides = append(overrides, "*.load=true")
}
if cFlags.noCache != nil {
overrides = append(overrides, fmt.Sprintf("*.no-cache=%t", *cFlags.noCache))
Expand Down
1 change: 1 addition & 0 deletions docs/reference/buildx_bake.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ You can override the following fields:
* `context`
* `dockerfile`
* `labels`
* `load`
* `no-cache`
* `no-cache-filter`
* `output`
Expand Down

0 comments on commit 5af9738

Please sign in to comment.