client/image_create&import: Wrap options and result

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
Paweł Gronowski
2025-10-20 20:15:04 +02:00
committed by Austin Vazquez
parent 5cc1e5f800
commit a7f409014f
13 changed files with 77 additions and 35 deletions

View File

@@ -108,8 +108,8 @@ type ImageAPIClient interface {
ImageBuild(ctx context.Context, context io.Reader, options ImageBuildOptions) (ImageBuildResult, error)
BuildCachePrune(ctx context.Context, opts BuildCachePruneOptions) (BuildCachePruneResult, error)
BuildCancel(ctx context.Context, id string, opts BuildCancelOptions) (BuildCancelResult, error)
ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (io.ReadCloser, error)
ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (io.ReadCloser, error)
ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (ImageCreateResult, error)
ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (ImageImportResult, error)
ImageList(ctx context.Context, options ImageListOptions) ([]image.Summary, error)
ImagePull(ctx context.Context, ref string, options ImagePullOptions) (ImagePullResponse, error)

View File

@@ -2,7 +2,6 @@ package client
import (
"context"
"io"
"net/http"
"net/url"
"strings"
@@ -13,10 +12,10 @@ import (
// ImageCreate creates a new image based on the parent options.
// It returns the JSON content in the response body.
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (io.ReadCloser, error) {
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (ImageCreateResult, error) {
ref, err := reference.ParseNormalizedNamed(parentReference)
if err != nil {
return nil, err
return ImageCreateResult{}, err
}
query := url.Values{}
@@ -27,9 +26,9 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
}
resp, err := cli.tryImageCreate(ctx, query, staticAuth(options.RegistryAuth))
if err != nil {
return nil, err
return ImageCreateResult{}, err
}
return resp.Body, nil
return ImageCreateResult{Body: resp.Body}, nil
}
func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, resolveAuth registry.RequestAuthConfig) (*http.Response, error) {

View File

@@ -1,7 +1,14 @@
package client
import "io"
// ImageCreateOptions holds information to create images.
type ImageCreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
}
// ImageCreateResult holds the response body returned by the daemon for image create.
type ImageCreateResult struct {
Body io.ReadCloser
}

View File

@@ -57,13 +57,13 @@ func TestImageCreate(t *testing.T) {
}))
assert.NilError(t, err)
createResponse, err := client.ImageCreate(context.Background(), specifiedReference, ImageCreateOptions{
createResult, err := client.ImageCreate(context.Background(), specifiedReference, ImageCreateOptions{
RegistryAuth: expectedRegistryAuth,
})
assert.NilError(t, err)
response, err := io.ReadAll(createResponse)
response, err := io.ReadAll(createResult.Body)
assert.NilError(t, err)
err = createResponse.Close()
err = createResult.Body.Close()
assert.NilError(t, err)
assert.Check(t, is.Equal(string(response), "body"))
}

View File

@@ -2,7 +2,6 @@ package client
import (
"context"
"io"
"net/url"
"strings"
@@ -11,11 +10,11 @@ import (
// ImageImport creates a new image based on the source options.
// It returns the JSON content in the response body.
func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (io.ReadCloser, error) {
func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (ImageImportResult, error) {
if ref != "" {
// Check if the given image name can be resolved
if _, err := reference.ParseNormalizedNamed(ref); err != nil {
return nil, err
return ImageImportResult{}, err
}
}
@@ -41,7 +40,7 @@ func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, re
resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil)
if err != nil {
return nil, err
return ImageImportResult{}, err
}
return resp.Body, nil
return ImageImportResult{body: resp.Body}, nil
}

View File

@@ -17,3 +17,19 @@ type ImageImportOptions struct {
Changes []string // Changes are the raw changes to apply to this image
Platform string // Platform is the target platform of the image
}
// ImageImportResult holds the response body returned by the daemon for image import.
type ImageImportResult struct {
body io.ReadCloser
}
func (r ImageImportResult) Read(p []byte) (n int, err error) {
return r.body.Read(p)
}
func (r ImageImportResult) Close() error {
if r.body == nil {
return nil
}
return r.body.Close()
}

View File

@@ -77,14 +77,14 @@ func TestImageImport(t *testing.T) {
}, nil
}))
assert.NilError(t, err)
resp, err := client.ImageImport(context.Background(), ImageImportSource{
result, err := client.ImageImport(context.Background(), ImageImportSource{
Source: strings.NewReader("source"),
SourceName: "image_source",
}, "repository_name:imported", tc.options)
assert.NilError(t, err)
defer assert.NilError(t, resp.Close())
defer assert.NilError(t, result.Close())
body, err := io.ReadAll(resp)
body, err := io.ReadAll(result)
assert.NilError(t, err)
assert.Check(t, is.Equal(string(body), expectedOutput))
})

