commands: implementation for inspect

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi 2019-04-15 10:21:09 -07:00
parent bd3d5cd19e
commit b7e15f3113
5 changed files with 189 additions and 23 deletions

View File

@ -128,7 +128,11 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
}
if in.use && ep != "" {
if err := txn.SetCurrent(ep, ng.Name, false, false); err != nil {
current, err := getCurrentEndpoint(dockerCli)
if err != nil {
return err
}
if err := txn.SetCurrent(current, ng.Name, false, false); err != nil {
return err
}
}

View File

@ -1,17 +1,44 @@
package commands
import (
"context"
"fmt"
"os"
"strings"
"text/tabwriter"
"time"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/moby/buildkit/util/appcontext"
"github.com/spf13/cobra"
"github.com/tonistiigi/buildx/build"
"github.com/tonistiigi/buildx/driver"
"github.com/tonistiigi/buildx/store"
"github.com/tonistiigi/buildx/util/progress"
"golang.org/x/sync/errgroup"
)
type inspectOptions struct {
bootstrap bool
}
type dinfo struct {
di *build.DriverInfo
info *driver.Info
platforms []string
err error
}
type nginfo struct {
ng *store.NodeGroup
drivers []dinfo
err error
}
func runInspect(dockerCli command.Cli, in inspectOptions, args []string) error {
ctx := appcontext.Context()
txn, release, err := getStore(dockerCli)
if err != nil {
return err
@ -21,7 +48,7 @@ func runInspect(dockerCli command.Cli, in inspectOptions, args []string) error {
var ng *store.NodeGroup
if len(args) > 0 {
ng, err = txn.NodeGroupByName(args[0])
ng, err = getNodeGroup(txn, dockerCli, args[0])
if err != nil {
return err
}
@ -33,21 +60,59 @@ func runInspect(dockerCli command.Cli, in inspectOptions, args []string) error {
}
if ng == nil {
ep, err := getCurrentEndpoint(dockerCli)
if err != nil {
return err
}
ng = &store.NodeGroup{
Name: "default",
Nodes: []store.Node{
{
Name: "default",
Endpoint: ep,
},
},
Nodes: []store.Node{{
Name: "default",
Endpoint: "default",
}},
}
}
ngi := &nginfo{ng: ng}
timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
err = loadNodeGroupData(timeoutCtx, dockerCli, ngi)
if in.bootstrap {
if err := boot(ctx, ngi); err != nil {
return err
}
ngi = &nginfo{ng: ng}
err = loadNodeGroupData(ctx, dockerCli, ngi)
}
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)
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())
}
fmt.Fprintln(w, "")
fmt.Fprintln(w, "Nodes:")
for i, n := range ngi.ng.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 {
fmt.Fprintf(w, "Error:\t%s\n", err.Error())
} else {
fmt.Fprintf(w, "Status:\t%s\n", ngi.drivers[i].info.Status)
fmt.Fprintf(w, "Platforms:\t%s\n", strings.Join(append(n.Platforms, ngi.drivers[i].platforms...), ", "))
}
}
w.Flush()
return nil
}
@ -71,3 +136,40 @@ func inspectCmd(dockerCli command.Cli) *cobra.Command {
return cmd
}
func boot(ctx context.Context, ngi *nginfo) 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 nil
}
pw := progress.NewPrinter(context.TODO(), os.Stderr, "auto")
mw := progress.NewMultiWriter(pw)
eg, _ := errgroup.WithContext(ctx)
for _, idx := range toBoot {
func(idx int) {
eg.Go(func() error {
pw := mw.WithPrefix(ngi.ng.Nodes[idx].Name, len(toBoot) > 1)
_, _, err := driver.Boot(ctx, ngi.drivers[idx].di.Driver, pw)
if err != nil {
ngi.drivers[idx].err = err
}
close(pw.Status())
<-pw.Done()
return nil
})
}(idx)
}
return eg.Wait()
}

View File

@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"github.com/containerd/containerd/platforms"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/docker"
dopts "github.com/docker/cli/opts"
@ -148,6 +149,7 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
if err != nil {
return nil, err
}
ng.Driver = f.Name()
}
for i, n := range ng.Nodes {
@ -243,10 +245,52 @@ func getDefaultDrivers(ctx context.Context, dockerCli command.Cli) ([]build.Driv
}, nil
}
// type ngInfo struct {
// ng *store.NodeGroup
// }
//
// func (i *ngInfo) init(ctx context.Context, boot bool) {
//
// }
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 {
for _, p := range w.Platforms {
d.platforms = append(d.platforms, platforms.Format(p))
}
}
}
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 {
ngi.drivers[i].di = &di
func(d *dinfo) {
eg.Go(func() error {
if err := loadInfoData(ctx, d); err != nil {
d.err = err
}
return nil
})
}(&ngi.drivers[i])
}
return eg.Wait()
}

View File

@ -153,7 +153,7 @@ func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
if err != nil {
if dockerclient.IsErrNotFound(err) {
return &driver.Info{
Status: driver.Terminated,
Status: driver.Inactive,
}, nil
}
return nil, err
@ -186,7 +186,7 @@ func (d *Driver) Rm(ctx context.Context, force bool) error {
if err != nil {
return err
}
if info.Status != driver.Terminated {
if info.Status != driver.Inactive {
return d.DockerAPI.ContainerRemove(ctx, d.Name, dockertypes.ContainerRemoveOptions{
RemoveVolumes: true,
Force: true,

View File

@ -10,18 +10,34 @@ import (
)
var ErrNotRunning = errors.Errorf("driver not running")
var ErrNotConnecting = errors.Errorf("driver not connection")
var ErrNotConnecting = errors.Errorf("driver not connecting")
type Status int
const (
Terminated Status = iota
Inactive Status = iota
Starting
Running
Stopping
Stopped
)
func (s Status) String() string {
switch s {
case Inactive:
return "inactive"
case Starting:
return "starting"
case Running:
return "running"
case Stopping:
return "stopping"
case Stopped:
return "stopped"
}
return "unknown"
}
type Info struct {
Status Status
}