mirror of https://github.com/docker/cli.git
Compare commits
3 Commits
598ff6cc0c
...
75b4ca9f0d
Author | SHA1 | Date |
---|---|---|
Marc Cornellà | 75b4ca9f0d | |
Sebastiaan van Stijn | a93fb1678a | |
Sebastiaan van Stijn | d41b80fafc |
|
@ -78,7 +78,8 @@ func runLoad(ctx context.Context, dockerCli command.Cli, opts loadOptions) error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "invalid platform")
|
return errors.Wrap(err, "invalid platform")
|
||||||
}
|
}
|
||||||
options.Platform = &p
|
// TODO(thaJeztah): change flag-type to support multiple platforms.
|
||||||
|
options.Platforms = append(options.Platforms, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := dockerCli.Client().ImageLoad(ctx, input, options)
|
response, err := dockerCli.Client().ImageLoad(ctx, input, options)
|
||||||
|
|
|
@ -109,7 +109,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
|
||||||
name: "with platform",
|
name: "with platform",
|
||||||
args: []string{"--platform", "linux/amd64"},
|
args: []string{"--platform", "linux/amd64"},
|
||||||
imageLoadFunc: func(input io.Reader, options image.LoadOptions) (image.LoadResponse, error) {
|
imageLoadFunc: func(input io.Reader, options image.LoadOptions) (image.LoadResponse, error) {
|
||||||
assert.Check(t, is.DeepEqual(ocispec.Platform{OS: "linux", Architecture: "amd64"}, *options.Platform))
|
assert.Check(t, is.DeepEqual([]ocispec.Platform{{OS: "linux", Architecture: "amd64"}}, options.Platforms))
|
||||||
return image.LoadResponse{Body: io.NopCloser(strings.NewReader("Success"))}, nil
|
return image.LoadResponse{Body: io.NopCloser(strings.NewReader("Success"))}, nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -63,7 +63,8 @@ func RunSave(ctx context.Context, dockerCli command.Cli, opts saveOptions) error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "invalid platform")
|
return errors.Wrap(err, "invalid platform")
|
||||||
}
|
}
|
||||||
options.Platform = &p
|
// TODO(thaJeztah): change flag-type to support multiple platforms.
|
||||||
|
options.Platforms = append(options.Platforms, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
responseBody, err := dockerCli.Client().ImageSave(ctx, opts.images, options)
|
responseBody, err := dockerCli.Client().ImageSave(ctx, opts.images, options)
|
||||||
|
|
|
@ -106,7 +106,7 @@ func TestNewSaveCommandSuccess(t *testing.T) {
|
||||||
imageSaveFunc: func(images []string, options image.SaveOptions) (io.ReadCloser, error) {
|
imageSaveFunc: func(images []string, options image.SaveOptions) (io.ReadCloser, error) {
|
||||||
assert.Assert(t, is.Len(images, 1))
|
assert.Assert(t, is.Len(images, 1))
|
||||||
assert.Check(t, is.Equal("arg1", images[0]))
|
assert.Check(t, is.Equal("arg1", images[0]))
|
||||||
assert.Check(t, is.DeepEqual(ocispec.Platform{OS: "linux", Architecture: "amd64"}, *options.Platform))
|
assert.Check(t, is.DeepEqual([]ocispec.Platform{{OS: "linux", Architecture: "amd64"}}, options.Platforms))
|
||||||
return io.NopCloser(strings.NewReader("")), nil
|
return io.NopCloser(strings.NewReader("")), nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,7 +13,7 @@ require (
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/distribution/reference v0.6.0
|
||||||
github.com/docker/cli-docs-tool v0.8.0
|
github.com/docker/cli-docs-tool v0.8.0
|
||||||
github.com/docker/distribution v2.8.3+incompatible
|
github.com/docker/distribution v2.8.3+incompatible
|
||||||
github.com/docker/docker v27.0.2-0.20241031194140-6ac445c42bad+incompatible // master (v-next)
|
github.com/docker/docker v27.0.2-0.20241120142749-e5c2b5e10d68+incompatible // master (v-next)
|
||||||
github.com/docker/docker-credential-helpers v0.8.2
|
github.com/docker/docker-credential-helpers v0.8.2
|
||||||
github.com/docker/go-connections v0.5.0
|
github.com/docker/go-connections v0.5.0
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
|
|
|
@ -51,8 +51,8 @@ github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsB
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v27.0.2-0.20241031194140-6ac445c42bad+incompatible h1:kSQ4U+63JfFxIOrTo6wMW1mqkOkPpiTe/7ZfvUdNLVE=
|
github.com/docker/docker v27.0.2-0.20241120142749-e5c2b5e10d68+incompatible h1:ZWh4HhdUCagAd3S+gsFPOobHbc562obYFSrz3irGSsU=
|
||||||
github.com/docker/docker v27.0.2-0.20241031194140-6ac445c42bad+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v27.0.2-0.20241120142749-e5c2b5e10d68+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
||||||
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||||
|
|
|
@ -1991,6 +1991,18 @@ definitions:
|
||||||
type: "string"
|
type: "string"
|
||||||
x-nullable: false
|
x-nullable: false
|
||||||
example: "sha256:ec3f0931a6e6b6855d76b2d7b0be30e81860baccd891b2e243280bf1cd8ad710"
|
example: "sha256:ec3f0931a6e6b6855d76b2d7b0be30e81860baccd891b2e243280bf1cd8ad710"
|
||||||
|
Descriptor:
|
||||||
|
description: |
|
||||||
|
Descriptor is an OCI descriptor of the image target.
|
||||||
|
In case of a multi-platform image, this descriptor points to the OCI index
|
||||||
|
or a manifest list.
|
||||||
|
|
||||||
|
This field is only present if the daemon provides a multi-platform image store.
|
||||||
|
|
||||||
|
WARNING: This is experimental and may change at any time without any backward
|
||||||
|
compatibility.
|
||||||
|
x-nullable: true
|
||||||
|
$ref: "#/definitions/OCIDescriptor"
|
||||||
RepoTags:
|
RepoTags:
|
||||||
description: |
|
description: |
|
||||||
List of image names/tags in the local image cache that reference this
|
List of image names/tags in the local image cache that reference this
|
||||||
|
@ -2278,6 +2290,18 @@ definitions:
|
||||||
x-omitempty: true
|
x-omitempty: true
|
||||||
items:
|
items:
|
||||||
$ref: "#/definitions/ImageManifestSummary"
|
$ref: "#/definitions/ImageManifestSummary"
|
||||||
|
Descriptor:
|
||||||
|
description: |
|
||||||
|
Descriptor is an OCI descriptor of the image target.
|
||||||
|
In case of a multi-platform image, this descriptor points to the OCI index
|
||||||
|
or a manifest list.
|
||||||
|
|
||||||
|
This field is only present if the daemon provides a multi-platform image store.
|
||||||
|
|
||||||
|
WARNING: This is experimental and may change at any time without any backward
|
||||||
|
compatibility.
|
||||||
|
x-nullable: true
|
||||||
|
$ref: "#/definitions/OCIDescriptor"
|
||||||
|
|
||||||
AuthConfig:
|
AuthConfig:
|
||||||
type: "object"
|
type: "object"
|
||||||
|
@ -7242,6 +7266,14 @@ paths:
|
||||||
type: "string"
|
type: "string"
|
||||||
Platform:
|
Platform:
|
||||||
type: "string"
|
type: "string"
|
||||||
|
ImageManifestDescriptor:
|
||||||
|
$ref: "#/definitions/OCIDescriptor"
|
||||||
|
description: |
|
||||||
|
OCI descriptor of the platform-specific manifest of the image
|
||||||
|
the container was created from.
|
||||||
|
|
||||||
|
Note: Only available if the daemon provides a multi-platform
|
||||||
|
image store.
|
||||||
MountLabel:
|
MountLabel:
|
||||||
type: "string"
|
type: "string"
|
||||||
ProcessLabel:
|
ProcessLabel:
|
||||||
|
@ -9210,9 +9242,14 @@ paths:
|
||||||
type: "string"
|
type: "string"
|
||||||
in: "query"
|
in: "query"
|
||||||
description: |
|
description: |
|
||||||
JSON encoded OCI platform describing platform to show the history for.
|
JSON-encoded OCI platform to select the platform-variant.
|
||||||
If not provided, the host platform will be used. If it's not
|
If omitted, it defaults to any locally available platform,
|
||||||
available, any present platform will be picked.
|
prioritizing the daemon's host platform.
|
||||||
|
|
||||||
|
If the daemon provides a multi-platform image store, this selects
|
||||||
|
the platform-variant to show the history for. If the image is
|
||||||
|
a single-platform image, or if the multi-platform image does not
|
||||||
|
provide a variant matching the given platform, an error is returned.
|
||||||
|
|
||||||
Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}`
|
Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}`
|
||||||
tags: ["Image"]
|
tags: ["Image"]
|
||||||
|
@ -9262,6 +9299,19 @@ paths:
|
||||||
all tags of the given image that are present in the local image store
|
all tags of the given image that are present in the local image store
|
||||||
are pushed.
|
are pushed.
|
||||||
type: "string"
|
type: "string"
|
||||||
|
- name: "platform"
|
||||||
|
type: "string"
|
||||||
|
in: "query"
|
||||||
|
description: |
|
||||||
|
JSON-encoded OCI platform to select the platform-variant to push.
|
||||||
|
If not provided, all available variants will attempt to be pushed.
|
||||||
|
|
||||||
|
If the daemon provides a multi-platform image store, this selects
|
||||||
|
the platform-variant to push to the registry. If the image is
|
||||||
|
a single-platform image, or if the multi-platform image does not
|
||||||
|
provide a variant matching the given platform, an error is returned.
|
||||||
|
|
||||||
|
Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}`
|
||||||
- name: "X-Registry-Auth"
|
- name: "X-Registry-Auth"
|
||||||
in: "header"
|
in: "header"
|
||||||
description: |
|
description: |
|
||||||
|
@ -9271,11 +9321,6 @@ paths:
|
||||||
details.
|
details.
|
||||||
type: "string"
|
type: "string"
|
||||||
required: true
|
required: true
|
||||||
- name: "platform"
|
|
||||||
in: "query"
|
|
||||||
description: "Select a platform-specific manifest to be pushed. OCI platform (JSON encoded)"
|
|
||||||
type: "string"
|
|
||||||
x-nullable: true
|
|
||||||
tags: ["Image"]
|
tags: ["Image"]
|
||||||
/images/{name}/tag:
|
/images/{name}/tag:
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/mount"
|
"github.com/docker/docker/api/types/mount"
|
||||||
"github.com/docker/docker/api/types/storage"
|
"github.com/docker/docker/api/types/storage"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PruneReport contains the response for Engine API:
|
// PruneReport contains the response for Engine API:
|
||||||
|
@ -171,4 +172,6 @@ type InspectResponse struct {
|
||||||
Mounts []MountPoint
|
Mounts []MountPoint
|
||||||
Config *Config
|
Config *Config
|
||||||
NetworkSettings *NetworkSettings
|
NetworkSettings *NetworkSettings
|
||||||
|
// ImageManifestDescriptor is the descriptor of a platform-specific manifest of the image used to create the container.
|
||||||
|
ImageManifestDescriptor *ocispec.Descriptor `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/api/types/strslice"
|
"github.com/docker/docker/api/types/strslice"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
units "github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CgroupnsMode represents the cgroup namespace mode of the container
|
// CgroupnsMode represents the cgroup namespace mode of the container
|
||||||
|
|
|
@ -3,6 +3,7 @@ package image
|
||||||
import (
|
import (
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/storage"
|
"github.com/docker/docker/api/types/storage"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RootFS returns Image's RootFS description including the layer IDs.
|
// RootFS returns Image's RootFS description including the layer IDs.
|
||||||
|
@ -119,4 +120,11 @@ type InspectResponse struct {
|
||||||
//
|
//
|
||||||
// This information is local to the daemon, and not part of the image itself.
|
// This information is local to the daemon, and not part of the image itself.
|
||||||
Metadata Metadata
|
Metadata Metadata
|
||||||
|
|
||||||
|
// Descriptor is the OCI descriptor of the image target.
|
||||||
|
// It's only set if the daemon provides a multi-platform image store.
|
||||||
|
//
|
||||||
|
// WARNING: This is experimental and may change at any time without any backward
|
||||||
|
// compatibility.
|
||||||
|
Descriptor *ocispec.Descriptor `json:"Descriptor,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,12 +98,14 @@ type LoadOptions struct {
|
||||||
// Quiet suppresses progress output
|
// Quiet suppresses progress output
|
||||||
Quiet bool
|
Quiet bool
|
||||||
|
|
||||||
// Platform is a specific platform to load when the image is a multi-platform
|
// Platforms selects the platforms to load if the image is a
|
||||||
Platform *ocispec.Platform
|
// multi-platform image and has multiple variants.
|
||||||
|
Platforms []ocispec.Platform
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveOptions holds parameters to save images.
|
// SaveOptions holds parameters to save images.
|
||||||
type SaveOptions struct {
|
type SaveOptions struct {
|
||||||
// Platform is a specific platform to save if the image is a multi-platform image.
|
// Platforms selects the platforms to save if the image is a
|
||||||
Platform *ocispec.Platform
|
// multi-platform image and has multiple variants.
|
||||||
|
Platforms []ocispec.Platform
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package image
|
package image
|
||||||
|
|
||||||
|
import ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
|
||||||
type Summary struct {
|
type Summary struct {
|
||||||
|
|
||||||
// Number of containers using this image. Includes both stopped and running
|
// Number of containers using this image. Includes both stopped and running
|
||||||
|
@ -42,6 +44,13 @@ type Summary struct {
|
||||||
// Required: true
|
// Required: true
|
||||||
ParentID string `json:"ParentId"`
|
ParentID string `json:"ParentId"`
|
||||||
|
|
||||||
|
// Descriptor is the OCI descriptor of the image target.
|
||||||
|
// It's only set if the daemon provides a multi-platform image store.
|
||||||
|
//
|
||||||
|
// WARNING: This is experimental and may change at any time without any backward
|
||||||
|
// compatibility.
|
||||||
|
Descriptor *ocispec.Descriptor `json:"Descriptor,omitempty"`
|
||||||
|
|
||||||
// Manifests is a list of image manifests available in this image. It
|
// Manifests is a list of image manifests available in this image. It
|
||||||
// provides a more detailed view of the platform-specific image manifests or
|
// provides a more detailed view of the platform-specific image manifests or
|
||||||
// other image-attached data like build attestations.
|
// other image-attached data like build attestations.
|
||||||
|
|
|
@ -3,7 +3,6 @@ package client // import "github.com/docker/docker/client"
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/image"
|
"github.com/docker/docker/api/types/image"
|
||||||
|
@ -11,26 +10,26 @@ import (
|
||||||
|
|
||||||
// ImageHistory returns the changes in an image in history format.
|
// ImageHistory returns the changes in an image in history format.
|
||||||
func (cli *Client) ImageHistory(ctx context.Context, imageID string, opts image.HistoryOptions) ([]image.HistoryResponseItem, error) {
|
func (cli *Client) ImageHistory(ctx context.Context, imageID string, opts image.HistoryOptions) ([]image.HistoryResponseItem, error) {
|
||||||
values := url.Values{}
|
query := url.Values{}
|
||||||
if opts.Platform != nil {
|
if opts.Platform != nil {
|
||||||
if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := json.Marshal(*opts.Platform)
|
p, err := encodePlatform(opts.Platform)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid platform: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
values.Set("platform", string(p))
|
query.Set("platform", p)
|
||||||
|
}
|
||||||
|
|
||||||
|
serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", query, nil)
|
||||||
|
defer ensureReaderClosed(serverResp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var history []image.HistoryResponseItem
|
var history []image.HistoryResponseItem
|
||||||
serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", values, nil)
|
|
||||||
defer ensureReaderClosed(serverResp)
|
|
||||||
if err != nil {
|
|
||||||
return history, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.NewDecoder(serverResp.body).Decode(&history)
|
err = json.NewDecoder(serverResp.body).Decode(&history)
|
||||||
return history, err
|
return history, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,18 @@ func (cli *Client) ImageImport(ctx context.Context, source image.ImportSource, r
|
||||||
}
|
}
|
||||||
|
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
query.Set("fromSrc", source.SourceName)
|
if source.SourceName != "" {
|
||||||
query.Set("repo", ref)
|
query.Set("fromSrc", source.SourceName)
|
||||||
query.Set("tag", options.Tag)
|
}
|
||||||
query.Set("message", options.Message)
|
if ref != "" {
|
||||||
|
query.Set("repo", ref)
|
||||||
|
}
|
||||||
|
if options.Tag != "" {
|
||||||
|
query.Set("tag", options.Tag)
|
||||||
|
}
|
||||||
|
if options.Message != "" {
|
||||||
|
query.Set("message", options.Message)
|
||||||
|
}
|
||||||
if options.Platform != "" {
|
if options.Platform != "" {
|
||||||
query.Set("platform", strings.ToLower(options.Platform))
|
query.Set("platform", strings.ToLower(options.Platform))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package client // import "github.com/docker/docker/client"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -18,24 +17,24 @@ import (
|
||||||
// the provided multi-platform image. This is only has effect if the input image
|
// the provided multi-platform image. This is only has effect if the input image
|
||||||
// is a multi-platform image.
|
// is a multi-platform image.
|
||||||
func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, opts image.LoadOptions) (image.LoadResponse, error) {
|
func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, opts image.LoadOptions) (image.LoadResponse, error) {
|
||||||
v := url.Values{}
|
query := url.Values{}
|
||||||
v.Set("quiet", "0")
|
query.Set("quiet", "0")
|
||||||
if opts.Quiet {
|
if opts.Quiet {
|
||||||
v.Set("quiet", "1")
|
query.Set("quiet", "1")
|
||||||
}
|
}
|
||||||
if opts.Platform != nil {
|
if len(opts.Platforms) > 0 {
|
||||||
if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil {
|
||||||
return image.LoadResponse{}, err
|
return image.LoadResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := json.Marshal(*opts.Platform)
|
p, err := encodePlatforms(opts.Platforms...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return image.LoadResponse{}, err
|
return image.LoadResponse{}, err
|
||||||
}
|
}
|
||||||
v.Set("platform", string(p))
|
query["platform"] = p
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := cli.postRaw(ctx, "/images/load", v, input, http.Header{
|
resp, err := cli.postRaw(ctx, "/images/load", query, input, http.Header{
|
||||||
"Content-Type": {"application/x-tar"},
|
"Content-Type": {"application/x-tar"},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,8 +2,6 @@ package client // import "github.com/docker/docker/client"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
@ -17,16 +15,15 @@ func (cli *Client) ImageSave(ctx context.Context, imageIDs []string, opts image.
|
||||||
"names": imageIDs,
|
"names": imageIDs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Platform != nil {
|
if len(opts.Platforms) > 0 {
|
||||||
if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
p, err := encodePlatforms(opts.Platforms...)
|
||||||
p, err := json.Marshal(*opts.Platform)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid platform: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
query.Set("platform", string(p))
|
query["platform"] = p
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := cli.get(ctx, "/images/get", query, nil)
|
resp, err := cli.get(ctx, "/images/get", query, nil)
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package client // import "github.com/docker/docker/client"
|
package client // import "github.com/docker/docker/client"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/errdefs"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
|
var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
|
||||||
|
@ -32,3 +36,43 @@ func getFiltersQuery(f filters.Args) (url.Values, error) {
|
||||||
}
|
}
|
||||||
return query, nil
|
return query, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// encodePlatforms marshals the given platform(s) to JSON format, to
|
||||||
|
// be used for query-parameters for filtering / selecting platforms.
|
||||||
|
func encodePlatforms(platform ...ocispec.Platform) ([]string, error) {
|
||||||
|
if len(platform) == 0 {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
if len(platform) == 1 {
|
||||||
|
p, err := encodePlatform(&platform[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return []string{p}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
seen := make(map[string]struct{}, len(platform))
|
||||||
|
out := make([]string, 0, len(platform))
|
||||||
|
for i := range platform {
|
||||||
|
p, err := encodePlatform(&platform[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if _, ok := seen[p]; !ok {
|
||||||
|
out = append(out, p)
|
||||||
|
seen[p] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodePlatforms marshals the given platform to JSON format, to
|
||||||
|
// be used for query-parameters for filtering / selecting platforms. It
|
||||||
|
// is used as a helper for encodePlatforms,
|
||||||
|
func encodePlatform(platform *ocispec.Platform) (string, error) {
|
||||||
|
p, err := json.Marshal(platform)
|
||||||
|
if err != nil {
|
||||||
|
return "", errdefs.InvalidParameter(fmt.Errorf("invalid platform: %v", err))
|
||||||
|
}
|
||||||
|
return string(p), nil
|
||||||
|
}
|
||||||
|
|
|
@ -261,13 +261,13 @@ func readdirnames(dirname string) (names []nameIno, err error) {
|
||||||
func parseDirent(buf []byte, names []nameIno) (consumed int, newnames []nameIno) {
|
func parseDirent(buf []byte, names []nameIno) (consumed int, newnames []nameIno) {
|
||||||
origlen := len(buf)
|
origlen := len(buf)
|
||||||
for len(buf) > 0 {
|
for len(buf) > 0 {
|
||||||
dirent := (*unix.Dirent)(unsafe.Pointer(&buf[0]))
|
dirent := (*unix.Dirent)(unsafe.Pointer(&buf[0])) // #nosec G103 -- Ignore "G103: Use of unsafe calls should be audited"
|
||||||
buf = buf[dirent.Reclen:]
|
buf = buf[dirent.Reclen:]
|
||||||
if dirent.Ino == 0 { // File absent in directory.
|
if dirent.Ino == 0 { // File absent in directory.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
b := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) // #nosec G103 -- Ignore "G103: Use of unsafe calls should be audited"
|
||||||
name := string(bytes[0:clen(bytes[:])])
|
name := string(b[0:clen(b[:])])
|
||||||
if name == "." || name == ".." { // Useless names
|
if name == "." || name == ".." { // Useless names
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,11 @@ type subIDRange struct {
|
||||||
Length int
|
Length int
|
||||||
}
|
}
|
||||||
|
|
||||||
type ranges []subIDRange
|
type subIDRanges []subIDRange
|
||||||
|
|
||||||
func (e ranges) Len() int { return len(e) }
|
func (e subIDRanges) Len() int { return len(e) }
|
||||||
func (e ranges) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
|
func (e subIDRanges) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
|
||||||
func (e ranges) Less(i, j int) bool { return e[i].Start < e[j].Start }
|
func (e subIDRanges) Less(i, j int) bool { return e[i].Start < e[j].Start }
|
||||||
|
|
||||||
const (
|
const (
|
||||||
subuidFileName = "/etc/subuid"
|
subuidFileName = "/etc/subuid"
|
||||||
|
@ -162,7 +162,7 @@ func (i IdentityMapping) Empty() bool {
|
||||||
return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0
|
return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func createIDMap(subidRanges ranges) []IDMap {
|
func createIDMap(subidRanges subIDRanges) []IDMap {
|
||||||
idMap := []IDMap{}
|
idMap := []IDMap{}
|
||||||
|
|
||||||
containerID := 0
|
containerID := 0
|
||||||
|
@ -177,19 +177,19 @@ func createIDMap(subidRanges ranges) []IDMap {
|
||||||
return idMap
|
return idMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSubuid(username string) (ranges, error) {
|
func parseSubuid(username string) (subIDRanges, error) {
|
||||||
return parseSubidFile(subuidFileName, username)
|
return parseSubidFile(subuidFileName, username)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSubgid(username string) (ranges, error) {
|
func parseSubgid(username string) (subIDRanges, error) {
|
||||||
return parseSubidFile(subgidFileName, username)
|
return parseSubidFile(subgidFileName, username)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid)
|
// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid)
|
||||||
// and return all found ranges for a specified username. If the special value
|
// and return all found subIDRanges for a specified username. If the special value
|
||||||
// "ALL" is supplied for username, then all ranges in the file will be returned
|
// "ALL" is supplied for username, then all subIDRanges in the file will be returned
|
||||||
func parseSubidFile(path, username string) (ranges, error) {
|
func parseSubidFile(path, username string) (subIDRanges, error) {
|
||||||
var rangeList ranges
|
var rangeList subIDRanges
|
||||||
|
|
||||||
subidFile, err := os.Open(path)
|
subidFile, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -145,7 +145,7 @@ func findNextGIDRange() (int, error) {
|
||||||
return findNextRangeStart(ranges)
|
return findNextRangeStart(ranges)
|
||||||
}
|
}
|
||||||
|
|
||||||
func findNextRangeStart(rangeList ranges) (int, error) {
|
func findNextRangeStart(rangeList subIDRanges) (int, error) {
|
||||||
startID := defaultRangeStart
|
startID := defaultRangeStart
|
||||||
for _, arange := range rangeList {
|
for _, arange := range rangeList {
|
||||||
if wouldOverlap(arange, startID) {
|
if wouldOverlap(arange, startID) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
units "github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
"github.com/moby/term"
|
"github.com/moby/term"
|
||||||
"github.com/morikuni/aec"
|
"github.com/morikuni/aec"
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,8 +3,8 @@ package system // import "github.com/docker/docker/pkg/system"
|
||||||
// containerdRuntimeSupported determines if containerd should be the runtime.
|
// containerdRuntimeSupported determines if containerd should be the runtime.
|
||||||
var containerdRuntimeSupported = false
|
var containerdRuntimeSupported = false
|
||||||
|
|
||||||
// InitContainerdRuntime sets whether to use containerd for runtime on Windows.
|
// EnableContainerdRuntime sets whether to use containerd for runtime on Windows.
|
||||||
func InitContainerdRuntime(cdPath string) {
|
func EnableContainerdRuntime(cdPath string) {
|
||||||
if len(cdPath) > 0 {
|
if len(cdPath) > 0 {
|
||||||
containerdRuntimeSupported = true
|
containerdRuntimeSupported = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ github.com/docker/distribution/registry/client/transport
|
||||||
github.com/docker/distribution/registry/storage/cache
|
github.com/docker/distribution/registry/storage/cache
|
||||||
github.com/docker/distribution/registry/storage/cache/memory
|
github.com/docker/distribution/registry/storage/cache/memory
|
||||||
github.com/docker/distribution/uuid
|
github.com/docker/distribution/uuid
|
||||||
# github.com/docker/docker v27.0.2-0.20241031194140-6ac445c42bad+incompatible
|
# github.com/docker/docker v27.0.2-0.20241120142749-e5c2b5e10d68+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/docker/docker/api
|
github.com/docker/docker/api
|
||||||
github.com/docker/docker/api/types
|
github.com/docker/docker/api/types
|
||||||
|
|
Loading…
Reference in New Issue