mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
Merge pull request #51227 from vvoland/client-image-opts
client/image: Wrap result and options in structs
This commit is contained in:
@@ -7,13 +7,15 @@ import (
|
||||
|
||||
type BuildCancelOptions struct{}
|
||||
|
||||
type BuildCancelResult struct{}
|
||||
|
||||
// BuildCancel requests the daemon to cancel the ongoing build request
|
||||
// with the given id.
|
||||
func (cli *Client) BuildCancel(ctx context.Context, id string, _ BuildCancelOptions) error {
|
||||
func (cli *Client) BuildCancel(ctx context.Context, id string, _ BuildCancelOptions) (BuildCancelResult, error) {
|
||||
query := url.Values{}
|
||||
query.Set("id", id)
|
||||
|
||||
resp, err := cli.post(ctx, "/build/cancel", query, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
return err
|
||||
return BuildCancelResult{}, err
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/moby/moby/api/types"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/api/types/events"
|
||||
"github.com/moby/moby/api/types/image"
|
||||
"github.com/moby/moby/api/types/network"
|
||||
"github.com/moby/moby/api/types/plugin"
|
||||
"github.com/moby/moby/api/types/registry"
|
||||
@@ -105,18 +104,18 @@ type DistributionAPIClient interface {
|
||||
|
||||
// ImageAPIClient defines API client methods for the images
|
||||
type ImageAPIClient interface {
|
||||
ImageBuild(ctx context.Context, context io.Reader, options ImageBuildOptions) (ImageBuildResponse, error)
|
||||
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) 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)
|
||||
BuildCancel(ctx context.Context, id string, opts BuildCancelOptions) (BuildCancelResult, 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)
|
||||
ImageList(ctx context.Context, options ImageListOptions) (ImageListResult, error)
|
||||
ImagePull(ctx context.Context, ref string, options ImagePullOptions) (ImagePullResponse, error)
|
||||
ImagePush(ctx context.Context, ref string, options ImagePushOptions) (ImagePushResponse, error)
|
||||
ImageRemove(ctx context.Context, image string, options ImageRemoveOptions) ([]image.DeleteResponse, error)
|
||||
ImageSearch(ctx context.Context, term string, options ImageSearchOptions) ([]registry.SearchResult, error)
|
||||
ImageTag(ctx context.Context, image, ref string) error
|
||||
ImageRemove(ctx context.Context, image string, options ImageRemoveOptions) (ImageRemoveResult, error)
|
||||
ImageSearch(ctx context.Context, term string, options ImageSearchOptions) (ImageSearchResult, error)
|
||||
ImageTag(ctx context.Context, options ImageTagOptions) (ImageTagResult, error)
|
||||
ImagesPrune(ctx context.Context, opts ImagePruneOptions) (ImagePruneResult, error)
|
||||
|
||||
ImageInspect(ctx context.Context, image string, _ ...ImageInspectOption) (ImageInspectResult, error)
|
||||
|
||||
@@ -17,15 +17,15 @@ import (
|
||||
// ImageBuild sends a request to the daemon to build images.
|
||||
// The Body in the response implements an [io.ReadCloser] and it's up to the caller to
|
||||
// close it.
|
||||
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options ImageBuildOptions) (ImageBuildResponse, error) {
|
||||
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options ImageBuildOptions) (ImageBuildResult, error) {
|
||||
query, err := cli.imageBuildOptionsToQuery(ctx, options)
|
||||
if err != nil {
|
||||
return ImageBuildResponse{}, err
|
||||
return ImageBuildResult{}, err
|
||||
}
|
||||
|
||||
buf, err := json.Marshal(options.AuthConfigs)
|
||||
if err != nil {
|
||||
return ImageBuildResponse{}, err
|
||||
return ImageBuildResult{}, err
|
||||
}
|
||||
|
||||
headers := http.Header{}
|
||||
@@ -34,10 +34,10 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
||||
|
||||
resp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
|
||||
if err != nil {
|
||||
return ImageBuildResponse{}, err
|
||||
return ImageBuildResult{}, err
|
||||
}
|
||||
|
||||
return ImageBuildResponse{
|
||||
return ImageBuildResult{
|
||||
Body: resp.Body,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -68,9 +68,9 @@ type ImageBuildOutput struct {
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
// ImageBuildResponse holds information
|
||||
// ImageBuildResult holds information
|
||||
// returned by a server after building
|
||||
// an image.
|
||||
type ImageBuildResponse struct {
|
||||
type ImageBuildResult struct {
|
||||
Body io.ReadCloser
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
// to include [image.Summary.Manifests] with information about image manifests.
|
||||
// This is experimental and might change in the future without any backward
|
||||
// compatibility.
|
||||
func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]image.Summary, error) {
|
||||
func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) (ImageListResult, error) {
|
||||
var images []image.Summary
|
||||
|
||||
query := url.Values{}
|
||||
@@ -34,7 +34,7 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i
|
||||
// Normally, version-negotiation (if enabled) would not happen until
|
||||
// the API request is made.
|
||||
if err := cli.checkVersion(ctx); err != nil {
|
||||
return images, err
|
||||
return ImageListResult{}, err
|
||||
}
|
||||
|
||||
if versions.GreaterThanOrEqualTo(cli.version, "1.47") {
|
||||
@@ -45,9 +45,9 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i
|
||||
resp, err := cli.get(ctx, "/images/json", query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return images, err
|
||||
return ImageListResult{}, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&images)
|
||||
return images, err
|
||||
return ImageListResult{Items: images}, err
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package client
|
||||
|
||||
import "github.com/moby/moby/api/types/image"
|
||||
|
||||
// ImageListOptions holds parameters to list images with.
|
||||
type ImageListOptions struct {
|
||||
// All controls whether all images in the graph are filtered, or just
|
||||
@@ -15,3 +17,8 @@ type ImageListOptions struct {
|
||||
// Manifests indicates whether the image manifests should be returned.
|
||||
Manifests bool
|
||||
}
|
||||
|
||||
// ImageListResult holds the result from ImageList.
|
||||
type ImageListResult struct {
|
||||
Items []image.Summary
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ func TestImageList(t *testing.T) {
|
||||
|
||||
images, err := client.ImageList(context.Background(), listCase.options)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Len(images, 2))
|
||||
assert.Check(t, is.Len(images.Items, 2))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// ImageRemove removes an image from the docker host.
|
||||
func (cli *Client) ImageRemove(ctx context.Context, imageID string, options ImageRemoveOptions) ([]image.DeleteResponse, error) {
|
||||
func (cli *Client) ImageRemove(ctx context.Context, imageID string, options ImageRemoveOptions) (ImageRemoveResult, error) {
|
||||
query := url.Values{}
|
||||
|
||||
if options.Force {
|
||||
@@ -22,7 +22,7 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options Imag
|
||||
if len(options.Platforms) > 0 {
|
||||
p, err := encodePlatforms(options.Platforms...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ImageRemoveResult{}, err
|
||||
}
|
||||
query["platforms"] = p
|
||||
}
|
||||
@@ -30,10 +30,10 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options Imag
|
||||
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ImageRemoveResult{}, err
|
||||
}
|
||||
|
||||
var dels []image.DeleteResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&dels)
|
||||
return dels, err
|
||||
return ImageRemoveResult{Deleted: dels}, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package client
|
||||
|
||||
import ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
import (
|
||||
"github.com/moby/moby/api/types/image"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// ImageRemoveOptions holds parameters to remove images.
|
||||
type ImageRemoveOptions struct {
|
||||
@@ -8,3 +11,8 @@ type ImageRemoveOptions struct {
|
||||
Force bool
|
||||
PruneChildren bool
|
||||
}
|
||||
|
||||
// ImageRemoveResult holds the delete responses returned by the daemon.
|
||||
type ImageRemoveResult struct {
|
||||
Deleted []image.DeleteResponse
|
||||
}
|
||||
|
||||
@@ -108,6 +108,6 @@ func TestImageRemove(t *testing.T) {
|
||||
|
||||
imageDeletes, err := client.ImageRemove(context.Background(), "image_id", opts)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Len(imageDeletes, 2))
|
||||
assert.Check(t, is.Len(imageDeletes.Deleted, 2))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
// ImageSearch makes the docker host search by a term in a remote registry.
|
||||
// The list of results is not sorted in any fashion.
|
||||
func (cli *Client) ImageSearch(ctx context.Context, term string, options ImageSearchOptions) ([]registry.SearchResult, error) {
|
||||
func (cli *Client) ImageSearch(ctx context.Context, term string, options ImageSearchOptions) (ImageSearchResult, error) {
|
||||
var results []registry.SearchResult
|
||||
query := url.Values{}
|
||||
query.Set("term", term)
|
||||
@@ -28,16 +28,16 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options ImageSe
|
||||
if cerrdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
|
||||
newAuthHeader, privilegeErr := options.PrivilegeFunc(ctx)
|
||||
if privilegeErr != nil {
|
||||
return results, privilegeErr
|
||||
return ImageSearchResult{}, privilegeErr
|
||||
}
|
||||
resp, err = cli.tryImageSearch(ctx, query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
return results, err
|
||||
return ImageSearchResult{}, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&results)
|
||||
return results, err
|
||||
return ImageSearchResult{Items: results}, err
|
||||
}
|
||||
|
||||
func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (*http.Response, error) {
|
||||
|
||||
@@ -2,8 +2,15 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/moby/moby/api/types/registry"
|
||||
)
|
||||
|
||||
// ImageSearchResult wraps results returned by ImageSearch.
|
||||
type ImageSearchResult struct {
|
||||
Items []registry.SearchResult
|
||||
}
|
||||
|
||||
// ImageSearchOptions holds parameters to search images with.
|
||||
type ImageSearchOptions struct {
|
||||
RegistryAuth string
|
||||
|
||||
@@ -97,7 +97,7 @@ func TestImageSearchWithPrivilegedFuncNoError(t *testing.T) {
|
||||
PrivilegeFunc: privilegeFunc,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Len(results, 1))
|
||||
assert.Check(t, is.Len(results.Items, 1))
|
||||
}
|
||||
|
||||
func TestImageSearchWithoutErrors(t *testing.T) {
|
||||
@@ -135,5 +135,5 @@ func TestImageSearchWithoutErrors(t *testing.T) {
|
||||
Filters: make(Filters).Add("is-automated", "true").Add("stars", "3"),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Len(results, 1))
|
||||
assert.Check(t, is.Len(results.Items, 1))
|
||||
}
|
||||
|
||||
@@ -9,19 +9,29 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
)
|
||||
|
||||
type ImageTagOptions struct {
|
||||
Source string
|
||||
Target string
|
||||
}
|
||||
|
||||
type ImageTagResult struct{}
|
||||
|
||||
// ImageTag tags an image in the docker host
|
||||
func (cli *Client) ImageTag(ctx context.Context, source, target string) error {
|
||||
func (cli *Client) ImageTag(ctx context.Context, options ImageTagOptions) (ImageTagResult, error) {
|
||||
source := options.Source
|
||||
target := options.Target
|
||||
|
||||
if _, err := reference.ParseAnyReference(source); err != nil {
|
||||
return fmt.Errorf("error parsing reference: %q is not a valid repository/tag: %w", source, err)
|
||||
return ImageTagResult{}, fmt.Errorf("error parsing reference: %q is not a valid repository/tag: %w", source, err)
|
||||
}
|
||||
|
||||
ref, err := reference.ParseNormalizedNamed(target)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing reference: %q is not a valid repository/tag: %w", target, err)
|
||||
return ImageTagResult{}, fmt.Errorf("error parsing reference: %q is not a valid repository/tag: %w", target, err)
|
||||
}
|
||||
|
||||
if _, ok := ref.(reference.Digested); ok {
|
||||
return errors.New("refusing to create a tag with a digest reference")
|
||||
return ImageTagResult{}, errors.New("refusing to create a tag with a digest reference")
|
||||
}
|
||||
|
||||
ref = reference.TagNameOnly(ref)
|
||||
@@ -34,5 +44,5 @@ func (cli *Client) ImageTag(ctx context.Context, source, target string) error {
|
||||
|
||||
resp, err := cli.post(ctx, "/images/"+source+"/tag", query, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
return err
|
||||
return ImageTagResult{}, err
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestImageTagError(t *testing.T) {
|
||||
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ImageTag(context.Background(), "image_id", "repo:tag")
|
||||
_, err = client.ImageTag(context.Background(), ImageTagOptions{Source: "image_id", Target: "repo:tag"})
|
||||
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func TestImageTagInvalidReference(t *testing.T) {
|
||||
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ImageTag(context.Background(), "image_id", "aa/asdf$$^/aa")
|
||||
_, err = client.ImageTag(context.Background(), ImageTagOptions{Source: "image_id", Target: "aa/asdf$$^/aa"})
|
||||
assert.Check(t, is.Error(err, `error parsing reference: "aa/asdf$$^/aa" is not a valid repository/tag: invalid reference format`))
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestImageTagInvalidSourceImageName(t *testing.T) {
|
||||
for _, repo := range invalidRepos {
|
||||
t.Run("invalidRepo/"+repo, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := client.ImageTag(ctx, "busybox", repo)
|
||||
_, err := client.ImageTag(ctx, ImageTagOptions{Source: "busybox", Target: repo})
|
||||
assert.Check(t, is.ErrorContains(err, "not a valid repository/tag"))
|
||||
})
|
||||
}
|
||||
@@ -53,26 +53,26 @@ func TestImageTagInvalidSourceImageName(t *testing.T) {
|
||||
for _, repotag := range invalidTags {
|
||||
t.Run("invalidTag/"+repotag, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := client.ImageTag(ctx, "busybox", repotag)
|
||||
_, err := client.ImageTag(ctx, ImageTagOptions{Source: "busybox", Target: repotag})
|
||||
assert.Check(t, is.ErrorContains(err, "not a valid repository/tag"))
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("test repository name begin with '-'", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := client.ImageTag(ctx, "busybox:latest", "-busybox:test")
|
||||
_, err := client.ImageTag(ctx, ImageTagOptions{Source: "busybox:latest", Target: "-busybox:test"})
|
||||
assert.Check(t, is.ErrorContains(err, "error parsing reference"))
|
||||
})
|
||||
|
||||
t.Run("test namespace name begin with '-'", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := client.ImageTag(ctx, "busybox:latest", "-test/busybox:test")
|
||||
_, err := client.ImageTag(ctx, ImageTagOptions{Source: "busybox:latest", Target: "-test/busybox:test"})
|
||||
assert.Check(t, is.ErrorContains(err, "error parsing reference"))
|
||||
})
|
||||
|
||||
t.Run("test index name begin with '-'", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := client.ImageTag(ctx, "busybox:latest", "-index:5000/busybox:test")
|
||||
_, err := client.ImageTag(ctx, ImageTagOptions{Source: "busybox:latest", Target: "-index:5000/busybox:test"})
|
||||
assert.Check(t, is.ErrorContains(err, "error parsing reference"))
|
||||
})
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func TestImageTagHexSource(t *testing.T) {
|
||||
client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusOK, "OK")))
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ImageTag(context.Background(), "0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", "repo:tag")
|
||||
_, err = client.ImageTag(context.Background(), ImageTagOptions{Source: "0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", Target: "repo:tag"})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ func TestImageTag(t *testing.T) {
|
||||
}, nil
|
||||
}))
|
||||
assert.NilError(t, err)
|
||||
err = client.ImageTag(context.Background(), "image_id", tagCase.reference)
|
||||
_, err = client.ImageTag(context.Background(), ImageTagOptions{Source: "image_id", Target: tagCase.reference})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ func (s *DockerRegistrySuite) TestBuildCopyFromForcePull(c *testing.T) {
|
||||
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
|
||||
// tag the image to upload it to the private registry
|
||||
ctx := testutil.GetContext(c)
|
||||
err := apiClient.ImageTag(ctx, "busybox", repoName)
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox", Target: repoName})
|
||||
assert.Check(c, err)
|
||||
// push the image to the registry
|
||||
rc, err := apiClient.ImagePush(ctx, repoName, client.ImagePushOptions{RegistryAuth: "{}"})
|
||||
|
||||
@@ -102,10 +102,10 @@ func (s *DockerAPISuite) TestAPIImagesSizeCompatibility(c *testing.T) {
|
||||
apiclient := testEnv.APIClient()
|
||||
defer apiclient.Close()
|
||||
|
||||
images, err := apiclient.ImageList(testutil.GetContext(c), client.ImageListOptions{})
|
||||
imageList, err := apiclient.ImageList(testutil.GetContext(c), client.ImageListOptions{})
|
||||
assert.NilError(c, err)
|
||||
assert.Assert(c, len(images) != 0)
|
||||
for _, img := range images {
|
||||
assert.Assert(c, len(imageList.Items) != 0)
|
||||
for _, img := range imageList.Items {
|
||||
assert.Assert(c, img.Size != int64(-1))
|
||||
}
|
||||
|
||||
@@ -115,8 +115,8 @@ func (s *DockerAPISuite) TestAPIImagesSizeCompatibility(c *testing.T) {
|
||||
|
||||
v124Images, err := apiclient.ImageList(testutil.GetContext(c), client.ImageListOptions{})
|
||||
assert.NilError(c, err)
|
||||
assert.Assert(c, len(v124Images) != 0)
|
||||
for _, img := range v124Images {
|
||||
assert.Assert(c, len(v124Images.Items) != 0)
|
||||
for _, img := range v124Images.Items {
|
||||
assert.Assert(c, img.Size != int64(-1))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -800,9 +800,9 @@ func TestBuildHistoryDoesNotPreventRemoval(t *testing.T) {
|
||||
err := buildImage("history-a")
|
||||
assert.NilError(t, err)
|
||||
|
||||
resp, err := apiClient.ImageRemove(ctx, "history-a", client.ImageRemoveOptions{})
|
||||
res, err := apiClient.ImageRemove(ctx, "history-a", client.ImageRemoveOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, slices.ContainsFunc(resp, func(r image.DeleteResponse) bool {
|
||||
assert.Check(t, slices.ContainsFunc(res.Deleted, func(r image.DeleteResponse) bool {
|
||||
return r.Deleted != ""
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -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.Items[0].ID))
|
||||
}
|
||||
|
||||
// TestExportContainerAfterDaemonRestart checks that a container
|
||||
|
||||
@@ -136,7 +136,7 @@ func TestMigrateSaveLoad(t *testing.T) {
|
||||
// Delete all images
|
||||
list, err := apiClient.ImageList(ctx, client.ImageListOptions{})
|
||||
assert.NilError(t, err)
|
||||
for _, i := range list {
|
||||
for _, i := range list.Items {
|
||||
_, err = apiClient.ImageRemove(ctx, i.ID, client.ImageRemoveOptions{Force: true})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func TestImageInspectUniqueRepoDigests(t *testing.T) {
|
||||
|
||||
for _, tag := range []string{"master", "newest"} {
|
||||
imgName := "busybox:" + tag
|
||||
err := apiClient.ImageTag(ctx, "busybox", imgName)
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox", Target: imgName})
|
||||
assert.NilError(t, err)
|
||||
defer func() {
|
||||
_, _ = apiClient.ImageRemove(ctx, imgName, client.ImageRemoveOptions{Force: true})
|
||||
|
||||
@@ -36,19 +36,19 @@ func TestImagesFilterMultiReference(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, repoTag := range repoTags {
|
||||
err := apiClient.ImageTag(ctx, "busybox:latest", repoTag)
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox:latest", Target: repoTag})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
options := client.ImageListOptions{
|
||||
Filters: make(client.Filters).Add("reference", repoTags[:3]...),
|
||||
}
|
||||
images, err := apiClient.ImageList(ctx, options)
|
||||
imageList, err := apiClient.ImageList(ctx, options)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, is.Len(images, 1))
|
||||
assert.Check(t, is.Len(images[0].RepoTags, 3))
|
||||
for _, repoTag := range images[0].RepoTags {
|
||||
assert.Assert(t, is.Len(imageList.Items, 1))
|
||||
assert.Check(t, is.Len(imageList.Items[0].RepoTags, 3))
|
||||
for _, repoTag := range imageList.Items[0].RepoTags {
|
||||
if repoTag != repoTags[0] && repoTag != repoTags[1] && repoTag != repoTags[2] {
|
||||
t.Errorf("list images doesn't match any repoTag we expected, repoTag: %s", repoTag)
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func TestImagesFilterUntil(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
var listedIDs []string
|
||||
for _, i := range list {
|
||||
for _, i := range list.Items {
|
||||
t.Logf("ImageList: ID=%v RepoTags=%v", i.ID, i.RepoTags)
|
||||
listedIDs = append(listedIDs, i.ID)
|
||||
}
|
||||
@@ -124,7 +124,7 @@ func TestImagesFilterBeforeSince(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
var listedIDs []string
|
||||
for _, i := range list {
|
||||
for _, i := range list.Items {
|
||||
t.Logf("ImageList: ID=%v RepoTags=%v", i.ID, i.RepoTags)
|
||||
listedIDs = append(listedIDs, i.ID)
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func TestAPIImagesFilters(t *testing.T) {
|
||||
apiClient := testEnv.APIClient()
|
||||
|
||||
for _, n := range []string{"utest:tag1", "utest/docker:tag2", "utest:5000/docker:tag3"} {
|
||||
err := apiClient.ImageTag(ctx, "busybox:latest", n)
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox:latest", Target: n})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
@@ -181,12 +181,12 @@ func TestAPIImagesFilters(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := testutil.StartSpan(ctx, t)
|
||||
images, err := apiClient.ImageList(ctx, client.ImageListOptions{
|
||||
imageList, err := apiClient.ImageList(ctx, client.ImageListOptions{
|
||||
Filters: tc.filters,
|
||||
})
|
||||
assert.Check(t, err)
|
||||
assert.Assert(t, is.Len(images, tc.expectedImages))
|
||||
assert.Check(t, is.Len(images[0].RepoTags, tc.expectedRepoTags))
|
||||
assert.Assert(t, is.Len(imageList.Items, tc.expectedImages))
|
||||
assert.Check(t, is.Len(imageList.Items[0].RepoTags, tc.expectedRepoTags))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -255,31 +255,31 @@ func TestAPIImagesListManifests(t *testing.T) {
|
||||
// TODO: Remove when MinAPIVersion >= 1.47
|
||||
c := d.NewClientT(t, client.WithVersion("1.46"))
|
||||
|
||||
images, err := c.ImageList(ctx, client.ImageListOptions{Manifests: true})
|
||||
imageList, err := c.ImageList(ctx, client.ImageListOptions{Manifests: true})
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, is.Len(images, 1))
|
||||
assert.Check(t, is.Nil(images[0].Manifests))
|
||||
assert.Assert(t, is.Len(imageList.Items, 1))
|
||||
assert.Check(t, is.Nil(imageList.Items[0].Manifests))
|
||||
})
|
||||
|
||||
api147 := d.NewClientT(t, client.WithVersion("1.47"))
|
||||
|
||||
t.Run("no manifests if not requested", func(t *testing.T) {
|
||||
images, err := api147.ImageList(ctx, client.ImageListOptions{})
|
||||
imageList, err := api147.ImageList(ctx, client.ImageListOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, is.Len(images, 1))
|
||||
assert.Check(t, is.Nil(images[0].Manifests))
|
||||
assert.Assert(t, is.Len(imageList.Items, 1))
|
||||
assert.Check(t, is.Nil(imageList.Items[0].Manifests))
|
||||
})
|
||||
|
||||
images, err := api147.ImageList(ctx, client.ImageListOptions{Manifests: true})
|
||||
imageList, err := api147.ImageList(ctx, client.ImageListOptions{Manifests: true})
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Len(images, 1))
|
||||
assert.Check(t, images[0].Manifests != nil)
|
||||
assert.Check(t, is.Len(images[0].Manifests, 3))
|
||||
assert.Check(t, is.Len(imageList.Items, 1))
|
||||
assert.Check(t, imageList.Items[0].Manifests != nil)
|
||||
assert.Check(t, is.Len(imageList.Items[0].Manifests, 3))
|
||||
|
||||
for _, mfst := range images[0].Manifests {
|
||||
for _, mfst := range imageList.Items[0].Manifests {
|
||||
// All manifests should be image manifests
|
||||
assert.Check(t, is.Equal(mfst.Kind, image.ManifestKindImage))
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestLoadDanglingImages(t *testing.T) {
|
||||
})
|
||||
|
||||
// Should be one image.
|
||||
images, err := apiClient.ImageList(ctx, client.ImageListOptions{})
|
||||
imageList, err := apiClient.ImageList(ctx, client.ImageListOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
findImageByName := func(images []image.Summary, imageName string) (image.Summary, error) {
|
||||
@@ -42,7 +42,7 @@ func TestLoadDanglingImages(t *testing.T) {
|
||||
return images[index], nil
|
||||
}
|
||||
|
||||
oldImage, err := findImageByName(images, "namedimage:latest")
|
||||
oldImage, err := findImageByName(imageList.Items, "namedimage:latest")
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Retain a copy of the old image and then replace it with a new one.
|
||||
@@ -52,10 +52,10 @@ func TestLoadDanglingImages(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
images, err = apiClient.ImageList(ctx, client.ImageListOptions{})
|
||||
imageList, err = apiClient.ImageList(ctx, client.ImageListOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
newImage, err := findImageByName(images, "namedimage:latest")
|
||||
newImage, err := findImageByName(imageList.Items, "namedimage:latest")
|
||||
assert.NilError(t, err)
|
||||
|
||||
// IDs should be different.
|
||||
@@ -72,7 +72,7 @@ func TestLoadDanglingImages(t *testing.T) {
|
||||
return images[index], nil
|
||||
}
|
||||
|
||||
danglingImage, err := findImageById(images, oldImage.ID)
|
||||
danglingImage, err := findImageById(imageList.Items, oldImage.ID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Len(danglingImage.RepoTags, 0))
|
||||
}
|
||||
|
||||
@@ -74,10 +74,10 @@ func TestPruneLexographicalOrder(t *testing.T) {
|
||||
|
||||
tags := []string{"h", "a", "j", "o", "s", "q", "w", "e", "r", "t"}
|
||||
for _, tag := range tags {
|
||||
err = apiClient.ImageTag(ctx, id, "busybox:"+tag)
|
||||
_, err = apiClient.ImageTag(ctx, client.ImageTagOptions{Source: id, Target: "busybox:" + tag})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
err = apiClient.ImageTag(ctx, id, "busybox:z")
|
||||
_, err = apiClient.ImageTag(ctx, client.ImageTagOptions{Source: id, Target: "busybox:z"})
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = apiClient.ImageRemove(ctx, "busybox:latest", client.ImageRemoveOptions{Force: true})
|
||||
@@ -127,7 +127,8 @@ func TestPruneDontDeleteUsedImage(t *testing.T) {
|
||||
// busybox:other tag pointing to the same image.
|
||||
name: "two tags",
|
||||
prepare: func(t *testing.T, d *daemon.Daemon, apiClient *client.Client) error {
|
||||
return apiClient.ImageTag(ctx, "busybox:latest", "busybox:a")
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox:latest", Target: "busybox:a"})
|
||||
return err
|
||||
},
|
||||
check: func(t *testing.T, apiClient *client.Client, pruned image.PruneReport) {
|
||||
if assert.Check(t, is.Len(pruned.ImagesDeleted, 1)) {
|
||||
|
||||
@@ -216,7 +216,8 @@ func TestImagePullKeepOldAsDangling(t *testing.T) {
|
||||
|
||||
t.Log(inspect1)
|
||||
|
||||
assert.NilError(t, apiClient.ImageTag(ctx, "busybox:latest", "alpine:latest"))
|
||||
_, err = apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox:latest", Target: "alpine:latest"})
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = apiClient.ImageRemove(ctx, "busybox:latest", client.ImageRemoveOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
@@ -71,7 +71,7 @@ func TestRemoveByDigest(t *testing.T) {
|
||||
ctx := setupTest(t)
|
||||
apiClient := testEnv.APIClient()
|
||||
|
||||
err := apiClient.ImageTag(ctx, "busybox", "test-remove-by-digest:latest")
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox", Target: "test-remove-by-digest:latest"})
|
||||
assert.NilError(t, err)
|
||||
|
||||
inspect, err := apiClient.ImageInspect(ctx, "test-remove-by-digest")
|
||||
@@ -142,25 +142,25 @@ func TestRemoveWithPlatform(t *testing.T) {
|
||||
{platform: &platformHost, deleted: descs[0]},
|
||||
{platform: &someOtherPlatform, deleted: descs[3]},
|
||||
} {
|
||||
resp, err := apiClient.ImageRemove(ctx, imgName, client.ImageRemoveOptions{
|
||||
res, err := apiClient.ImageRemove(ctx, imgName, client.ImageRemoveOptions{
|
||||
Platforms: []ocispec.Platform{*tc.platform},
|
||||
Force: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Len(resp, 1))
|
||||
for _, r := range resp {
|
||||
assert.Check(t, is.Len(res.Deleted, 1))
|
||||
for _, r := range res.Deleted {
|
||||
assert.Check(t, is.Equal(r.Untagged, ""), "No image should be untagged")
|
||||
}
|
||||
checkPlatformDeleted(t, imageIdx, resp, tc.deleted)
|
||||
checkPlatformDeleted(t, imageIdx, res.Deleted, tc.deleted)
|
||||
}
|
||||
|
||||
// Delete the rest
|
||||
resp, err := apiClient.ImageRemove(ctx, imgName, client.ImageRemoveOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Len(resp, 2))
|
||||
assert.Check(t, is.Equal(resp[0].Untagged, imgName))
|
||||
assert.Check(t, is.Equal(resp[1].Deleted, imageIdx.Manifests[0].Digest.String()))
|
||||
assert.Check(t, is.Len(resp.Deleted, 2))
|
||||
assert.Check(t, is.Equal(resp.Deleted[0].Untagged, imgName))
|
||||
assert.Check(t, is.Equal(resp.Deleted[1].Deleted, imageIdx.Manifests[0].Digest.String()))
|
||||
// TODO(vvoland): Should it also include platform-specific manifests? https://github.com/moby/moby/pull/49982
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/moby/moby/client"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
@@ -12,23 +13,23 @@ import (
|
||||
func TestTagUnprefixedRepoByNameOrName(t *testing.T) {
|
||||
ctx := setupTest(t)
|
||||
|
||||
client := testEnv.APIClient()
|
||||
apiClient := testEnv.APIClient()
|
||||
|
||||
// By name
|
||||
err := client.ImageTag(ctx, "busybox:latest", "testfoobarbaz")
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox:latest", Target: "testfoobarbaz"})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// By ID
|
||||
insp, err := client.ImageInspect(ctx, "busybox")
|
||||
insp, err := apiClient.ImageInspect(ctx, "busybox")
|
||||
assert.NilError(t, err)
|
||||
err = client.ImageTag(ctx, insp.ID, "testfoobarbaz")
|
||||
_, err = apiClient.ImageTag(ctx, client.ImageTagOptions{Source: insp.ID, Target: "testfoobarbaz"})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestTagUsingDigestAlgorithmAsName(t *testing.T) {
|
||||
ctx := setupTest(t)
|
||||
client := testEnv.APIClient()
|
||||
err := client.ImageTag(ctx, "busybox:latest", "sha256:sometag")
|
||||
apiClient := testEnv.APIClient()
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox:latest", Target: "sha256:sometag"})
|
||||
assert.Check(t, is.ErrorContains(err, "refusing to create an ambiguous tag using digest algorithm as name"))
|
||||
}
|
||||
|
||||
@@ -36,14 +37,14 @@ func TestTagUsingDigestAlgorithmAsName(t *testing.T) {
|
||||
func TestTagValidPrefixedRepo(t *testing.T) {
|
||||
ctx := setupTest(t)
|
||||
|
||||
client := testEnv.APIClient()
|
||||
apiClient := testEnv.APIClient()
|
||||
|
||||
validRepos := []string{"fooo/bar", "fooaa/test", "foooo:t", "HOSTNAME.DOMAIN.COM:443/foo/bar"}
|
||||
|
||||
for _, repo := range validRepos {
|
||||
t.Run(repo, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := client.ImageTag(ctx, "busybox", repo)
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox", Target: repo})
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
}
|
||||
@@ -52,9 +53,9 @@ func TestTagValidPrefixedRepo(t *testing.T) {
|
||||
// tag an image with an existed tag name without -f option should work
|
||||
func TestTagExistedNameWithoutForce(t *testing.T) {
|
||||
ctx := setupTest(t)
|
||||
client := testEnv.APIClient()
|
||||
apiClient := testEnv.APIClient()
|
||||
|
||||
err := client.ImageTag(ctx, "busybox:latest", "busybox:test")
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox:latest", Target: "busybox:test"})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ func TestTagExistedNameWithoutForce(t *testing.T) {
|
||||
// ensure all tags result in the same name
|
||||
func TestTagOfficialNames(t *testing.T) {
|
||||
ctx := setupTest(t)
|
||||
client := testEnv.APIClient()
|
||||
apiClient := testEnv.APIClient()
|
||||
|
||||
names := []string{
|
||||
"docker.io/busybox",
|
||||
@@ -74,16 +75,16 @@ func TestTagOfficialNames(t *testing.T) {
|
||||
|
||||
for _, name := range names {
|
||||
t.Run("tag from busybox to "+name, func(t *testing.T) {
|
||||
err := client.ImageTag(ctx, "busybox", name+":latest")
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox", Target: name + ":latest"})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// ensure we don't have multiple tag names.
|
||||
insp, err := client.ImageInspect(ctx, "busybox")
|
||||
insp, err := apiClient.ImageInspect(ctx, "busybox")
|
||||
assert.NilError(t, err)
|
||||
// TODO(vvoland): Not sure what's actually being tested here. Is is still doing anything useful?
|
||||
assert.Assert(t, !is.Contains(insp.RepoTags, name)().Success())
|
||||
|
||||
err = client.ImageTag(ctx, name+":latest", "test-tag-official-names/foobar:latest")
|
||||
_, err = apiClient.ImageTag(ctx, client.ImageTagOptions{Source: name + ":latest", Target: "test-tag-official-names/foobar:latest"})
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
}
|
||||
@@ -92,14 +93,14 @@ func TestTagOfficialNames(t *testing.T) {
|
||||
// ensure tags can not match digests
|
||||
func TestTagMatchesDigest(t *testing.T) {
|
||||
ctx := setupTest(t)
|
||||
client := testEnv.APIClient()
|
||||
apiClient := testEnv.APIClient()
|
||||
|
||||
digest := "busybox@sha256:abcdef76720241213f5303bda7704ec4c2ef75613173910a56fb1b6e20251507"
|
||||
// test setting tag fails
|
||||
err := client.ImageTag(ctx, "busybox:latest", digest)
|
||||
_, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: "busybox:latest", Target: digest})
|
||||
assert.Check(t, is.ErrorContains(err, "refusing to create a tag with a digest reference"))
|
||||
|
||||
// check that no new image matches the digest
|
||||
_, err = client.ImageInspect(ctx, digest)
|
||||
_, err = apiClient.ImageInspect(ctx, digest)
|
||||
assert.Check(t, is.ErrorContains(err, fmt.Sprintf("No such image: %s", digest)))
|
||||
}
|
||||
|
||||
@@ -94,10 +94,10 @@ func getAllContainers(ctx context.Context, t testing.TB, apiClient client.Contai
|
||||
|
||||
func deleteAllImages(ctx context.Context, t testing.TB, apiclient client.ImageAPIClient, protectedImages map[string]struct{}) {
|
||||
t.Helper()
|
||||
images, err := apiclient.ImageList(ctx, client.ImageListOptions{})
|
||||
imageList, err := apiclient.ImageList(ctx, client.ImageListOptions{})
|
||||
assert.Check(t, err, "failed to list images")
|
||||
|
||||
for _, img := range images {
|
||||
for _, img := range imageList.Items {
|
||||
tags := tagsFromImageSummary(img)
|
||||
if _, ok := protectedImages[img.ID]; ok {
|
||||
continue
|
||||
|
||||
@@ -205,7 +205,7 @@ func (e *Execution) HasExistingImage(t testing.TB, reference string) bool {
|
||||
})
|
||||
assert.NilError(t, err, "failed to list images")
|
||||
|
||||
return len(imageList) > 0
|
||||
return len(imageList.Items) > 0
|
||||
}
|
||||
|
||||
// EnsureFrozenImagesLinux loads frozen test images into the daemon
|
||||
|
||||
@@ -121,7 +121,7 @@ func getExistingImages(ctx context.Context, t testing.TB, testEnv *Execution) []
|
||||
assert.NilError(t, err, "failed to list images")
|
||||
|
||||
var images []string
|
||||
for _, img := range imageList {
|
||||
for _, img := range imageList.Items {
|
||||
images = append(images, tagsFromImageSummary(img)...)
|
||||
}
|
||||
return images
|
||||
|
||||
@@ -70,7 +70,7 @@ func FrozenImagesLinux(ctx context.Context, apiClient client.APIClient, images .
|
||||
|
||||
for _, img := range loadImages {
|
||||
if img.srcName != img.destName {
|
||||
if err := apiClient.ImageTag(ctx, img.srcName, img.destName); err != nil {
|
||||
if _, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: img.srcName, Target: img.destName}); err != nil {
|
||||
return errors.Wrapf(err, "failed to tag %s as %s", img.srcName, img.destName)
|
||||
}
|
||||
if _, err := apiClient.ImageRemove(ctx, img.srcName, client.ImageRemoveOptions{}); err != nil {
|
||||
@@ -171,7 +171,7 @@ func pullTagAndRemove(ctx context.Context, apiClient client.APIClient, ref strin
|
||||
return err
|
||||
}
|
||||
|
||||
if err := apiClient.ImageTag(ctx, ref, tag); err != nil {
|
||||
if _, err := apiClient.ImageTag(ctx, client.ImageTagOptions{Source: ref, Target: tag}); err != nil {
|
||||
return errors.Wrapf(err, "failed to tag %s as %s", ref, tag)
|
||||
}
|
||||
_, err = apiClient.ImageRemove(ctx, ref, client.ImageRemoveOptions{})
|
||||
|
||||
6
vendor/github.com/moby/moby/client/build_cancel.go
generated
vendored
6
vendor/github.com/moby/moby/client/build_cancel.go
generated
vendored
@@ -7,13 +7,15 @@ import (
|
||||
|
||||
type BuildCancelOptions struct{}
|
||||
|
||||
type BuildCancelResult struct{}
|
||||
|
||||
// BuildCancel requests the daemon to cancel the ongoing build request
|
||||
// with the given id.
|
||||
func (cli *Client) BuildCancel(ctx context.Context, id string, _ BuildCancelOptions) error {
|
||||
func (cli *Client) BuildCancel(ctx context.Context, id string, _ BuildCancelOptions) (BuildCancelResult, error) {
|
||||
query := url.Values{}
|
||||
query.Set("id", id)
|
||||
|
||||
resp, err := cli.post(ctx, "/build/cancel", query, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
return err
|
||||
return BuildCancelResult{}, err
|
||||
}
|
||||
|
||||
17
vendor/github.com/moby/moby/client/client_interfaces.go
generated
vendored
17
vendor/github.com/moby/moby/client/client_interfaces.go
generated
vendored
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/moby/moby/api/types"
|
||||
"github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/api/types/events"
|
||||
"github.com/moby/moby/api/types/image"
|
||||
"github.com/moby/moby/api/types/network"
|
||||
"github.com/moby/moby/api/types/plugin"
|
||||
"github.com/moby/moby/api/types/registry"
|
||||
@@ -105,18 +104,18 @@ type DistributionAPIClient interface {
|
||||
|
||||
// ImageAPIClient defines API client methods for the images
|
||||
type ImageAPIClient interface {
|
||||
ImageBuild(ctx context.Context, context io.Reader, options ImageBuildOptions) (ImageBuildResponse, error)
|
||||
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) 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)
|
||||
BuildCancel(ctx context.Context, id string, opts BuildCancelOptions) (BuildCancelResult, 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)
|
||||
ImageList(ctx context.Context, options ImageListOptions) (ImageListResult, error)
|
||||
ImagePull(ctx context.Context, ref string, options ImagePullOptions) (ImagePullResponse, error)
|
||||
ImagePush(ctx context.Context, ref string, options ImagePushOptions) (ImagePushResponse, error)
|
||||
ImageRemove(ctx context.Context, image string, options ImageRemoveOptions) ([]image.DeleteResponse, error)
|
||||
ImageSearch(ctx context.Context, term string, options ImageSearchOptions) ([]registry.SearchResult, error)
|
||||
ImageTag(ctx context.Context, image, ref string) error
|
||||
ImageRemove(ctx context.Context, image string, options ImageRemoveOptions) (ImageRemoveResult, error)
|
||||
ImageSearch(ctx context.Context, term string, options ImageSearchOptions) (ImageSearchResult, error)
|
||||
ImageTag(ctx context.Context, options ImageTagOptions) (ImageTagResult, error)
|
||||
ImagesPrune(ctx context.Context, opts ImagePruneOptions) (ImagePruneResult, error)
|
||||
|
||||
ImageInspect(ctx context.Context, image string, _ ...ImageInspectOption) (ImageInspectResult, error)
|
||||
|
||||
10
vendor/github.com/moby/moby/client/image_build.go
generated
vendored
10
vendor/github.com/moby/moby/client/image_build.go
generated
vendored
@@ -17,15 +17,15 @@ import (
|
||||
// ImageBuild sends a request to the daemon to build images.
|
||||
// The Body in the response implements an [io.ReadCloser] and it's up to the caller to
|
||||
// close it.
|
||||
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options ImageBuildOptions) (ImageBuildResponse, error) {
|
||||
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options ImageBuildOptions) (ImageBuildResult, error) {
|
||||
query, err := cli.imageBuildOptionsToQuery(ctx, options)
|
||||
if err != nil {
|
||||
return ImageBuildResponse{}, err
|
||||
return ImageBuildResult{}, err
|
||||
}
|
||||
|
||||
buf, err := json.Marshal(options.AuthConfigs)
|
||||
if err != nil {
|
||||
return ImageBuildResponse{}, err
|
||||
return ImageBuildResult{}, err
|
||||
}
|
||||
|
||||
headers := http.Header{}
|
||||
@@ -34,10 +34,10 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
||||
|
||||
resp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
|
||||
if err != nil {
|
||||
return ImageBuildResponse{}, err
|
||||
return ImageBuildResult{}, err
|
||||
}
|
||||
|
||||
return ImageBuildResponse{
|
||||
return ImageBuildResult{
|
||||
Body: resp.Body,
|
||||
}, nil
|
||||
}
|
||||
|
||||
4
vendor/github.com/moby/moby/client/image_build_opts.go
generated
vendored
4
vendor/github.com/moby/moby/client/image_build_opts.go
generated
vendored
@@ -68,9 +68,9 @@ type ImageBuildOutput struct {
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
// ImageBuildResponse holds information
|
||||
// ImageBuildResult holds information
|
||||
// returned by a server after building
|
||||
// an image.
|
||||
type ImageBuildResponse struct {
|
||||
type ImageBuildResult struct {
|
||||
Body io.ReadCloser
|
||||
}
|
||||
|
||||
9
vendor/github.com/moby/moby/client/image_create.go
generated
vendored
9
vendor/github.com/moby/moby/client/image_create.go
generated
vendored
@@ -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) {
|
||||
|
||||
7
vendor/github.com/moby/moby/client/image_create_opts.go
generated
vendored
7
vendor/github.com/moby/moby/client/image_create_opts.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
9
vendor/github.com/moby/moby/client/image_import.go
generated
vendored
9
vendor/github.com/moby/moby/client/image_import.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
16
vendor/github.com/moby/moby/client/image_import_opts.go
generated
vendored
16
vendor/github.com/moby/moby/client/image_import_opts.go
generated
vendored
@@ -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()
|
||||
}
|
||||
|
||||
8
vendor/github.com/moby/moby/client/image_list.go
generated
vendored
8
vendor/github.com/moby/moby/client/image_list.go
generated
vendored
@@ -15,7 +15,7 @@ import (
|
||||
// to include [image.Summary.Manifests] with information about image manifests.
|
||||
// This is experimental and might change in the future without any backward
|
||||
// compatibility.
|
||||
func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]image.Summary, error) {
|
||||
func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) (ImageListResult, error) {
|
||||
var images []image.Summary
|
||||
|
||||
query := url.Values{}
|
||||
@@ -34,7 +34,7 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i
|
||||
// Normally, version-negotiation (if enabled) would not happen until
|
||||
// the API request is made.
|
||||
if err := cli.checkVersion(ctx); err != nil {
|
||||
return images, err
|
||||
return ImageListResult{}, err
|
||||
}
|
||||
|
||||
if versions.GreaterThanOrEqualTo(cli.version, "1.47") {
|
||||
@@ -45,9 +45,9 @@ func (cli *Client) ImageList(ctx context.Context, options ImageListOptions) ([]i
|
||||
resp, err := cli.get(ctx, "/images/json", query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return images, err
|
||||
return ImageListResult{}, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&images)
|
||||
return images, err
|
||||
return ImageListResult{Items: images}, err
|
||||
}
|
||||
|
||||
7
vendor/github.com/moby/moby/client/image_list_opts.go
generated
vendored
7
vendor/github.com/moby/moby/client/image_list_opts.go
generated
vendored
@@ -1,5 +1,7 @@
|
||||
package client
|
||||
|
||||
import "github.com/moby/moby/api/types/image"
|
||||
|
||||
// ImageListOptions holds parameters to list images with.
|
||||
type ImageListOptions struct {
|
||||
// All controls whether all images in the graph are filtered, or just
|
||||
@@ -15,3 +17,8 @@ type ImageListOptions struct {
|
||||
// Manifests indicates whether the image manifests should be returned.
|
||||
Manifests bool
|
||||
}
|
||||
|
||||
// ImageListResult holds the result from ImageList.
|
||||
type ImageListResult struct {
|
||||
Items []image.Summary
|
||||
}
|
||||
|
||||
8
vendor/github.com/moby/moby/client/image_remove.go
generated
vendored
8
vendor/github.com/moby/moby/client/image_remove.go
generated
vendored
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// ImageRemove removes an image from the docker host.
|
||||
func (cli *Client) ImageRemove(ctx context.Context, imageID string, options ImageRemoveOptions) ([]image.DeleteResponse, error) {
|
||||
func (cli *Client) ImageRemove(ctx context.Context, imageID string, options ImageRemoveOptions) (ImageRemoveResult, error) {
|
||||
query := url.Values{}
|
||||
|
||||
if options.Force {
|
||||
@@ -22,7 +22,7 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options Imag
|
||||
if len(options.Platforms) > 0 {
|
||||
p, err := encodePlatforms(options.Platforms...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ImageRemoveResult{}, err
|
||||
}
|
||||
query["platforms"] = p
|
||||
}
|
||||
@@ -30,10 +30,10 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options Imag
|
||||
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ImageRemoveResult{}, err
|
||||
}
|
||||
|
||||
var dels []image.DeleteResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&dels)
|
||||
return dels, err
|
||||
return ImageRemoveResult{Deleted: dels}, err
|
||||
}
|
||||
|
||||
10
vendor/github.com/moby/moby/client/image_remove_opts.go
generated
vendored
10
vendor/github.com/moby/moby/client/image_remove_opts.go
generated
vendored
@@ -1,6 +1,9 @@
|
||||
package client
|
||||
|
||||
import ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
import (
|
||||
"github.com/moby/moby/api/types/image"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// ImageRemoveOptions holds parameters to remove images.
|
||||
type ImageRemoveOptions struct {
|
||||
@@ -8,3 +11,8 @@ type ImageRemoveOptions struct {
|
||||
Force bool
|
||||
PruneChildren bool
|
||||
}
|
||||
|
||||
// ImageRemoveResult holds the delete responses returned by the daemon.
|
||||
type ImageRemoveResult struct {
|
||||
Deleted []image.DeleteResponse
|
||||
}
|
||||
|
||||
8
vendor/github.com/moby/moby/client/image_search.go
generated
vendored
8
vendor/github.com/moby/moby/client/image_search.go
generated
vendored
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
// ImageSearch makes the docker host search by a term in a remote registry.
|
||||
// The list of results is not sorted in any fashion.
|
||||
func (cli *Client) ImageSearch(ctx context.Context, term string, options ImageSearchOptions) ([]registry.SearchResult, error) {
|
||||
func (cli *Client) ImageSearch(ctx context.Context, term string, options ImageSearchOptions) (ImageSearchResult, error) {
|
||||
var results []registry.SearchResult
|
||||
query := url.Values{}
|
||||
query.Set("term", term)
|
||||
@@ -28,16 +28,16 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options ImageSe
|
||||
if cerrdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
|
||||
newAuthHeader, privilegeErr := options.PrivilegeFunc(ctx)
|
||||
if privilegeErr != nil {
|
||||
return results, privilegeErr
|
||||
return ImageSearchResult{}, privilegeErr
|
||||
}
|
||||
resp, err = cli.tryImageSearch(ctx, query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
return results, err
|
||||
return ImageSearchResult{}, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&results)
|
||||
return results, err
|
||||
return ImageSearchResult{Items: results}, err
|
||||
}
|
||||
|
||||
func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (*http.Response, error) {
|
||||
|
||||
7
vendor/github.com/moby/moby/client/image_search_opts.go
generated
vendored
7
vendor/github.com/moby/moby/client/image_search_opts.go
generated
vendored
@@ -2,8 +2,15 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/moby/moby/api/types/registry"
|
||||
)
|
||||
|
||||
// ImageSearchResult wraps results returned by ImageSearch.
|
||||
type ImageSearchResult struct {
|
||||
Items []registry.SearchResult
|
||||
}
|
||||
|
||||
// ImageSearchOptions holds parameters to search images with.
|
||||
type ImageSearchOptions struct {
|
||||
RegistryAuth string
|
||||
|
||||
20
vendor/github.com/moby/moby/client/image_tag.go
generated
vendored
20
vendor/github.com/moby/moby/client/image_tag.go
generated
vendored
@@ -9,19 +9,29 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
)
|
||||
|
||||
type ImageTagOptions struct {
|
||||
Source string
|
||||
Target string
|
||||
}
|
||||
|
||||
type ImageTagResult struct{}
|
||||
|
||||
// ImageTag tags an image in the docker host
|
||||
func (cli *Client) ImageTag(ctx context.Context, source, target string) error {
|
||||
func (cli *Client) ImageTag(ctx context.Context, options ImageTagOptions) (ImageTagResult, error) {
|
||||
source := options.Source
|
||||
target := options.Target
|
||||
|
||||
if _, err := reference.ParseAnyReference(source); err != nil {
|
||||
return fmt.Errorf("error parsing reference: %q is not a valid repository/tag: %w", source, err)
|
||||
return ImageTagResult{}, fmt.Errorf("error parsing reference: %q is not a valid repository/tag: %w", source, err)
|
||||
}
|
||||
|
||||
ref, err := reference.ParseNormalizedNamed(target)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing reference: %q is not a valid repository/tag: %w", target, err)
|
||||
return ImageTagResult{}, fmt.Errorf("error parsing reference: %q is not a valid repository/tag: %w", target, err)
|
||||
}
|
||||
|
||||
if _, ok := ref.(reference.Digested); ok {
|
||||
return errors.New("refusing to create a tag with a digest reference")
|
||||
return ImageTagResult{}, errors.New("refusing to create a tag with a digest reference")
|
||||
}
|
||||
|
||||
ref = reference.TagNameOnly(ref)
|
||||
@@ -34,5 +44,5 @@ func (cli *Client) ImageTag(ctx context.Context, source, target string) error {
|
||||
|
||||
resp, err := cli.post(ctx, "/images/"+source+"/tag", query, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
return err
|
||||
return ImageTagResult{}, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user