mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-01 00:23:56 +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:
		
							
								
								
									
										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