chore: internal Docker client PushImage

This commit is contained in:
Pasha Sviderski
2025-09-30 13:58:34 +10:00
parent 782f4cb20b
commit bcc504b8cc
2 changed files with 64 additions and 13 deletions
+59 -8
View File
@@ -15,15 +15,15 @@ import (
"github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/jsonmessage"
) )
type PullImageMessage struct { type PullPushImageMessage struct {
Message jsonmessage.JSONMessage Message jsonmessage.JSONMessage
Err error Err error
} }
// PullImage pulls a Docker image and returns a channel to receive progress messages. // PullImage pulls an image and returns a channel to receive progress messages.
func (cli *Client) PullImage( func (cli *Client) PullImage(
ctx context.Context, image string, opts image.PullOptions, ctx context.Context, image string, opts image.PullOptions,
) (<-chan PullImageMessage, error) { ) (<-chan PullPushImageMessage, error) {
if opts.RegistryAuth == "" { if opts.RegistryAuth == "" {
// Try to retrieve the authentication token for the image from the default local Docker config file. // Try to retrieve the authentication token for the image from the default local Docker config file.
if encodedAuth, err := RetrieveLocalDockerRegistryAuth(image); err == nil { if encodedAuth, err := RetrieveLocalDockerRegistryAuth(image); err == nil {
@@ -37,30 +37,81 @@ func (cli *Client) PullImage(
} }
decoder := json.NewDecoder(respBody) decoder := json.NewDecoder(respBody)
ch := make(chan PullImageMessage) ch := make(chan PullPushImageMessage)
go func() { go func() {
defer respBody.Close() defer respBody.Close()
defer close(ch) defer close(ch)
var jm jsonmessage.JSONMessage
for { for {
var jm jsonmessage.JSONMessage
if err = decoder.Decode(&jm); err != nil { if err = decoder.Decode(&jm); err != nil {
if errors.Is(err, io.EOF) { if errors.Is(err, io.EOF) {
break break
} }
ch <- PullImageMessage{Err: fmt.Errorf("decode image pull message: %w", err)} ch <- PullPushImageMessage{Err: fmt.Errorf("decode image pull message: %w", err)}
break break
} }
msg := PullImageMessage{Message: jm} msg := PullPushImageMessage{Message: jm}
if jm.Error != nil { if jm.Error != nil {
msg.Err = errors.New(jm.Error.Message) msg.Err = errors.New(jm.Error.Message)
} }
select { select {
case <-ctx.Done(): case <-ctx.Done():
ch <- PullImageMessage{Err: ctx.Err()} ch <- PullPushImageMessage{Err: ctx.Err()}
return
default:
ch <- msg
}
}
}()
return ch, nil
}
// PushImage pushes an image and returns a channel to receive progress messages.
func (cli *Client) PushImage(
ctx context.Context, image string, opts image.PushOptions,
) (<-chan PullPushImageMessage, error) {
if opts.RegistryAuth == "" {
// Try to retrieve the authentication token for the image from the default local Docker config file.
if encodedAuth, err := RetrieveLocalDockerRegistryAuth(image); err == nil {
opts.RegistryAuth = encodedAuth
}
}
respBody, err := cli.ImagePush(ctx, image, opts)
if err != nil {
return nil, err
}
decoder := json.NewDecoder(respBody)
ch := make(chan PullPushImageMessage)
go func() {
defer respBody.Close()
defer close(ch)
for {
var jm jsonmessage.JSONMessage
if err = decoder.Decode(&jm); err != nil {
if errors.Is(err, io.EOF) {
break
}
ch <- PullPushImageMessage{Err: fmt.Errorf("decode image push message: %w", err)}
break
}
msg := PullPushImageMessage{Message: jm}
if jm.Error != nil {
msg.Err = errors.New(jm.Error.Message)
}
select {
case <-ctx.Done():
ch <- PullPushImageMessage{Err: ctx.Err()}
return return
default: default:
ch <- msg ch <- msg
+5 -5
View File
@@ -206,7 +206,7 @@ type PullOptions struct {
Platform string Platform string
} }
func (c *Client) PullImage(ctx context.Context, image string, opts PullOptions) (<-chan docker.PullImageMessage, error) { func (c *Client) PullImage(ctx context.Context, image string, opts PullOptions) (<-chan docker.PullPushImageMessage, error) {
optsBytes, err := json.Marshal(opts) optsBytes, err := json.Marshal(opts)
if err != nil { if err != nil {
return nil, fmt.Errorf("marshal options: %w", err) return nil, fmt.Errorf("marshal options: %w", err)
@@ -217,7 +217,7 @@ func (c *Client) PullImage(ctx context.Context, image string, opts PullOptions)
return nil, err return nil, err
} }
ch := make(chan docker.PullImageMessage) ch := make(chan docker.PullPushImageMessage)
go func() { go func() {
defer close(ch) defer close(ch)
@@ -228,16 +228,16 @@ func (c *Client) PullImage(ctx context.Context, image string, opts PullOptions)
return return
} }
if err != nil { if err != nil {
ch <- docker.PullImageMessage{Err: err} ch <- docker.PullPushImageMessage{Err: err}
return return
} }
var jm jsonmessage.JSONMessage var jm jsonmessage.JSONMessage
if err = json.Unmarshal(msg.Message, &jm); err != nil { if err = json.Unmarshal(msg.Message, &jm); err != nil {
ch <- docker.PullImageMessage{Err: fmt.Errorf("unmarshal JSON message: %w", err)} ch <- docker.PullPushImageMessage{Err: fmt.Errorf("unmarshal JSON message: %w", err)}
return return
} }
ch <- docker.PullImageMessage{Message: jm} ch <- docker.PullPushImageMessage{Message: jm}
} }
}() }()