mirror of https://github.com/docker/buildx.git
dockerutil pkg to manage docker api client and context
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
parent
47cf72b8ba
commit
63073b65c0
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/docker/buildx/driver"
|
"github.com/docker/buildx/driver"
|
||||||
|
"github.com/docker/buildx/util/dockerutil"
|
||||||
"github.com/docker/buildx/util/imagetools"
|
"github.com/docker/buildx/util/imagetools"
|
||||||
"github.com/docker/buildx/util/progress"
|
"github.com/docker/buildx/util/progress"
|
||||||
"github.com/docker/buildx/util/resolver"
|
"github.com/docker/buildx/util/resolver"
|
||||||
|
@ -31,7 +32,6 @@ import (
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/builder/remotecontext/urlutil"
|
"github.com/docker/docker/builder/remotecontext/urlutil"
|
||||||
dockerclient "github.com/docker/docker/client"
|
|
||||||
"github.com/docker/docker/pkg/jsonmessage"
|
"github.com/docker/docker/pkg/jsonmessage"
|
||||||
"github.com/moby/buildkit/client"
|
"github.com/moby/buildkit/client"
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
|
@ -118,10 +118,6 @@ type DriverInfo struct {
|
||||||
ProxyConfig map[string]string
|
ProxyConfig map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type DockerAPI interface {
|
|
||||||
DockerAPI(name string) (dockerclient.APIClient, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func filterAvailableDrivers(drivers []DriverInfo) ([]DriverInfo, error) {
|
func filterAvailableDrivers(drivers []DriverInfo) ([]DriverInfo, error) {
|
||||||
out := make([]DriverInfo, 0, len(drivers))
|
out := make([]DriverInfo, 0, len(drivers))
|
||||||
err := errors.Errorf("no drivers found")
|
err := errors.Errorf("no drivers found")
|
||||||
|
@ -782,11 +778,11 @@ func Invoke(ctx context.Context, cfg ContainerConfig) error {
|
||||||
return err
|
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)
|
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 {
|
if len(drivers) == 0 {
|
||||||
return nil, errors.Errorf("driver required for build")
|
return nil, errors.Errorf("driver required for build")
|
||||||
}
|
}
|
||||||
|
@ -864,7 +860,7 @@ func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[s
|
||||||
}
|
}
|
||||||
opt.Platforms = dp.platforms
|
opt.Platforms = dp.platforms
|
||||||
so, release, err := toSolveOpt(ctx, di, multiDriver, opt, dp.bopts, configDir, w, func(name string) (io.WriteCloser, func(), error) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1631,40 +1627,6 @@ func notSupported(d driver.Driver, f driver.Feature) error {
|
||||||
|
|
||||||
type dockerLoadCallback func(name string) (io.WriteCloser, func(), 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 {
|
func noDefaultLoad() bool {
|
||||||
v, ok := os.LookupEnv("BUILDX_NO_DEFAULT_LOAD")
|
v, ok := os.LookupEnv("BUILDX_NO_DEFAULT_LOAD")
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -1677,34 +1639,6 @@ func noDefaultLoad() bool {
|
||||||
return b
|
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
|
// handle https://github.com/moby/moby/pull/10858
|
||||||
func handleLowercaseDockerfile(dir, p string) string {
|
func handleLowercaseDockerfile(dir, p string) string {
|
||||||
if filepath.Base(p) != "Dockerfile" {
|
if filepath.Base(p) != "Dockerfile" {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/docker/buildx/bake"
|
"github.com/docker/buildx/bake"
|
||||||
"github.com/docker/buildx/build"
|
"github.com/docker/buildx/build"
|
||||||
"github.com/docker/buildx/util/confutil"
|
"github.com/docker/buildx/util/confutil"
|
||||||
|
"github.com/docker/buildx/util/dockerutil"
|
||||||
"github.com/docker/buildx/util/progress"
|
"github.com/docker/buildx/util/progress"
|
||||||
"github.com/docker/buildx/util/tracing"
|
"github.com/docker/buildx/util/tracing"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
|
@ -146,7 +147,7 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
|
||||||
return nil
|
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 {
|
if err != nil {
|
||||||
return wrapBuildError(err, true)
|
return wrapBuildError(err, true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/docker/buildx/monitor"
|
"github.com/docker/buildx/monitor"
|
||||||
"github.com/docker/buildx/util/buildflags"
|
"github.com/docker/buildx/util/buildflags"
|
||||||
"github.com/docker/buildx/util/confutil"
|
"github.com/docker/buildx/util/confutil"
|
||||||
|
"github.com/docker/buildx/util/dockerutil"
|
||||||
"github.com/docker/buildx/util/platformutil"
|
"github.com/docker/buildx/util/platformutil"
|
||||||
"github.com/docker/buildx/util/progress"
|
"github.com/docker/buildx/util/progress"
|
||||||
"github.com/docker/buildx/util/tracing"
|
"github.com/docker/buildx/util/tracing"
|
||||||
|
@ -291,7 +292,7 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]bu
|
||||||
|
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
var idx int
|
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()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
if res == nil || driverIndex < idx {
|
if res == nil || driverIndex < idx {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/docker/buildx/store/storeutil"
|
"github.com/docker/buildx/store/storeutil"
|
||||||
"github.com/docker/buildx/util/cobrautil"
|
"github.com/docker/buildx/util/cobrautil"
|
||||||
"github.com/docker/buildx/util/confutil"
|
"github.com/docker/buildx/util/confutil"
|
||||||
|
"github.com/docker/buildx/util/dockerutil"
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/google/shlex"
|
"github.com/google/shlex"
|
||||||
|
@ -204,7 +205,7 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
||||||
if dockerCli.CurrentContext() == "default" && dockerCli.DockerEndpoint().TLSData != nil {
|
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>`")
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -259,7 +260,7 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if in.use && ep != "" {
|
if in.use && ep != "" {
|
||||||
current, err := storeutil.GetCurrentEndpoint(dockerCli)
|
current, err := dockerutil.GetCurrentEndpoint(dockerCli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/docker/buildx/store/storeutil"
|
"github.com/docker/buildx/store/storeutil"
|
||||||
|
"github.com/docker/buildx/util/dockerutil"
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -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")
|
return errors.Errorf("run `docker context use default` to switch to default context")
|
||||||
}
|
}
|
||||||
if in.builder == "default" || in.builder == dockerCli.CurrentContext() {
|
if in.builder == "default" || in.builder == dockerCli.CurrentContext() {
|
||||||
ep, err := storeutil.GetCurrentEndpoint(dockerCli)
|
ep, err := dockerutil.GetCurrentEndpoint(dockerCli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,7 @@ func runUse(dockerCli command.Cli, in useOptions) error {
|
||||||
return errors.Wrapf(err, "failed to find instance %q", in.builder)
|
return errors.Wrapf(err, "failed to find instance %q", in.builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
ep, err := storeutil.GetCurrentEndpoint(dockerCli)
|
ep, err := dockerutil.GetCurrentEndpoint(dockerCli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,11 @@ import (
|
||||||
remoteutil "github.com/docker/buildx/driver/remote/util"
|
remoteutil "github.com/docker/buildx/driver/remote/util"
|
||||||
"github.com/docker/buildx/store"
|
"github.com/docker/buildx/store"
|
||||||
"github.com/docker/buildx/store/storeutil"
|
"github.com/docker/buildx/store/storeutil"
|
||||||
|
"github.com/docker/buildx/util/dockerutil"
|
||||||
"github.com/docker/buildx/util/platformutil"
|
"github.com/docker/buildx/util/platformutil"
|
||||||
"github.com/docker/buildx/util/progress"
|
"github.com/docker/buildx/util/progress"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/context/docker"
|
|
||||||
dopts "github.com/docker/cli/opts"
|
dopts "github.com/docker/cli/opts"
|
||||||
dockerclient "github.com/docker/docker/client"
|
|
||||||
"github.com/moby/buildkit/util/grpcerrors"
|
"github.com/moby/buildkit/util/grpcerrors"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -26,10 +25,10 @@ import (
|
||||||
|
|
||||||
// validateEndpoint validates that endpoint is either a context or a docker host
|
// validateEndpoint validates that endpoint is either a context or a docker host
|
||||||
func validateEndpoint(dockerCli command.Cli, ep string) (string, error) {
|
func validateEndpoint(dockerCli command.Cli, ep string) (string, error) {
|
||||||
de, err := storeutil.GetDockerEndpoint(dockerCli, ep)
|
dem, err := dockerutil.GetDockerEndpoint(dockerCli, ep)
|
||||||
if err == nil && de != "" {
|
if err == nil && dem != nil {
|
||||||
if ep == "default" {
|
if ep == "default" {
|
||||||
return de, nil
|
return dem.Host, nil
|
||||||
}
|
}
|
||||||
return ep, nil
|
return ep, nil
|
||||||
}
|
}
|
||||||
|
@ -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
|
// docker-container driver for older daemon that doesn't support
|
||||||
// buildkit (< 18.06).
|
// buildkit (< 18.06).
|
||||||
ep := ng.Nodes[0].Endpoint
|
ep := ng.Nodes[0].Endpoint
|
||||||
dockerapi, err := clientForEndpoint(dockerCli, ep)
|
dockerapi, err := dockerutil.NewClientAPI(dockerCli, ep)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -99,7 +98,7 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
|
||||||
dis[i] = di
|
dis[i] = di
|
||||||
}()
|
}()
|
||||||
|
|
||||||
dockerapi, err := clientForEndpoint(dockerCli, n.Endpoint)
|
dockerapi, err := dockerutil.NewClientAPI(dockerCli, n.Endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
di.Err = err
|
di.Err = err
|
||||||
return nil
|
return nil
|
||||||
|
@ -154,44 +153,6 @@ func driversForNodeGroup(ctx context.Context, dockerCli command.Cli, ng *store.N
|
||||||
return dis, nil
|
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) {
|
func getInstanceOrDefault(ctx context.Context, dockerCli command.Cli, instance, contextPathHash string) ([]build.DriverInfo, error) {
|
||||||
var defaultOnly bool
|
var defaultOnly bool
|
||||||
|
|
||||||
|
@ -380,21 +341,6 @@ func hasNodeGroup(list []*nginfo, ngi *nginfo) bool {
|
||||||
return false
|
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 {
|
type dinfo struct {
|
||||||
di *build.DriverInfo
|
di *build.DriverInfo
|
||||||
info *driver.Info
|
info *driver.Info
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
|
|
||||||
"github.com/docker/buildx/store"
|
"github.com/docker/buildx/store"
|
||||||
"github.com/docker/buildx/util/confutil"
|
"github.com/docker/buildx/util/confutil"
|
||||||
|
"github.com/docker/buildx/util/dockerutil"
|
||||||
"github.com/docker/buildx/util/imagetools"
|
"github.com/docker/buildx/util/imagetools"
|
||||||
"github.com/docker/buildx/util/resolver"
|
"github.com/docker/buildx/util/resolver"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/context/docker"
|
|
||||||
buildkitdconfig "github.com/moby/buildkit/cmd/buildkitd/config"
|
buildkitdconfig "github.com/moby/buildkit/cmd/buildkitd/config"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
@ -24,19 +24,6 @@ func GetStore(dockerCli command.Cli) (*store.Txn, func(), error) {
|
||||||
return s.Txn()
|
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 {
|
func GetProxyConfig(dockerCli command.Cli) map[string]string {
|
||||||
cfg := dockerCli.ConfigFile()
|
cfg := dockerCli.ConfigFile()
|
||||||
host := dockerCli.Client().DaemonHost()
|
host := dockerCli.Client().DaemonHost()
|
||||||
|
@ -63,31 +50,9 @@ func GetProxyConfig(dockerCli command.Cli) map[string]string {
|
||||||
return m
|
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
|
// GetCurrentInstance finds the current builder instance
|
||||||
func GetCurrentInstance(txn *store.Txn, dockerCli command.Cli) (*store.NodeGroup, error) {
|
func GetCurrentInstance(txn *store.Txn, dockerCli command.Cli) (*store.NodeGroup, error) {
|
||||||
ep, err := GetCurrentEndpoint(dockerCli)
|
ep, err := dockerutil.GetCurrentEndpoint(dockerCli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package dockerutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/cli/cli/command"
|
||||||
|
"github.com/docker/cli/cli/context/docker"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClientAPI represents an active docker API object.
|
||||||
|
type ClientAPI struct {
|
||||||
|
client.APIClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClientAPI(cli command.Cli, ep string) (*ClientAPI, error) {
|
||||||
|
ca := &ClientAPI{}
|
||||||
|
|
||||||
|
var dep docker.Endpoint
|
||||||
|
dem, err := GetDockerEndpoint(cli, ep)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if dem != nil {
|
||||||
|
dep, err = docker.WithTLSData(cli.ContextStore(), ep, *dem)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dep = docker.Endpoint{
|
||||||
|
EndpointMeta: docker.EndpointMeta{
|
||||||
|
Host: ep,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clientOpts, err := dep.ClientOpts()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ca.APIClient, err = client.NewClientWithOpts(clientOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ca, nil
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package dockerutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/docker/buildx/util/progress"
|
||||||
|
"github.com/docker/cli/cli/command"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client represents an active docker object.
|
||||||
|
type Client struct {
|
||||||
|
cli command.Cli
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient initializes a new docker client.
|
||||||
|
func NewClient(cli command.Cli) *Client {
|
||||||
|
return &Client{cli: cli}
|
||||||
|
}
|
||||||
|
|
||||||
|
// API returns a new docker API client.
|
||||||
|
func (c *Client) API(name string) (client.APIClient, error) {
|
||||||
|
if name == "" {
|
||||||
|
name = c.cli.CurrentContext()
|
||||||
|
}
|
||||||
|
return NewClientAPI(c.cli, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadImage imports an image to docker.
|
||||||
|
func (c *Client) LoadImage(ctx context.Context, name string, status progress.Writer) (io.WriteCloser, func(), error) {
|
||||||
|
dapi, err := c.API(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 := dapi.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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package dockerutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/cli/cli/command"
|
||||||
|
"github.com/docker/cli/cli/context/docker"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetDockerEndpoint returns docker endpoint meta for given context
|
||||||
|
func GetDockerEndpoint(dockerCli command.Cli, name string) (*docker.EndpointMeta, 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
|
||||||
|
}
|
||||||
|
return &epm, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCurrentEndpoint returns the current default endpoint value
|
||||||
|
func GetCurrentEndpoint(dockerCli command.Cli) (string, error) {
|
||||||
|
name := dockerCli.CurrentContext()
|
||||||
|
if name != "default" {
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
dem, err := GetDockerEndpoint(dockerCli, name)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Errorf("docker endpoint for %q not found", name)
|
||||||
|
} else if dem != nil {
|
||||||
|
return dem.Host, nil
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
Loading…
Reference in New Issue