refactor: mutualize builder logic

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
pull/865/head
CrazyMax 4 years ago
parent a3a4e48f25
commit 9d37e466a0
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7

@ -6,8 +6,8 @@ import (
"context"
"strings"
"github.com/docker/buildx/build"
"github.com/docker/buildx/driver"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/progress"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
@ -20,7 +20,7 @@ type Input struct {
URL string
}
func ReadRemoteFiles(ctx context.Context, dis []build.DriverInfo, url string, names []string, pw progress.Writer) ([]File, *Input, error) {
func ReadRemoteFiles(ctx context.Context, drivers []builderutil.Driver, url string, names []string, pw progress.Writer) ([]File, *Input, error) {
var filename string
st, ok := detectGitContext(url)
if !ok {
@ -33,8 +33,8 @@ func ReadRemoteFiles(ctx context.Context, dis []build.DriverInfo, url string, na
inp := &Input{State: st, URL: url}
var files []File
var di *build.DriverInfo
for _, d := range dis {
var di *builderutil.Driver
for _, d := range drivers {
if d.Err == nil {
di = &d
continue

@ -20,6 +20,7 @@ import (
"github.com/containerd/containerd/platforms"
"github.com/docker/buildx/driver"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/imagetools"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/resolver"
@ -81,16 +82,8 @@ type Inputs struct {
DockerfileInline string
}
type DriverInfo struct {
Driver driver.Driver
Name string
Platform []specs.Platform
Err error
ImageOpt imagetools.Opt
}
func filterAvailableDrivers(drivers []DriverInfo) ([]DriverInfo, error) {
out := make([]DriverInfo, 0, len(drivers))
func filterAvailableDrivers(drivers []builderutil.Driver) ([]builderutil.Driver, error) {
out := make([]builderutil.Driver, 0, len(drivers))
err := errors.Errorf("no drivers found")
for _, di := range drivers {
if di.Err == nil && di.Driver != nil {
@ -136,7 +129,7 @@ func allIndexes(l int) []int {
return out
}
func ensureBooted(ctx context.Context, drivers []DriverInfo, idxs []int, pw progress.Writer) ([]*client.Client, error) {
func ensureBooted(ctx context.Context, drivers []builderutil.Driver, idxs []int, pw progress.Writer) ([]*client.Client, error) {
clients := make([]*client.Client, len(drivers))
baseCtx := ctx
@ -182,7 +175,7 @@ func splitToDriverPairs(availablePlatforms map[string]int, opt map[string]Option
return m
}
func resolveDrivers(ctx context.Context, drivers []DriverInfo, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) {
func resolveDrivers(ctx context.Context, drivers []builderutil.Driver, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) {
dps, clients, err := resolveDriversBase(ctx, drivers, opt, pw)
if err != nil {
return nil, nil, err
@ -223,10 +216,10 @@ func resolveDrivers(ctx context.Context, drivers []DriverInfo, opt map[string]Op
return dps, clients, nil
}
func resolveDriversBase(ctx context.Context, drivers []DriverInfo, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) {
func resolveDriversBase(ctx context.Context, drivers []builderutil.Driver, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) {
availablePlatforms := map[string]int{}
for i, d := range drivers {
for _, p := range d.Platform {
for _, p := range d.Platforms {
availablePlatforms[platforms.Format(p)] = i
}
}
@ -576,7 +569,7 @@ func toSolveOpt(ctx context.Context, d driver.Driver, multiDriver bool, opt Opti
return &so, releaseF, nil
}
func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker *storeutil.DockerClient, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) {
func Build(ctx context.Context, drivers []builderutil.Driver, opt map[string]Options, docker *storeutil.DockerClient, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) {
if len(drivers) == 0 {
return nil, errors.Errorf("driver required for build")
}

@ -10,6 +10,7 @@ import (
"github.com/docker/buildx/bake"
"github.com/docker/buildx/build"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/tracing"
@ -88,16 +89,28 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
}
}()
dis, err := getInstanceOrDefault(ctx, dockerCli, in.builder, contextPathHash)
txn, release, err := storeutil.GetStore(dockerCli)
if err != nil {
return err
}
defer release()
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
if err = builder.Validate(); err != nil {
return err
}
if err = builder.LoadDrivers(ctx, false, contextPathHash); err != nil {
return err
}
var files []bake.File
var inp *bake.Input
if url != "" {
files, inp, err = bake.ReadRemoteFiles(ctx, dis, url, in.files, printer)
files, inp, err = bake.ReadRemoteFiles(ctx, builder.Drivers, url, in.files, printer)
} else {
files, err = bake.ReadLocalFiles(in.files)
}
@ -147,7 +160,7 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
return nil
}
resp, err := build.Build(ctx, dis, bo, storeutil.NewDockerClient(dockerCli), confutil.ConfigDir(dockerCli), printer)
resp, err := build.Build(ctx, builder.Drivers, bo, storeutil.NewDockerClient(dockerCli), confutil.ConfigDir(dockerCli), printer)
if err != nil {
return err
}

@ -10,6 +10,7 @@ import (
"github.com/docker/buildx/build"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/platformutil"
@ -205,7 +206,24 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
contextPathHash = in.contextPath
}
imageID, err := buildTargets(ctx, dockerCli, map[string]build.Options{defaultTargetName: opts}, in.progress, contextPathHash, in.builder, in.metadataFile)
txn, release, err := storeutil.GetStore(dockerCli)
if err != nil {
return err
}
defer release()
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
if err = builder.Validate(); err != nil {
return err
}
if err = builder.LoadDrivers(ctx, false, contextPathHash); err != nil {
return err
}
imageID, err := buildTargets(ctx, dockerCli, builder.Drivers, map[string]build.Options{defaultTargetName: opts}, in.progress, in.metadataFile)
if err != nil {
return err
}
@ -216,18 +234,13 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
return nil
}
func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]build.Options, progressMode, contextPathHash, instance string, metadataFile string) (imageID string, err error) {
dis, err := getInstanceOrDefault(ctx, dockerCli, instance, contextPathHash)
if err != nil {
return "", err
}
func buildTargets(ctx context.Context, dockerCli command.Cli, drivers []builderutil.Driver, opts map[string]build.Options, progressMode string, metadataFile string) (imageID string, err error) {
ctx2, cancel := context.WithCancel(context.TODO())
defer cancel()
printer := progress.NewPrinter(ctx2, os.Stderr, progressMode)
resp, err := build.Build(ctx, dis, opts, storeutil.NewDockerClient(dockerCli), confutil.ConfigDir(dockerCli), printer)
resp, err := build.Build(ctx, drivers, opts, storeutil.NewDockerClient(dockerCli), confutil.ConfigDir(dockerCli), printer)
err1 := printer.Wait()
if err == nil {
err = err1

@ -13,6 +13,7 @@ import (
"github.com/docker/buildx/driver"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/cobrautil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@ -185,17 +186,17 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
}
}
ngi := &nginfo{ng: ng}
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
if err = loadNodeGroupData(timeoutCtx, dockerCli, ngi); err != nil {
return err
}
if in.bootstrap {
if _, err = boot(ctx, ngi); err != nil {
builder, err := builderutil.New(dockerCli, txn, ng.Name)
if err != nil {
return err
}
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
if err = builder.LoadDrivers(timeoutCtx, true, ""); err != nil {
return err
}
if _, err = builder.Boot(ctx); err != nil {
return err
}
}

@ -6,7 +6,8 @@ import (
"os"
"text/tabwriter"
"github.com/docker/buildx/build"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/opts"
@ -23,30 +24,43 @@ type duOptions struct {
verbose bool
}
func runDiskUsage(dockerCli command.Cli, opts duOptions) error {
func runDiskUsage(dockerCli command.Cli, in duOptions) error {
ctx := appcontext.Context()
pi, err := toBuildkitPruneInfo(opts.filter.Value())
pi, err := toBuildkitPruneInfo(in.filter.Value())
if err != nil {
return err
}
dis, err := getInstanceOrDefault(ctx, dockerCli, opts.builder, "")
txn, release, err := storeutil.GetStore(dockerCli)
if err != nil {
return err
}
defer release()
for _, di := range dis {
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
if err = builder.Validate(); err != nil {
return err
}
if err = builder.LoadDrivers(ctx, false, ""); err != nil {
return err
}
drivers := builder.Drivers
for _, di := range drivers {
if di.Err != nil {
return err
}
}
out := make([][]*client.UsageInfo, len(dis))
out := make([][]*client.UsageInfo, len(drivers))
eg, ctx := errgroup.WithContext(ctx)
for i, di := range dis {
func(i int, di build.DriverInfo) {
for i, di := range drivers {
func(i int, di builderutil.Driver) {
eg.Go(func() error {
if di.Driver != nil {
c, err := di.Driver.Client(ctx)
@ -75,7 +89,7 @@ func runDiskUsage(dockerCli command.Cli, opts duOptions) error {
if du == nil {
continue
}
if opts.verbose {
if in.verbose {
printVerbose(tw, du)
} else {
if first {
@ -90,7 +104,7 @@ func runDiskUsage(dockerCli command.Cli, opts duOptions) error {
}
}
if opts.filter.Value().Len() == 0 {
if in.filter.Value().Len() == 0 {
printSummary(tw, out)
}

@ -6,8 +6,8 @@ import (
"io/ioutil"
"strings"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/imagetools"
"github.com/docker/cli/cli/command"
"github.com/docker/distribution/reference"
@ -110,21 +110,14 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
}
defer release()
var ng *store.NodeGroup
if in.builder != "" {
ng, err = storeutil.GetNodeGroup(txn, dockerCli, in.builder)
if err != nil {
return err
}
} else {
ng, err = storeutil.GetCurrentInstance(txn, dockerCli)
if err != nil {
return err
}
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
imageopt, err := storeutil.GetImageConfig(dockerCli, ng)
if err = builder.Validate(); err != nil {
return err
}
imageopt, err := builder.GetImageOpt()
if err != nil {
return err
}

@ -5,8 +5,8 @@ import (
"os"
"github.com/containerd/containerd/images"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/imagetools"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@ -29,24 +29,18 @@ func runInspect(dockerCli command.Cli, in inspectOptions, name string) error {
}
defer release()
var ng *store.NodeGroup
if in.builder != "" {
ng, err = storeutil.GetNodeGroup(txn, dockerCli, in.builder)
if err != nil {
return err
}
} else {
ng, err = storeutil.GetCurrentInstance(txn, dockerCli)
if err != nil {
return err
}
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
imageopt, err := storeutil.GetImageConfig(dockerCli, ng)
if err = builder.Validate(); err != nil {
return err
}
imageopt, err := builder.GetImageOpt()
if err != nil {
return err
}
r := imagetools.New(imageopt)
dt, desc, err := r.Get(ctx, name)

@ -8,8 +8,8 @@ import (
"text/tabwriter"
"time"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/platformutil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@ -31,81 +31,57 @@ func runInspect(dockerCli command.Cli, in inspectOptions) error {
}
defer release()
var ng *store.NodeGroup
if in.builder != "" {
ng, err = storeutil.GetNodeGroup(txn, dockerCli, in.builder)
if err != nil {
return err
}
} else {
ng, err = storeutil.GetCurrentInstance(txn, dockerCli)
if err != nil {
return err
}
}
if ng == nil {
ng = &store.NodeGroup{
Name: "default",
Nodes: []store.Node{{
Name: "default",
Endpoint: "default",
}},
}
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
ngi := &nginfo{ng: ng}
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
err = loadNodeGroupData(timeoutCtx, dockerCli, ngi)
err = builder.LoadDrivers(timeoutCtx, true, "")
var bootNgi *nginfo
var bootBuilder *builderutil.Builder
if in.bootstrap {
var ok bool
ok, err = boot(ctx, ngi)
ok, err = builder.Boot(ctx)
if err != nil {
return err
}
bootNgi = ngi
bootBuilder = builder
if ok {
ngi = &nginfo{ng: ng}
err = loadNodeGroupData(ctx, dockerCli, ngi)
err = builder.LoadDrivers(timeoutCtx, true, "")
}
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
fmt.Fprintf(w, "Name:\t%s\n", ngi.ng.Name)
fmt.Fprintf(w, "Driver:\t%s\n", ngi.ng.Driver)
fmt.Fprintf(w, "Name:\t%s\n", builder.NodeGroup.Name)
fmt.Fprintf(w, "Driver:\t%s\n", builder.NodeGroup.Driver)
if err != nil {
fmt.Fprintf(w, "Error:\t%s\n", err.Error())
} else if ngi.err != nil {
fmt.Fprintf(w, "Error:\t%s\n", ngi.err.Error())
} else if builder.Err != nil {
fmt.Fprintf(w, "Error:\t%s\n", builder.Err.Error())
}
if err == nil {
fmt.Fprintln(w, "")
fmt.Fprintln(w, "Nodes:")
for i, n := range ngi.ng.Nodes {
for i, n := range builder.NodeGroup.Nodes {
if i != 0 {
fmt.Fprintln(w, "")
}
fmt.Fprintf(w, "Name:\t%s\n", n.Name)
fmt.Fprintf(w, "Endpoint:\t%s\n", n.Endpoint)
if err := ngi.drivers[i].di.Err; err != nil {
fmt.Fprintf(w, "Error:\t%s\n", err.Error())
} else if err := ngi.drivers[i].err; err != nil {
if err := builder.Drivers[i].Err; err != nil {
fmt.Fprintf(w, "Error:\t%s\n", err.Error())
} else if bootNgi != nil && len(bootNgi.drivers) > i && bootNgi.drivers[i].err != nil {
fmt.Fprintf(w, "Error:\t%s\n", bootNgi.drivers[i].err.Error())
} else if bootBuilder != nil && len(bootBuilder.Drivers) > i && bootBuilder.Drivers[i].Err != nil {
fmt.Fprintf(w, "Error:\t%s\n", bootBuilder.Drivers[i].Err.Error())
} else {
fmt.Fprintf(w, "Status:\t%s\n", ngi.drivers[i].info.Status)
fmt.Fprintf(w, "Status:\t%s\n", builder.Drivers[i].Info.Status)
if len(n.Flags) > 0 {
fmt.Fprintf(w, "Flags:\t%s\n", strings.Join(n.Flags, " "))
}
fmt.Fprintf(w, "Platforms:\t%s\n", strings.Join(platformutil.FormatInGroups(n.Platforms, ngi.drivers[i].platforms), ", "))
fmt.Fprintf(w, "Platforms:\t%s\n", strings.Join(platformutil.FormatInGroups(n.Platforms, builder.Drivers[i].Platforms), ", "))
}
}
}

@ -9,8 +9,8 @@ import (
"text/tabwriter"
"time"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/buildx/util/cobrautil"
"github.com/docker/buildx/util/platformutil"
"github.com/docker/cli/cli"
@ -32,74 +32,36 @@ func runLs(dockerCli command.Cli, in lsOptions) error {
}
defer release()
ctx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
ll, err := txn.List()
builders, err := builderutil.GetBuilders(dockerCli, txn)
if err != nil {
return err
}
builders := make([]*nginfo, len(ll))
for i, ng := range ll {
builders[i] = &nginfo{ng: ng}
}
list, err := dockerCli.ContextStore().List()
if err != nil {
return err
}
ctxbuilders := make([]*nginfo, len(list))
for i, l := range list {
ctxbuilders[i] = &nginfo{ng: &store.NodeGroup{
Name: l.Name,
Nodes: []store.Node{{
Name: l.Name,
Endpoint: l.Name,
}},
}}
}
builders = append(builders, ctxbuilders...)
eg, _ := errgroup.WithContext(ctx)
timeoutCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
eg, _ := errgroup.WithContext(timeoutCtx)
for _, b := range builders {
func(b *nginfo) {
func(b *builderutil.Builder) {
eg.Go(func() error {
err = loadNodeGroupData(ctx, dockerCli, b)
if b.err == nil && err != nil {
b.err = err
err = b.LoadDrivers(timeoutCtx, true, "")
if b.Err == nil && err != nil {
b.Err = err
}
return nil
})
}(b)
}
if err := eg.Wait(); err != nil {
return err
}
currentName := "default"
current, err := storeutil.GetCurrentInstance(txn, dockerCli)
if err != nil {
return err
}
if current != nil {
currentName = current.Name
if current.Name == "default" {
currentName = current.Nodes[0].Endpoint
}
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
fmt.Fprintf(w, "NAME/NODE\tDRIVER/ENDPOINT\tSTATUS\tPLATFORMS\n")
currentSet := false
for _, b := range builders {
if !currentSet && b.ng.Name == currentName {
b.ng.Name += " *"
currentSet = true
if b.NodeGroup.Current {
b.NodeGroup.Name += " *"
}
printngi(w, b)
}
@ -109,29 +71,27 @@ func runLs(dockerCli command.Cli, in lsOptions) error {
return nil
}
func printngi(w io.Writer, ngi *nginfo) {
func printngi(w io.Writer, b *builderutil.Builder) {
var err string
if ngi.err != nil {
err = ngi.err.Error()
if b.Err != nil {
err = b.Err.Error()
}
fmt.Fprintf(w, "%s\t%s\t%s\t\n", ngi.ng.Name, ngi.ng.Driver, err)
if ngi.err == nil {
for idx, n := range ngi.ng.Nodes {
d := ngi.drivers[idx]
fmt.Fprintf(w, "%s\t%s\t%s\t\n", b.NodeGroup.Name, b.NodeGroup.Driver, err)
if b.Err == nil {
for idx, n := range b.NodeGroup.Nodes {
d := b.Drivers[idx]
var err string
if d.err != nil {
err = d.err.Error()
} else if d.di.Err != nil {
err = d.di.Err.Error()
if d.Err != nil {
err = d.Err.Error()
}
var status string
if d.info != nil {
status = d.info.Status.String()
if d.Info != nil {
status = d.Info.Status.String()
}
if err != "" {
fmt.Fprintf(w, " %s\t%s\t%s\n", n.Name, n.Endpoint, err)
} else {
fmt.Fprintf(w, " %s\t%s\t%s\t%s\n", n.Name, n.Endpoint, status, strings.Join(platformutil.FormatInGroups(n.Platforms, d.platforms), ", "))
fmt.Fprintf(w, " %s\t%s\t%s\t%s\n", n.Name, n.Endpoint, status, strings.Join(platformutil.FormatInGroups(n.Platforms, d.Platforms), ", "))
}
}
}

@ -7,7 +7,8 @@ import (
"text/tabwriter"
"time"
"github.com/docker/buildx/build"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/opts"
@ -34,10 +35,10 @@ const (
allCacheWarning = `WARNING! This will remove all build cache. Are you sure you want to continue?`
)
func runPrune(dockerCli command.Cli, opts pruneOptions) error {
func runPrune(dockerCli command.Cli, in pruneOptions) error {
ctx := appcontext.Context()
pruneFilters := opts.filter.Value()
pruneFilters := in.filter.Value()
pruneFilters = command.PruneFilters(dockerCli, pruneFilters)
pi, err := toBuildkitPruneInfo(pruneFilters)
@ -46,20 +47,33 @@ func runPrune(dockerCli command.Cli, opts pruneOptions) error {
}
warning := normalWarning
if opts.all {
if in.all {
warning = allCacheWarning
}
if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
if !in.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
return nil
}
dis, err := getInstanceOrDefault(ctx, dockerCli, opts.builder, "")
txn, release, err := storeutil.GetStore(dockerCli)
if err != nil {
return err
}
defer release()
for _, di := range dis {
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
if err = builder.Validate(); err != nil {
return err
}
if err = builder.LoadDrivers(ctx, false, ""); err != nil {
return err
}
drivers := builder.Drivers
for _, di := range drivers {
if di.Err != nil {
return err
}
@ -76,7 +90,7 @@ func runPrune(dockerCli command.Cli, opts pruneOptions) error {
defer close(printed)
for du := range ch {
total += du.Size
if opts.verbose {
if in.verbose {
printVerbose(tw, []*client.UsageInfo{&du})
} else {
if first {
@ -90,8 +104,8 @@ func runPrune(dockerCli command.Cli, opts pruneOptions) error {
}()
eg, ctx := errgroup.WithContext(ctx)
for _, di := range dis {
func(di build.DriverInfo) {
for _, di := range drivers {
func(di builderutil.Driver) {
eg.Go(func() error {
if di.Driver != nil {
c, err := di.Driver.Client(ctx)
@ -99,10 +113,10 @@ func runPrune(dockerCli command.Cli, opts pruneOptions) error {
return err
}
popts := []client.PruneOption{
client.WithKeepOpt(pi.KeepDuration, opts.keepStorage.Value()),
client.WithKeepOpt(pi.KeepDuration, in.keepStorage.Value()),
client.WithFilter(pi.Filter),
}
if opts.all {
if in.all {
popts = append(popts, client.PruneAll)
}
return c.Prune(ctx, ch, popts...)

@ -3,8 +3,8 @@ package commands
import (
"context"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/moby/buildkit/util/appcontext"
@ -26,31 +26,22 @@ func runRm(dockerCli command.Cli, in rmOptions) error {
}
defer release()
if in.builder != "" {
ng, err := storeutil.GetNodeGroup(txn, dockerCli, in.builder)
if err != nil {
return err
}
err1 := rm(ctx, dockerCli, ng, in.keepState, in.keepDaemon)
if err := txn.Remove(ng.Name); err != nil {
return err
}
return err1
}
ng, err := storeutil.GetCurrentInstance(txn, dockerCli)
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
if ng != nil {
err1 := rm(ctx, dockerCli, ng, in.keepState, in.keepDaemon)
if err := txn.Remove(ng.Name); err != nil {
return err
}
return err1
if err = builder.Validate(); err != nil {
return err
}
if err = builder.LoadDrivers(ctx, false, ""); err != nil {
return err
}
return nil
err1 := rm(ctx, builder.Drivers, in.keepState, in.keepDaemon)
if err := txn.Remove(builder.NodeGroup.Name); err != nil {
return err
}
return err1
}
func rmCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
@ -76,22 +67,18 @@ func rmCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
return cmd
}
func rm(ctx context.Context, dockerCli command.Cli, ng *store.NodeGroup, keepState, keepDaemon bool) error {
dis, err := driversForNodeGroup(ctx, dockerCli, ng, "")
if err != nil {
return err
}
for _, di := range dis {
func rm(ctx context.Context, drivers []builderutil.Driver, keepState, keepDaemon bool) (err error) {
for _, di := range drivers {
if di.Driver == nil {
continue
}
// Do not stop the buildkitd daemon when --keep-daemon is provided
if !keepDaemon {
if err := di.Driver.Stop(ctx, true); err != nil {
if err = di.Driver.Stop(ctx, true); err != nil {
return err
}
}
if err := di.Driver.Rm(ctx, true, !keepState, !keepDaemon); err != nil {
if err = di.Driver.Rm(ctx, true, !keepState, !keepDaemon); err != nil {
return err
}
if di.Err != nil {

@ -3,8 +3,8 @@ package commands
import (
"context"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/builderutil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/moby/buildkit/util/appcontext"
@ -24,26 +24,18 @@ func runStop(dockerCli command.Cli, in stopOptions) error {
}
defer release()
if in.builder != "" {
ng, err := storeutil.GetNodeGroup(txn, dockerCli, in.builder)
if err != nil {
return err
}
if err := stop(ctx, dockerCli, ng); err != nil {
return err
}
return nil
}
ng, err := storeutil.GetCurrentInstance(txn, dockerCli)
builder, err := builderutil.New(dockerCli, txn, in.builder)
if err != nil {
return err
}
if ng != nil {
return stop(ctx, dockerCli, ng)
if err = builder.Validate(); err != nil {
return err
}
if err = builder.LoadDrivers(ctx, false, ""); err != nil {
return err
}
return stopCurrent(ctx, dockerCli)
return stop(ctx, builder.Drivers)
}
func stopCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
@ -65,30 +57,8 @@ func stopCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
return cmd
}
func stop(ctx context.Context, dockerCli command.Cli, ng *store.NodeGroup) error {
dis, err := driversForNodeGroup(ctx, dockerCli, ng, "")
if err != nil {
return err
}
for _, di := range dis {
if di.Driver != nil {
if err := di.Driver.Stop(ctx, true); err != nil {
return err
}
}
if di.Err != nil {
err = di.Err
}
}
return err
}
func stopCurrent(ctx context.Context, dockerCli command.Cli) error {
dis, err := getDefaultDrivers(ctx, dockerCli, false, "")
if err != nil {
return err
}
for _, di := range dis {
func stop(ctx context.Context, drivers []builderutil.Driver) (err error) {
for _, di := range drivers {
if di.Driver != nil {
if err := di.Driver.Stop(ctx, true); err != nil {
return err

@ -1,353 +0,0 @@
package commands
import (
"context"
"net/url"
"os"
"strings"
"github.com/docker/buildx/build"
"github.com/docker/buildx/driver"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/platformutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/kubernetes"
ctxstore "github.com/docker/cli/cli/context/store"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"k8s.io/client-go/tools/clientcmd"
)
// driversForNodeGroup returns drivers for a nodegroup instance
func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.NodeGroup, contextPathHash string) ([]build.DriverInfo, error) {
eg, _ := errgroup.WithContext(ctx)
dis := make([]build.DriverInfo, len(ng.Nodes))
var f driver.Factory
if ng.Driver != "" {
f = driver.GetFactory(ng.Driver, true)
if f == nil {
return nil, errors.Errorf("failed to find driver %q", f)
}
} else {
dockerapi, err := storeutil.ClientForEndpoint(dockerCli, ng.Nodes[0].Endpoint)
if err != nil {
return nil, err
}
f, err = driver.GetDefaultFactory(ctx, dockerapi, false)
if err != nil {
return nil, err
}
ng.Driver = f.Name()
}
imageopt, err := storeutil.GetImageConfig(dockerCli, ng)
if err != nil {
return nil, err
}
for i, n := range ng.Nodes {
func(i int, n store.Node) {
eg.Go(func() error {
di := build.DriverInfo{
Name: n.Name,
Platform: n.Platforms,
}
defer func() {
dis[i] = di
}()
dockerapi, err := storeutil.ClientForEndpoint(dockerCli, n.Endpoint)
if err != nil {
di.Err = err
return nil
}
contextStore := dockerCli.ContextStore()
var kcc driver.KubeClientConfig
kcc, err = configFromContext(n.Endpoint, contextStore)
if err != nil {
// err is returned if n.Endpoint is non-context name like "unix:///var/run/docker.sock".
// try again with name="default".
// FIXME: n should retain real context name.
kcc, err = configFromContext("default", contextStore)
if err != nil {
logrus.Error(err)
}
}
tryToUseKubeConfigInCluster := false
if kcc == nil {
tryToUseKubeConfigInCluster = true
} else {
if _, err := kcc.ClientConfig(); err != nil {
tryToUseKubeConfigInCluster = true
}
}
if tryToUseKubeConfigInCluster {
kccInCluster := driver.KubeClientConfigInCluster{}
if _, err := kccInCluster.ClientConfig(); err == nil {
logrus.Debug("using kube config in cluster")
kcc = kccInCluster
}
}
d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi, imageopt.Auth, kcc, n.Flags, n.Files, n.DriverOpts, n.Platforms, contextPathHash)
if err != nil {
di.Err = err
return nil
}
di.Driver = d
di.ImageOpt = imageopt
return nil
})
}(i, n)
}
if err := eg.Wait(); err != nil {
return nil, err
}
return dis, nil
}
func configFromContext(endpointName string, s ctxstore.Reader) (clientcmd.ClientConfig, error) {
if strings.HasPrefix(endpointName, "kubernetes://") {
u, _ := url.Parse(endpointName)
if kubeconfig := u.Query().Get("kubeconfig"); kubeconfig != "" {
_ = os.Setenv(clientcmd.RecommendedConfigPathEnvVar, kubeconfig)
}
rules := clientcmd.NewDefaultClientConfigLoadingRules()
apiConfig, err := rules.Load()
if err != nil {
return nil, err
}
return clientcmd.NewDefaultClientConfig(*apiConfig, &clientcmd.ConfigOverrides{}), nil
}
return kubernetes.ConfigFromContext(endpointName, s)
}
func getInstanceOrDefault(ctx context.Context, dockerCli command.Cli, instance, contextPathHash string) ([]build.DriverInfo, error) {
var defaultOnly bool
if instance == "default" && instance != dockerCli.CurrentContext() {
return nil, errors.Errorf("use `docker --context=default buildx` to switch to default context")
}
if instance == "default" || instance == dockerCli.CurrentContext() {
instance = ""
defaultOnly = true
}
list, err := dockerCli.ContextStore().List()
if err != nil {
return nil, err
}
for _, l := range list {
if l.Name == instance {
return nil, errors.Errorf("use `docker --context=%s buildx` to switch to context %s", instance, instance)
}
}
if instance != "" {
return getInstanceByName(ctx, dockerCli, instance, contextPathHash)
}
return getDefaultDrivers(ctx, dockerCli, defaultOnly, contextPathHash)
}
func getInstanceByName(ctx context.Context, dockerCli command.Cli, instance, contextPathHash string) ([]build.DriverInfo, error) {
txn, release, err := storeutil.GetStore(dockerCli)
if err != nil {
return nil, err
}
defer release()
ng, err := txn.NodeGroupByName(instance)
if err != nil {
return nil, err
}
return driversForNodeGroup(ctx, dockerCli, ng, contextPathHash)
}
// getDefaultDrivers returns drivers based on current cli config
func getDefaultDrivers(ctx context.Context, dockerCli command.Cli, defaultOnly bool, contextPathHash string) ([]build.DriverInfo, error) {
txn, release, err := storeutil.GetStore(dockerCli)
if err != nil {
return nil, err
}
defer release()
if !defaultOnly {
ng, err := storeutil.GetCurrentInstance(txn, dockerCli)
if err != nil {
return nil, err
}
if ng != nil {
return driversForNodeGroup(ctx, dockerCli, ng, contextPathHash)
}
}
imageopt, err := storeutil.GetImageConfig(dockerCli, nil)
if err != nil {
return nil, err
}
d, err := driver.GetDriver(ctx, "buildx_buildkit_default", nil, dockerCli.Client(), imageopt.Auth, nil, nil, nil, nil, nil, contextPathHash)
if err != nil {
return nil, err
}
return []build.DriverInfo{
{
Name: "default",
Driver: d,
ImageOpt: imageopt,
},
}, nil
}
func loadInfoData(ctx context.Context, d *dinfo) error {
if d.di.Driver == nil {
return nil
}
info, err := d.di.Driver.Info(ctx)
if err != nil {
return err
}
d.info = info
if info.Status == driver.Running {
c, err := d.di.Driver.Client(ctx)
if err != nil {
return err
}
workers, err := c.ListWorkers(ctx)
if err != nil {
return errors.Wrap(err, "listing workers")
}
for _, w := range workers {
d.platforms = append(d.platforms, w.Platforms...)
}
d.platforms = platformutil.Dedupe(d.platforms)
}
return nil
}
func loadNodeGroupData(ctx context.Context, dockerCli command.Cli, ngi *nginfo) error {
eg, _ := errgroup.WithContext(ctx)
dis, err := driversForNodeGroup(ctx, dockerCli, ngi.ng, "")
if err != nil {
return err
}
ngi.drivers = make([]dinfo, len(dis))
for i, di := range dis {
d := di
ngi.drivers[i].di = &d
func(d *dinfo) {
eg.Go(func() error {
if err := loadInfoData(ctx, d); err != nil {
d.err = err
}
return nil
})
}(&ngi.drivers[i])
}
if eg.Wait(); err != nil {
return err
}
kubernetesDriverCount := 0
for _, di := range ngi.drivers {
if di.info != nil && len(di.info.DynamicNodes) > 0 {
kubernetesDriverCount++
}
}
isAllKubernetesDrivers := len(ngi.drivers) == kubernetesDriverCount
if isAllKubernetesDrivers {
var drivers []dinfo
var dynamicNodes []store.Node
for _, di := range ngi.drivers {
// dynamic nodes are used in Kubernetes driver.
// Kubernetes pods are dynamically mapped to BuildKit Nodes.
if di.info != nil && len(di.info.DynamicNodes) > 0 {
for i := 0; i < len(di.info.DynamicNodes); i++ {
// all []dinfo share *build.DriverInfo and *driver.Info
diClone := di
if pl := di.info.DynamicNodes[i].Platforms; len(pl) > 0 {
diClone.platforms = pl
}
drivers = append(drivers, di)
}
dynamicNodes = append(dynamicNodes, di.info.DynamicNodes...)
}
}
// not append (remove the static nodes in the store)
ngi.ng.Nodes = dynamicNodes
ngi.drivers = drivers
ngi.ng.Dynamic = true
}
return nil
}
type dinfo struct {
di *build.DriverInfo
info *driver.Info
platforms []specs.Platform
err error
}
type nginfo struct {
ng *store.NodeGroup
drivers []dinfo
err error
}
func boot(ctx context.Context, ngi *nginfo) (bool, error) {
toBoot := make([]int, 0, len(ngi.drivers))
for i, d := range ngi.drivers {
if d.err != nil || d.di.Err != nil || d.di.Driver == nil || d.info == nil {
continue
}
if d.info.Status != driver.Running {
toBoot = append(toBoot, i)
}
}
if len(toBoot) == 0 {
return false, nil
}
printer := progress.NewPrinter(context.TODO(), os.Stderr, "auto")
baseCtx := ctx
eg, _ := errgroup.WithContext(ctx)
for _, idx := range toBoot {
func(idx int) {
eg.Go(func() error {
pw := progress.WithPrefix(printer, ngi.ng.Nodes[idx].Name, len(toBoot) > 1)
_, err := driver.Boot(ctx, baseCtx, ngi.drivers[idx].di.Driver, pw)
if err != nil {
ngi.drivers[idx].err = err
}
return nil
})
}(idx)
}
err := eg.Wait()
err1 := printer.Wait()
if err == nil {
err = err1
}
return true, err
}

@ -0,0 +1,28 @@
package config
import (
"net/url"
"os"
"strings"
cxtkubernetes "github.com/docker/cli/cli/context/kubernetes"
ctxstore "github.com/docker/cli/cli/context/store"
"k8s.io/client-go/tools/clientcmd"
)
// FromContext loads k8s config from context
func FromContext(endpointName string, s ctxstore.Reader) (clientcmd.ClientConfig, error) {
if strings.HasPrefix(endpointName, "kubernetes://") {
u, _ := url.Parse(endpointName)
if kubeconfig := u.Query().Get("kubeconfig"); kubeconfig != "" {
_ = os.Setenv(clientcmd.RecommendedConfigPathEnvVar, kubeconfig)
}
rules := clientcmd.NewDefaultClientConfigLoadingRules()
apiConfig, err := rules.Load()
if err != nil {
return nil, err
}
return clientcmd.NewDefaultClientConfig(*apiConfig, &clientcmd.ConfigOverrides{}), nil
}
return cxtkubernetes.ConfigFromContext(endpointName, s)
}

@ -15,6 +15,7 @@ type NodeGroup struct {
Driver string
Nodes []Node
Dynamic bool
Current bool
}
type Node struct {

@ -75,6 +75,7 @@ func GetCurrentInstance(txn *store.Txn, dockerCli command.Cli) (*store.NodeGroup
ng, _ = GetNodeGroup(txn, dockerCli, dockerCli.CurrentContext())
}
ng.Current = true
return ng, nil
}

@ -0,0 +1,173 @@
package builderutil
import (
"context"
"os"
"github.com/docker/buildx/driver"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/imagetools"
"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
)
// Builder represents an active builder object
type Builder struct {
dockerCli command.Cli
txn *store.Txn
NodeGroup *store.NodeGroup
Drivers []Driver
Err error
}
// New initializes a new builder client
func New(dockerCli command.Cli, txn *store.Txn, name string) (_ *Builder, err error) {
b := &Builder{
dockerCli: dockerCli,
txn: txn,
}
if name != "" {
b.NodeGroup, err = storeutil.GetNodeGroup(txn, dockerCli, name)
if err != nil {
return nil, err
}
return b, nil
}
b.NodeGroup, err = storeutil.GetCurrentInstance(txn, dockerCli)
if err != nil {
return nil, err
}
return b, nil
}
// Validate validates builder context
func (b *Builder) Validate() error {
if b.NodeGroup.Name == "default" && b.NodeGroup.Name != b.dockerCli.CurrentContext() {
return errors.Errorf("use `docker --context=default buildx` to switch to default context")
}
list, err := b.dockerCli.ContextStore().List()
if err != nil {
return err
}
for _, l := range list {
if l.Name == b.NodeGroup.Name && b.NodeGroup.Name != "default" {
return errors.Errorf("use `docker --context=%s buildx` to switch to context %q", b.NodeGroup.Name, b.NodeGroup.Name)
}
}
return nil
}
// GetImageOpt returns registry auth configuration
func (b *Builder) GetImageOpt() (imagetools.Opt, error) {
return storeutil.GetImageConfig(b.dockerCli, b.NodeGroup)
}
// Boot bootstrap a builder
func (b *Builder) Boot(ctx context.Context) (bool, error) {
toBoot := make([]int, 0, len(b.Drivers))
for idx, d := range b.Drivers {
if d.Err != nil || d.Driver == nil || d.Info == nil {
continue
}
if d.Info.Status != driver.Running {
toBoot = append(toBoot, idx)
}
}
if len(toBoot) == 0 {
return false, nil
}
printer := progress.NewPrinter(context.Background(), os.Stderr, progress.PrinterModeAuto)
baseCtx := ctx
eg, _ := errgroup.WithContext(ctx)
for _, idx := range toBoot {
func(idx int) {
eg.Go(func() error {
pw := progress.WithPrefix(printer, b.NodeGroup.Nodes[idx].Name, len(toBoot) > 1)
_, err := driver.Boot(ctx, baseCtx, b.Drivers[idx].Driver, pw)
if err != nil {
b.Drivers[idx].Err = err
}
return nil
})
}(idx)
}
err := eg.Wait()
err1 := printer.Wait()
if err == nil {
err = err1
}
return true, err
}
// GetBuilders returns all builders
func GetBuilders(dockerCli command.Cli, txn *store.Txn) ([]*Builder, error) {
storeng, err := txn.List()
if err != nil {
return nil, err
}
currentName := "default"
current, err := storeutil.GetCurrentInstance(txn, dockerCli)
if err != nil {
return nil, err
}
if current != nil {
currentName = current.Name
if current.Name == "default" {
currentName = current.Nodes[0].Endpoint
}
}
currentSet := false
storeBuilders := make([]*Builder, len(storeng))
for i, ng := range storeng {
if !currentSet && ng.Name == currentName {
ng.Current = true
currentSet = true
}
storeBuilders[i] = &Builder{
dockerCli: dockerCli,
txn: txn,
NodeGroup: ng,
}
}
list, err := dockerCli.ContextStore().List()
if err != nil {
return nil, err
}
ctxBuilders := make([]*Builder, len(list))
for i, l := range list {
defaultNg := false
if !currentSet && l.Name == currentName {
defaultNg = true
currentSet = true
}
ctxBuilders[i] = &Builder{
dockerCli: dockerCli,
txn: txn,
NodeGroup: &store.NodeGroup{
Name: l.Name,
Current: defaultNg,
Nodes: []store.Node{
{
Name: l.Name,
Endpoint: l.Name,
},
},
},
}
}
return append(storeBuilders, ctxBuilders...), nil
}

@ -0,0 +1,185 @@
package builderutil
import (
"context"
"github.com/docker/buildx/driver"
k8sconfig "github.com/docker/buildx/driver/kubernetes/config"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/imagetools"
"github.com/docker/buildx/util/platformutil"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
)
type Driver struct {
Name string
Driver driver.Driver
Info *driver.Info
Platforms []ocispecs.Platform
ImageOpt imagetools.Opt
Err error
}
// LoadDrivers loads drivers.
func (b *Builder) LoadDrivers(ctx context.Context, withData bool, contextPathHash string) error {
eg, _ := errgroup.WithContext(ctx)
b.Drivers = make([]Driver, len(b.NodeGroup.Nodes))
var f driver.Factory
if b.NodeGroup.Driver != "" {
f = driver.GetFactory(b.NodeGroup.Driver, true)
if f == nil {
return errors.Errorf("failed to find driver %q", f)
}
} else {
dockerapi, err := storeutil.ClientForEndpoint(b.dockerCli, b.NodeGroup.Nodes[0].Endpoint)
if err != nil {
return err
}
f, err = driver.GetDefaultFactory(ctx, dockerapi, false)
if err != nil {
return err
}
b.NodeGroup.Driver = f.Name()
}
imageopt, err := b.GetImageOpt()
if err != nil {
return err
}
for i, n := range b.NodeGroup.Nodes {
func(i int, n store.Node) {
eg.Go(func() error {
di := Driver{
Name: n.Name,
Platforms: n.Platforms,
}
defer func() {
b.Drivers[i] = di
}()
dockerapi, err := storeutil.ClientForEndpoint(b.dockerCli, n.Endpoint)
if err != nil {
di.Err = err
return nil
}
contextStore := b.dockerCli.ContextStore()
var kcc driver.KubeClientConfig
kcc, err = k8sconfig.FromContext(n.Endpoint, contextStore)
if err != nil {
// err is returned if n.Endpoint is non-context name like "unix:///var/run/docker.sock".
// try again with name="default".
// FIXME(@AkihiroSuda): n should retain real context name.
kcc, err = k8sconfig.FromContext("default", contextStore)
if err != nil {
logrus.Error(err)
}
}
tryToUseKubeConfigInCluster := false
if kcc == nil {
tryToUseKubeConfigInCluster = true
} else {
if _, err := kcc.ClientConfig(); err != nil {
tryToUseKubeConfigInCluster = true
}
}
if tryToUseKubeConfigInCluster {
kccInCluster := driver.KubeClientConfigInCluster{}
if _, err := kccInCluster.ClientConfig(); err == nil {
logrus.Debug("using kube config in cluster")
kcc = kccInCluster
}
}
d, err := driver.GetDriver(ctx, "buildx_buildkit_"+n.Name, f, dockerapi, imageopt.Auth, kcc, n.Flags, n.Files, n.DriverOpts, n.Platforms, contextPathHash)
if err != nil {
di.Err = err
return nil
}
di.Driver = d
di.ImageOpt = imageopt
if withData {
if err := di.loadData(ctx); err != nil {
di.Err = err
}
}
return nil
})
}(i, n)
}
if err := eg.Wait(); err != nil {
return err
}
if withData {
kubernetesDriverCount := 0
for _, d := range b.Drivers {
if d.Info != nil && len(d.Info.DynamicNodes) > 0 {
kubernetesDriverCount++
}
}
isAllKubernetesDrivers := len(b.Drivers) == kubernetesDriverCount
if isAllKubernetesDrivers {
var drivers []Driver
var dynamicNodes []store.Node
for _, di := range b.Drivers {
// dynamic nodes are used in Kubernetes driver.
// Kubernetes pods are dynamically mapped to BuildKit Nodes.
if di.Info != nil && len(di.Info.DynamicNodes) > 0 {
for i := 0; i < len(di.Info.DynamicNodes); i++ {
// all []dinfo share *build.DriverInfo and *driver.Info
diClone := di
if pl := di.Info.DynamicNodes[i].Platforms; len(pl) > 0 {
diClone.Platforms = pl
}
drivers = append(drivers, di)
}
dynamicNodes = append(dynamicNodes, di.Info.DynamicNodes...)
}
}
// not append (remove the static nodes in the store)
b.NodeGroup.Nodes = dynamicNodes
b.Drivers = drivers
b.NodeGroup.Dynamic = true
}
}
return nil
}
func (d *Driver) loadData(ctx context.Context) error {
if d.Driver == nil {
return nil
}
info, err := d.Driver.Info(ctx)
if err != nil {
return err
}
d.Info = info
if d.Info.Status == driver.Running {
cdriver, err := d.Driver.Client(ctx)
if err != nil {
return err
}
workers, err := cdriver.ListWorkers(ctx)
if err != nil {
return errors.Wrap(err, "listing workers")
}
for _, w := range workers {
d.Platforms = append(d.Platforms, w.Platforms...)
}
d.Platforms = platformutil.Dedupe(d.Platforms)
}
return nil
}
Loading…
Cancel
Save