diff --git a/build/build.go b/build/build.go index 194b1897..624ceb84 100644 --- a/build/build.go +++ b/build/build.go @@ -118,6 +118,11 @@ type NamedContext struct { State *llb.State } +type reqForNode struct { + *resolvedNode + so *client.SolveOpt +} + func filterAvailableNodes(nodes []builder.Node) ([]builder.Node, error) { out := make([]builder.Node, 0, len(nodes)) err := errors.Errorf("no drivers found") @@ -509,10 +514,6 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s if err != nil { return nil, err } - driversSolveOpts := make(map[string][]*client.SolveOpt, len(drivers)) - for k, dps := range drivers { - driversSolveOpts[k] = make([]*client.SolveOpt, len(dps)) - } defers := make([]func(), 0, 2) defer func() { @@ -523,6 +524,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s } }() + reqForNodes := make(map[string][]*reqForNode) eg, ctx := errgroup.WithContext(ctx) for k, opt := range opt { @@ -532,7 +534,8 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s if err != nil { logrus.WithError(err).Warn("current commit information was not captured by the build") } - for i, np := range drivers[k] { + var reqn []*reqForNode + for _, np := range drivers[k] { if np.Node().Driver.IsMobyDriver() { hasMobyDriver = true } @@ -552,8 +555,12 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s so.FrontendAttrs[k] = v } defers = append(defers, release) - driversSolveOpts[k][i] = so + reqn = append(reqn, &reqForNode{ + resolvedNode: np, + so: so, + }) } + reqForNodes[k] = reqn for _, at := range opt.Session { if s, ok := at.(interface { SetLogger(progresswriter.Logger) @@ -566,8 +573,8 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s // validate for multi-node push if hasMobyDriver && multiDriver { - for _, so := range driversSolveOpts[k] { - for _, e := range so.Exports { + for _, np := range reqForNodes[k] { + for _, e := range np.so.Exports { if e.Type == "moby" { if ok, _ := strconv.ParseBool(e.Attrs["push"]); ok { return nil, errors.Errorf("multi-node push can't currently be performed with the docker driver, please switch to a different driver") @@ -580,9 +587,9 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s // validate that all links between targets use same drivers for name := range opt { - dps := drivers[name] + dps := reqForNodes[name] for i, dp := range dps { - so := driversSolveOpts[name][i] + so := reqForNodes[name][i].so for k, v := range so.FrontendAttrs { if strings.HasPrefix(k, "context:") && strings.HasPrefix(v, "target:") { k2 := strings.TrimPrefix(v, "target:") @@ -610,7 +617,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s results := waitmap.New() multiTarget := len(opt) > 1 - childTargets := calculateChildTargets(drivers, driversSolveOpts, opt) + childTargets := calculateChildTargets(reqForNodes, opt) for k, opt := range opt { err := func(k string) error { @@ -634,7 +641,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s for i, dp := range dps { i, dp := i, dp node := dp.Node() - so := driversSolveOpts[k][i] + so := reqForNodes[k][i].so if multiDriver { for i, e := range so.Exports { switch e.Type { @@ -1303,12 +1310,12 @@ func resultKey(index int, name string) string { } // calculateChildTargets returns all the targets that depend on current target for reverse index -func calculateChildTargets(drivers map[string][]*resolvedNode, driversSolveOpts map[string][]*client.SolveOpt, opt map[string]Options) map[string][]string { +func calculateChildTargets(reqs map[string][]*reqForNode, opt map[string]Options) map[string][]string { out := make(map[string][]string) for name := range opt { - dps := drivers[name] + dps := reqs[name] for i, dp := range dps { - so := driversSolveOpts[name][i] + so := reqs[name][i].so for k, v := range so.FrontendAttrs { if strings.HasPrefix(k, "context:") && strings.HasPrefix(v, "target:") { target := resultKey(dp.driverIndex, strings.TrimPrefix(v, "target:")) diff --git a/build/driver.go b/build/driver.go index 9e89b440..07f4560b 100644 --- a/build/driver.go +++ b/build/driver.go @@ -162,10 +162,6 @@ func (r *nodeResolver) resolve(ctx context.Context, ps []specs.Platform, pw prog return nil, true, nil } - if len(ps) == 0 { - ps = []specs.Platform{platforms.DefaultSpec()} - } - perfect := true nodeIdxs := make([]int, 0) for _, p := range ps { @@ -178,13 +174,24 @@ func (r *nodeResolver) resolve(ctx context.Context, ps []specs.Platform, pw prog } var nodes []*resolvedNode - for i, idx := range nodeIdxs { + if len(nodeIdxs) == 0 { nodes = append(nodes, &resolvedNode{ resolver: r, - driverIndex: idx, - platforms: []specs.Platform{ps[i]}, + driverIndex: 0, }) + } else { + for i, idx := range nodeIdxs { + node := &resolvedNode{ + resolver: r, + driverIndex: idx, + } + if len(ps) > 0 { + node.platforms = []specs.Platform{ps[i]} + } + nodes = append(nodes, node) + } } + nodes = recombineNodes(nodes) if _, err := r.boot(ctx, nodeIdxs, pw); err != nil { return nil, false, err diff --git a/build/driver_test.go b/build/driver_test.go index 068ec7ee..24f43411 100644 --- a/build/driver_test.go +++ b/build/driver_test.go @@ -22,6 +22,7 @@ func TestFindDriverSanity(t *testing.T) { require.Len(t, res, 1) require.Equal(t, 0, res[0].driverIndex) require.Equal(t, "aaa", res[0].Node().Builder) + require.Equal(t, []specs.Platform{platforms.DefaultSpec()}, res[0].platforms) } func TestFindDriverEmpty(t *testing.T) { @@ -216,7 +217,7 @@ func TestSelectNodePreferExact(t *testing.T) { require.Equal(t, "bbb", res[0].Node().Builder) } -func TestSelectNodeCurrentPlatform(t *testing.T) { +func TestSelectNodeNoPlatform(t *testing.T) { r := makeTestResolver(map[string][]specs.Platform{ "aaa": {platforms.MustParse("linux/foobar")}, "bbb": {platforms.DefaultSpec()}, @@ -226,7 +227,8 @@ func TestSelectNodeCurrentPlatform(t *testing.T) { require.NoError(t, err) require.True(t, perfect) require.Len(t, res, 1) - require.Equal(t, "bbb", res[0].Node().Builder) + require.Equal(t, "aaa", res[0].Node().Builder) + require.Empty(t, res[0].platforms) } func TestSelectNodeAdditionalPlatforms(t *testing.T) {