mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-10-31 08:03:43 +08:00 
			
		
		
		
	dockerutil pkg to manage docker api client and context
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
		| @@ -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 | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								util/dockerutil/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								util/dockerutil/api.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
|  | } | ||||||
							
								
								
									
										92
									
								
								util/dockerutil/client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								util/dockerutil/client.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								util/dockerutil/context.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								util/dockerutil/context.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 CrazyMax
					CrazyMax