Skip to content

Commit

Permalink
Merge pull request docker#2131 from crazy-max/fix-driver-infer-platform
Browse files Browse the repository at this point in the history
build: infer platform from first node if none set
  • Loading branch information
crazy-max authored Dec 12, 2023
2 parents 0a0252d + 9d8ac1c commit 57dc457
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 24 deletions.
37 changes: 22 additions & 15 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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() {
Expand All @@ -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 {
Expand All @@ -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
}
Expand All @@ -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)
Expand All @@ -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")
Expand All @@ -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:")
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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:"))
Expand Down
21 changes: 14 additions & 7 deletions build/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
6 changes: 4 additions & 2 deletions build/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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()},
Expand All @@ -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) {
Expand Down

0 comments on commit 57dc457

Please sign in to comment.