View File

@@ -27,10 +27,10 @@ func TestExportContainerAndImportImage(t *testing.T) {
poll.WaitOn(t, container.IsStopped(ctx, apiClient, cID))
reference := "repo/" + strings.ToLower(t.Name()) + ":v1"
exportResp, err := apiClient.ContainerExport(ctx, cID)
exportRes, err := apiClient.ContainerExport(ctx, cID)
assert.NilError(t, err)
importResp, err := apiClient.ImageImport(ctx, client.ImageImportSource{
Source: exportResp,
importRes, err := apiClient.ImageImport(ctx, client.ImageImportSource{
Source: exportRes,
SourceName: "-",
}, reference, client.ImageImportOptions{})
assert.NilError(t, err)
@@ -38,7 +38,7 @@ func TestExportContainerAndImportImage(t *testing.T) {
// If the import is successfully, then the message output should contain
// the image ID and match with the output from `docker images`.
dec := json.NewDecoder(importResp)
dec := json.NewDecoder(importRes)
var jm jsonmessage.JSONMessage
err = dec.Decode(&jm)
assert.NilError(t, err)
@@ -47,7 +47,7 @@ func TestExportContainerAndImportImage(t *testing.T) {
Filters: make(client.Filters).Add("reference", reference),
})
assert.NilError(t, err)
assert.Check(t, is.Equal(jm.Status, images[0].ID))
assert.Check(t, is.Equal(jm.Status, images.Images[0].ID))
}
// TestExportContainerAfterDaemonRestart checks that a container

View File

@@ -108,8 +108,8 @@ type ImageAPIClient interface {
ImageBuild(ctx context.Context, context io.Reader, options ImageBuildOptions) (ImageBuildResult, error)
BuildCachePrune(ctx context.Context, opts BuildCachePruneOptions) (BuildCachePruneResult, error)
BuildCancel(ctx context.Context, id string, opts BuildCancelOptions) (BuildCancelResult, error)
ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (io.ReadCloser, error)
ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (io.ReadCloser, error)
ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (ImageCreateResult, error)
ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (ImageImportResult, error)
ImageList(ctx context.Context, options ImageListOptions) ([]image.Summary, error)
ImagePull(ctx context.Context, ref string, options ImagePullOptions) (ImagePullResponse, error)

View File

@@ -2,7 +2,6 @@ package client
import (
"context"
"io"
"net/http"
"net/url"
"strings"
@@ -13,10 +12,10 @@ import (
// ImageCreate creates a new image based on the parent options.
// It returns the JSON content in the response body.
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (io.ReadCloser, error) {
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options ImageCreateOptions) (ImageCreateResult, error) {
ref, err := reference.ParseNormalizedNamed(parentReference)
if err != nil {
return nil, err
return ImageCreateResult{}, err
}
query := url.Values{}
@@ -27,9 +26,9 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
}
resp, err := cli.tryImageCreate(ctx, query, staticAuth(options.RegistryAuth))
if err != nil {
return nil, err
return ImageCreateResult{}, err
}
return resp.Body, nil
return ImageCreateResult{Body: resp.Body}, nil
}
func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, resolveAuth registry.RequestAuthConfig) (*http.Response, error) {

View File

@@ -1,7 +1,14 @@
package client
import "io"
// ImageCreateOptions holds information to create images.
type ImageCreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
}
// ImageCreateResult holds the response body returned by the daemon for image create.
type ImageCreateResult struct {
Body io.ReadCloser
}

View File

@@ -2,7 +2,6 @@ package client
import (
"context"
"io"
"net/url"
"strings"
@@ -11,11 +10,11 @@ import (
// ImageImport creates a new image based on the source options.
// It returns the JSON content in the response body.
func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (io.ReadCloser, error) {
func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, ref string, options ImageImportOptions) (ImageImportResult, error) {
if ref != "" {
// Check if the given image name can be resolved
if _, err := reference.ParseNormalizedNamed(ref); err != nil {
return nil, err
return ImageImportResult{}, err
}
}
@@ -41,7 +40,7 @@ func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, re
resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil)
if err != nil {
return nil, err
return ImageImportResult{}, err
}
return resp.Body, nil
return ImageImportResult{body: resp.Body}, nil
}

View File

@@ -17,3 +17,19 @@ type ImageImportOptions struct {
Changes []string // Changes are the raw changes to apply to this image
Platform string // Platform is the target platform of the image
}
// ImageImportResult holds the response body returned by the daemon for image import.
type ImageImportResult struct {
body io.ReadCloser
}
func (r ImageImportResult) Read(p []byte) (n int, err error) {
return r.body.Read(p)
}
func (r ImageImportResult) Close() error {
if r.body == nil {
return nil
}
return r.body.Close()
}