Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 37 additions & 24 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,41 @@ func toRepoOnly(in string) (string, error) {
return strings.Join(out, ","), nil
}

func prepareMultiDriverExports(so *client.SolveOpt, pushNames *string, insecurePush *bool) error {
var pushPrepared bool
for i := range so.Exports {
e := &so.Exports[i]
switch e.Type {
case "oci", "tar":
return errors.Errorf("%s for multi-node builds currently not supported", e.Type)
case "image":
if pushPrepared {
continue
}
if ok, _ := strconv.ParseBool(e.Attrs["push"]); !ok {
continue
}
if *pushNames == "" {
*pushNames = e.Attrs["name"]
if *pushNames == "" {
return errors.Errorf("tag is needed when pushing to registry")
}
if ok, _ := strconv.ParseBool(e.Attrs["registry.insecure"]); ok {
*insecurePush = true
}
}
names, err := toRepoOnly(e.Attrs["name"])
if err != nil {
return err
}
e.Attrs["name"] = names
e.Attrs["push-by-digest"] = "true"
pushPrepared = true
}
}
return nil
}

type (
EvaluateFunc func(ctx context.Context, name string, c gateway.Client, res *gateway.Result, opt Options) error
Handler struct {
Expand Down Expand Up @@ -566,30 +601,8 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
node := dp.Node()
so := reqForNodes[k][i].so
if multiDriver {
for i, e := range so.Exports {
switch e.Type {
case "oci", "tar":
return errors.Errorf("%s for multi-node builds currently not supported", e.Type)
case "image":
if pushNames == "" && e.Attrs["push"] != "" {
if ok, _ := strconv.ParseBool(e.Attrs["push"]); ok {
pushNames = e.Attrs["name"]
if pushNames == "" {
return errors.Errorf("tag is needed when pushing to registry")
}
names, err := toRepoOnly(e.Attrs["name"])
if err != nil {
return err
}
if ok, _ := strconv.ParseBool(e.Attrs["registry.insecure"]); ok {
insecurePush = true
}
e.Attrs["name"] = names
e.Attrs["push-by-digest"] = "true"
so.Exports[i].Attrs = e.Attrs
}
}
}
if err := prepareMultiDriverExports(so, &pushNames, &insecurePush); err != nil {
return err
}
}

Expand Down
42 changes: 42 additions & 0 deletions build/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,48 @@ func (d warnOutputDriver) IsMobyDriver() bool {
return d.moby
}

func TestPrepareMultiDriverExportsForEveryNode(t *testing.T) {
const taggedName = "registry.example.com/user/app:latest"
const secondaryName = "registry.example.com/user/secondary:latest"
newSolveOpt := func() *client.SolveOpt {
return &client.SolveOpt{
Exports: []client.ExportEntry{
{
Type: "image",
Attrs: map[string]string{
"name": taggedName,
"push": "true",
"registry.insecure": "true",
},
},
{
Type: "image",
Attrs: map[string]string{
"name": secondaryName,
"push": "true",
},
},
},
}
}
solveOpts := []*client.SolveOpt{newSolveOpt(), newSolveOpt()}

var pushNames string
var insecurePush bool
for _, so := range solveOpts {
require.NoError(t, prepareMultiDriverExports(so, &pushNames, &insecurePush))
}

require.Equal(t, taggedName, pushNames)
require.True(t, insecurePush)
for _, so := range solveOpts {
require.Equal(t, "registry.example.com/user/app", so.Exports[0].Attrs["name"])
require.Equal(t, "true", so.Exports[0].Attrs["push-by-digest"])
require.Equal(t, secondaryName, so.Exports[1].Attrs["name"])
require.NotContains(t, so.Exports[1].Attrs, "push-by-digest")
}
}

func TestWarnOnNoOutput(t *testing.T) {
cloudNodes := []builder.Node{{Driver: newWarnOutputDriver("cloud", false)}}
mobyNodes := []builder.Node{{Driver: newWarnOutputDriver("docker", true)}}
Expand Down