Skip to content

Commit

Permalink
dockerutil pkg to manage docker api client and context
Browse files Browse the repository at this point in the history
Signed-off-by: CrazyMax <[email protected]>
  • Loading branch information
crazy-max committed Dec 6, 2022
1 parent 47cf72b commit 63073b6
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 173 deletions.
74 changes: 4 additions & 70 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms"
"github.com/docker/buildx/driver"
"github.com/docker/buildx/util/dockerutil"
"github.com/docker/buildx/util/imagetools"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/resolver"
Expand All @@ -31,7 +32,6 @@ import (
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/builder/remotecontext/urlutil"
dockerclient "github.com/docker/docker/client"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
Expand Down Expand Up @@ -118,10 +118,6 @@ type DriverInfo struct {
ProxyConfig map[string]string
}

type DockerAPI interface {
DockerAPI(name string) (dockerclient.APIClient, error)
}

func filterAvailableDrivers(drivers []DriverInfo) ([]DriverInfo, error) {
out := make([]DriverInfo, 0, len(drivers))
err := errors.Errorf("no drivers found")
Expand Down Expand Up @@ -782,11 +778,11 @@ func Invoke(ctx context.Context, cfg ContainerConfig) error {
return err
}

func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker DockerAPI, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) {
func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker *dockerutil.Client, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) {
return BuildWithResultHandler(ctx, drivers, opt, docker, configDir, w, nil, false)
}

func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker DockerAPI, configDir string, w progress.Writer, resultHandleFunc func(driverIndex int, rCtx *ResultContext), allowNoOutput bool) (resp map[string]*client.SolveResponse, err error) {
func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker *dockerutil.Client, configDir string, w progress.Writer, resultHandleFunc func(driverIndex int, rCtx *ResultContext), allowNoOutput bool) (resp map[string]*client.SolveResponse, err error) {
if len(drivers) == 0 {
return nil, errors.Errorf("driver required for build")
}
Expand Down Expand Up @@ -864,7 +860,7 @@ func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[s
}
opt.Platforms = dp.platforms
so, release, err := toSolveOpt(ctx, di, multiDriver, opt, dp.bopts, configDir, w, func(name string) (io.WriteCloser, func(), error) {
return newDockerLoader(ctx, docker, name, w)
return docker.LoadImage(ctx, name, w)
})
if err != nil {
return nil, err
Expand Down Expand Up @@ -1631,40 +1627,6 @@ func notSupported(d driver.Driver, f driver.Feature) error {

type dockerLoadCallback func(name string) (io.WriteCloser, func(), error)

func newDockerLoader(ctx context.Context, d DockerAPI, name string, status progress.Writer) (io.WriteCloser, func(), error) {
c, err := d.DockerAPI(name)
if err != nil {
return nil, nil, err
}

pr, pw := io.Pipe()
done := make(chan struct{})

ctx, cancel := context.WithCancel(ctx)
var w *waitingWriter
w = &waitingWriter{
PipeWriter: pw,
f: func() {
resp, err := c.ImageLoad(ctx, pr, false)
defer close(done)
if err != nil {
pr.CloseWithError(err)
w.mu.Lock()
w.err = err
w.mu.Unlock()
return
}
prog := progress.WithPrefix(status, "", false)
progress.FromReader(prog, "importing to docker", resp.Body)
},
done: done,
cancel: cancel,
}
return w, func() {
pr.Close()
}, nil
}

func noDefaultLoad() bool {
v, ok := os.LookupEnv("BUILDX_NO_DEFAULT_LOAD")
if !ok {
Expand All @@ -1677,34 +1639,6 @@ func noDefaultLoad() bool {
return b
}

type waitingWriter struct {
*io.PipeWriter
f func()
once sync.Once
mu sync.Mutex
err error
done chan struct{}
cancel func()
}

func (w *waitingWriter) Write(dt []byte) (int, error) {
w.once.Do(func() {
go w.f()
})
return w.PipeWriter.Write(dt)
}

func (w *waitingWriter) Close() error {
err := w.PipeWriter.Close()
<-w.done
if err == nil {
w.mu.Lock()
defer w.mu.Unlock()
return w.err
}
return err
}

// handle https://github.com/moby/moby/pull/10858
func handleLowercaseDockerfile(dir, p string) string {
if filepath.Base(p) != "Dockerfile" {
Expand Down
3 changes: 2 additions & 1 deletion commands/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/docker/buildx/bake"
"github.com/docker/buildx/build"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/dockerutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/tracing"
"github.com/docker/cli/cli/command"
Expand Down Expand Up @@ -146,7 +147,7 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
return nil
}

resp, err := build.Build(ctx, dis, bo, dockerAPI(dockerCli), confutil.ConfigDir(dockerCli), printer)
resp, err := build.Build(ctx, dis, bo, dockerutil.NewClient(dockerCli), confutil.ConfigDir(dockerCli), printer)
if err != nil {
return wrapBuildError(err, true)
}
Expand Down
3 changes: 2 additions & 1 deletion commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/docker/buildx/monitor"
"github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/dockerutil"
"github.com/docker/buildx/util/platformutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/tracing"
Expand Down Expand Up @@ -291,7 +292,7 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]bu

var mu sync.Mutex
var idx int
resp, err := build.BuildWithResultHandler(ctx, dis, opts, dockerAPI(dockerCli), confutil.ConfigDir(dockerCli), printer, func(driverIndex int, gotRes *build.ResultContext) {
resp, err := build.BuildWithResultHandler(ctx, dis, opts, dockerutil.NewClient(dockerCli), confutil.ConfigDir(dockerCli), printer, func(driverIndex int, gotRes *build.ResultContext) {
mu.Lock()
defer mu.Unlock()
if res == nil || driverIndex < idx {
Expand Down
5 changes: 3 additions & 2 deletions commands/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/cobrautil"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/dockerutil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/google/shlex"
Expand Down Expand Up @@ -204,7 +205,7 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
if dockerCli.CurrentContext() == "default" && dockerCli.DockerEndpoint().TLSData != nil {
return errors.Errorf("could not create a builder instance with TLS data loaded from environment. Please use `docker context create <context-name>` to create a context for current environment and then create a builder instance with `docker buildx create <context-name>`")
}
ep, err = storeutil.GetCurrentEndpoint(dockerCli)
ep, err = dockerutil.GetCurrentEndpoint(dockerCli)
if err != nil {
return err
}
Expand Down Expand Up @@ -259,7 +260,7 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
}

if in.use && ep != "" {
current, err := storeutil.GetCurrentEndpoint(dockerCli)
current, err := dockerutil.GetCurrentEndpoint(dockerCli)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions commands/use.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"os"

"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/dockerutil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/pkg/errors"
Expand All @@ -29,7 +30,7 @@ func runUse(dockerCli command.Cli, in useOptions) error {
return errors.Errorf("run `docker context use default` to switch to default context")
}
if in.builder == "default" || in.builder == dockerCli.CurrentContext() {
ep, err := storeutil.GetCurrentEndpoint(dockerCli)
ep, err := dockerutil.GetCurrentEndpoint(dockerCli)
if err != nil {
return err
}
Expand All @@ -52,7 +53,7 @@ func runUse(dockerCli command.Cli, in useOptions) error {
return errors.Wrapf(err, "failed to find instance %q", in.builder)
}

ep, err := storeutil.GetCurrentEndpoint(dockerCli)
ep, err := dockerutil.GetCurrentEndpoint(dockerCli)
if err != nil {
return err
}
Expand Down
66 changes: 6 additions & 60 deletions commands/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ import (
remoteutil "github.com/docker/buildx/driver/remote/util"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/dockerutil"
"github.com/docker/buildx/util/platformutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/docker"
dopts "github.com/docker/cli/opts"
dockerclient "github.com/docker/docker/client"
"github.com/moby/buildkit/util/grpcerrors"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
Expand All @@ -26,10 +25,10 @@ import (

// validateEndpoint validates that endpoint is either a context or a docker host
func validateEndpoint(dockerCli command.Cli, ep string) (string, error) {
de, err := storeutil.GetDockerEndpoint(dockerCli, ep)
if err == nil && de != "" {
dem, err := dockerutil.GetDockerEndpoint(dockerCli, ep)
if err == nil && dem != nil {
if ep == "default" {
return de, nil
return dem.Host, nil
}
return ep, nil
}
Expand Down Expand Up @@ -67,7 +66,7 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
// docker-container driver for older daemon that doesn't support
// buildkit (< 18.06).
ep := ng.Nodes[0].Endpoint
dockerapi, err := clientForEndpoint(dockerCli, ep)
dockerapi, err := dockerutil.NewClientAPI(dockerCli, ep)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -99,7 +98,7 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
dis[i] = di
}()

dockerapi, err := clientForEndpoint(dockerCli, n.Endpoint)
dockerapi, err := dockerutil.NewClientAPI(dockerCli, n.Endpoint)
if err != nil {
di.Err = err
return nil
Expand Down Expand Up @@ -154,44 +153,6 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
return dis, nil
}

// clientForEndpoint returns a docker client for an endpoint
func clientForEndpoint(dockerCli command.Cli, name string) (dockerclient.APIClient, error) {
list, err := dockerCli.ContextStore().List()
if err != nil {
return nil, err
}
for _, l := range list {
if l.Name == name {
epm, err := docker.EndpointFromContext(l)
if err != nil {
return nil, err
}
ep, err := docker.WithTLSData(dockerCli.ContextStore(), name, epm)
if err != nil {
return nil, err
}
clientOpts, err := ep.ClientOpts()
if err != nil {
return nil, err
}
return dockerclient.NewClientWithOpts(clientOpts...)
}
}

ep := docker.Endpoint{
EndpointMeta: docker.EndpointMeta{
Host: name,
},
}

clientOpts, err := ep.ClientOpts()
if err != nil {
return nil, err
}

return dockerclient.NewClientWithOpts(clientOpts...)
}

func getInstanceOrDefault(ctx context.Context, dockerCli command.Cli, instance, contextPathHash string) ([]build.DriverInfo, error) {
var defaultOnly bool

Expand Down Expand Up @@ -380,21 +341,6 @@ func hasNodeGroup(list []*nginfo, ngi *nginfo) bool {
return false
}

func dockerAPI(dockerCli command.Cli) *api {
return &api{dockerCli: dockerCli}
}

type api struct {
dockerCli command.Cli
}

func (a *api) DockerAPI(name string) (dockerclient.APIClient, error) {
if name == "" {
name = a.dockerCli.CurrentContext()
}
return clientForEndpoint(a.dockerCli, name)
}

type dinfo struct {
di *build.DriverInfo
info *driver.Info
Expand Down
39 changes: 2 additions & 37 deletions store/storeutil/storeutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import (

"github.com/docker/buildx/store"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/dockerutil"
"github.com/docker/buildx/util/imagetools"
"github.com/docker/buildx/util/resolver"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/docker"
buildkitdconfig "github.com/moby/buildkit/cmd/buildkitd/config"
"github.com/pkg/errors"
)
Expand All @@ -24,19 +24,6 @@ func GetStore(dockerCli command.Cli) (*store.Txn, func(), error) {
return s.Txn()
}

// GetCurrentEndpoint returns the current default endpoint value
func GetCurrentEndpoint(dockerCli command.Cli) (string, error) {
name := dockerCli.CurrentContext()
if name != "default" {
return name, nil
}
de, err := GetDockerEndpoint(dockerCli, name)
if err != nil {
return "", errors.Errorf("docker endpoint for %q not found", name)
}
return de, nil
}

func GetProxyConfig(dockerCli command.Cli) map[string]string {
cfg := dockerCli.ConfigFile()
host := dockerCli.Client().DaemonHost()
Expand All @@ -63,31 +50,9 @@ func GetProxyConfig(dockerCli command.Cli) map[string]string {
return m
}

// GetDockerEndpoint returns docker endpoint string for given context
func GetDockerEndpoint(dockerCli command.Cli, name string) (string, error) {
list, err := dockerCli.ContextStore().List()
if err != nil {
return "", err
}
for _, l := range list {
if l.Name == name {
ep, ok := l.Endpoints["docker"]
if !ok {
return "", errors.Errorf("context %q does not have a Docker endpoint", name)
}
typed, ok := ep.(docker.EndpointMeta)
if !ok {
return "", errors.Errorf("endpoint %q is not of type EndpointMeta, %T", ep, ep)
}
return typed.Host, nil
}
}
return "", nil
}

// GetCurrentInstance finds the current builder instance
func GetCurrentInstance(txn *store.Txn, dockerCli command.Cli) (*store.NodeGroup, error) {
ep, err := GetCurrentEndpoint(dockerCli)
ep, err := dockerutil.GetCurrentEndpoint(dockerCli)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 63073b6

Please sign in to comment.