mirror of https://github.com/docker/cli.git
Compare commits
7 Commits
e66638eb12
...
8dccdd1d13
Author | SHA1 | Date |
---|---|---|
Sebastiaan van Stijn | 8dccdd1d13 | |
Sebastiaan van Stijn | a93fb1678a | |
Sebastiaan van Stijn | d41b80fafc | |
Sebastiaan van Stijn | 81401f37f2 | |
Giedrius Jonikas | cb2f95ceee | |
Sebastiaan van Stijn | be3646b87c | |
Sebastiaan van Stijn | 7187c78554 |
|
@ -287,16 +287,26 @@ func RunStats(ctx context.Context, dockerCLI command.Cli, options *StatsOptions)
|
|||
cStats.mu.RUnlock()
|
||||
|
||||
if !options.NoStream {
|
||||
// Start by clearing the screen and moving the cursor to the top-left
|
||||
_, _ = fmt.Fprint(&statsTextBuffer, "\033[2J\033[H")
|
||||
// Start by moving the cursor to the top-left
|
||||
_, _ = fmt.Fprint(&statsTextBuffer, "\033[H")
|
||||
}
|
||||
|
||||
if err = statsFormatWrite(statsCtx, ccStats, daemonOSType, !options.NoTrunc); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprint(dockerCLI.Out(), statsTextBuffer.String())
|
||||
if !options.NoStream {
|
||||
for _, line := range strings.Split(statsTextBuffer.String(), "\n") {
|
||||
// In case the new text is shorter than the one we are writing over,
|
||||
// we'll append the "erase line" escape sequence to clear the remaining text.
|
||||
_, _ = fmt.Fprint(&statsTextBuffer, line, "\033[K\n")
|
||||
}
|
||||
|
||||
// We might have fewer containers than before, so let's clear the remaining text
|
||||
_, _ = fmt.Fprint(&statsTextBuffer, "\033[J")
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprint(dockerCLI.Out(), statsTextBuffer.String())
|
||||
statsTextBuffer.Reset()
|
||||
|
||||
if len(cStats.cs) == 0 && !showAll {
|
||||
|
|
|
@ -78,7 +78,8 @@ func runLoad(ctx context.Context, dockerCli command.Cli, opts loadOptions) error
|
|||
if err != nil {
|
||||
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)
|
||||
|
|
|
@ -109,7 +109,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
|
|||
name: "with platform",
|
||||
args: []string{"--platform", "linux/amd64"},
|
||||
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
|
||||
},
|
||||
},
|
||||
|
|
|
@ -63,7 +63,8 @@ func RunSave(ctx context.Context, dockerCli command.Cli, opts saveOptions) error
|
|||
if err != nil {
|
||||
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)
|
||||
|
|
|
@ -106,7 +106,7 @@ func TestNewSaveCommandSuccess(t *testing.T) {
|
|||
imageSaveFunc: func(images []string, options image.SaveOptions) (io.ReadCloser, error) {
|
||||
assert.Assert(t, is.Len(images, 1))
|
||||
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
|
||||
},
|
||||
},
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
imagetypes "github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/fvbommel/sortorder"
|
||||
"github.com/morikuni/aec"
|
||||
)
|
||||
|
||||
|
@ -81,16 +82,46 @@ func runTree(ctx context.Context, dockerCLI command.Cli, opts treeOptions) error
|
|||
|
||||
details.ContentSize = units.HumanSizeWithPrecision(float64(totalContent), 3)
|
||||
|
||||
view.images = append(view.images, topImage{
|
||||
Names: img.RepoTags,
|
||||
Details: details,
|
||||
Children: children,
|
||||
created: img.Created,
|
||||
})
|
||||
if len(img.RepoTags) == 0 {
|
||||
// Untagged image
|
||||
view.images = append(view.images, topImage{
|
||||
Names: img.RepoTags,
|
||||
Details: details,
|
||||
Children: children,
|
||||
created: img.Created,
|
||||
})
|
||||
} else {
|
||||
// Present images tagged under multiple names as separate images.
|
||||
for _, n := range img.RepoTags {
|
||||
view.images = append(view.images, topImage{
|
||||
Names: []string{n}, // Consider changing Names to be a single name for purpose of this presentation.
|
||||
Details: details,
|
||||
Children: children,
|
||||
created: img.Created,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort images alphabetically using natural-sort, with untagged images last.
|
||||
sort.Slice(view.images, func(i, j int) bool {
|
||||
return view.images[i].created > view.images[j].created
|
||||
iUntagged, jUntagged := len(view.images[i].Names) == 0, len(view.images[j].Names) == 0
|
||||
if iUntagged || jUntagged {
|
||||
switch {
|
||||
case iUntagged && jUntagged:
|
||||
// Both untagged images; sort by created date (desc)
|
||||
return view.images[i].created > view.images[j].created
|
||||
case iUntagged:
|
||||
// Sort untagged images last
|
||||
return false
|
||||
case jUntagged:
|
||||
// Sort untagged images last
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Sort alphabetically, ascending
|
||||
return sortorder.NaturalLess(view.images[i].Names[0], view.images[j].Names[0])
|
||||
})
|
||||
|
||||
return printImageTree(dockerCLI, view)
|
||||
|
|
|
@ -13,7 +13,7 @@ require (
|
|||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/cli-docs-tool v0.8.0
|
||||
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/go-connections 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.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/docker v27.0.2-0.20241031194140-6ac445c42bad+incompatible h1:kSQ4U+63JfFxIOrTo6wMW1mqkOkPpiTe/7ZfvUdNLVE=
|
||||
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 h1:ZWh4HhdUCagAd3S+gsFPOobHbc562obYFSrz3irGSsU=
|
||||
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/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
|
|
|
@ -1991,6 +1991,18 @@ definitions:
|
|||
type: "string"
|
||||
x-nullable: false
|
||||
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:
|
||||
description: |
|
||||
List of image names/tags in the local image cache that reference this
|
||||
|
@ -2278,6 +2290,18 @@ definitions:
|
|||
x-omitempty: true
|
||||
items:
|
||||
$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:
|
||||
type: "object"
|
||||
|
@ -7242,6 +7266,14 @@ paths:
|
|||
type: "string"
|
||||
Platform:
|
||||
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:
|
||||
type: "string"
|
||||
ProcessLabel:
|
||||
|
@ -9210,9 +9242,14 @@ paths:
|
|||
type: "string"
|
||||
in: "query"
|
||||
description: |
|
||||
JSON encoded OCI platform describing platform to show the history for.
|
||||
If not provided, the host platform will be used. If it's not
|
||||
available, any present platform will be picked.
|
||||
JSON-encoded OCI platform to select the platform-variant.
|
||||
If omitted, it defaults to any locally available platform,
|
||||
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"}`
|
||||
tags: ["Image"]
|
||||
|
@ -9262,6 +9299,19 @@ paths:
|
|||
all tags of the given image that are present in the local image store
|
||||
are pushed.
|
||||
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"
|
||||
in: "header"
|
||||
description: |
|
||||
|
@ -9271,11 +9321,6 @@ paths:
|
|||
details.
|
||||
type: "string"
|
||||
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"]
|
||||
/images/{name}/tag:
|
||||
post:
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/api/types/storage"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// PruneReport contains the response for Engine API:
|
||||
|
@ -171,4 +172,6 @@ type InspectResponse struct {
|
|||
Mounts []MountPoint
|
||||
Config *Config
|
||||
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/strslice"
|
||||
"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
|
||||
|
|
|
@ -3,6 +3,7 @@ package image
|
|||
import (
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"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.
|
||||
|
@ -119,4 +120,11 @@ type InspectResponse struct {
|
|||
//
|
||||
// This information is local to the daemon, and not part of the image itself.
|
||||
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 bool
|
||||
|
||||
// Platform is a specific platform to load when the image is a multi-platform
|
||||
Platform *ocispec.Platform
|
||||
// Platforms selects the platforms to load if the image is a
|
||||
// multi-platform image and has multiple variants.
|
||||
Platforms []ocispec.Platform
|
||||
}
|
||||
|
||||
// SaveOptions holds parameters to save images.
|
||||
type SaveOptions struct {
|
||||
// Platform is a specific platform to save if the image is a multi-platform image.
|
||||
Platform *ocispec.Platform
|
||||
// Platforms selects the platforms to save if the image is a
|
||||
// multi-platform image and has multiple variants.
|
||||
Platforms []ocispec.Platform
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package image
|
||||
|
||||
import ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
type Summary struct {
|
||||
|
||||
// Number of containers using this image. Includes both stopped and running
|
||||
|
@ -42,6 +44,13 @@ type Summary struct {
|
|||
// Required: true
|
||||
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
|
||||
// provides a more detailed view of the platform-specific image manifests or
|
||||
// other image-attached data like build attestations.
|
||||
|
|
|
@ -3,7 +3,6 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types/image"
|
||||
|
@ -11,26 +10,26 @@ import (
|
|||
|
||||
// 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) {
|
||||
values := url.Values{}
|
||||
query := url.Values{}
|
||||
if opts.Platform != nil {
|
||||
if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p, err := json.Marshal(*opts.Platform)
|
||||
p, err := encodePlatform(opts.Platform)
|
||||
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
|
||||
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)
|
||||
return history, err
|
||||
}
|
||||
|
|
|
@ -21,10 +21,18 @@ func (cli *Client) ImageImport(ctx context.Context, source image.ImportSource, r
|
|||
}
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("fromSrc", source.SourceName)
|
||||
query.Set("repo", ref)
|
||||
query.Set("tag", options.Tag)
|
||||
query.Set("message", options.Message)
|
||||
if source.SourceName != "" {
|
||||
query.Set("fromSrc", source.SourceName)
|
||||
}
|
||||
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 != "" {
|
||||
query.Set("platform", strings.ToLower(options.Platform))
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package client // import "github.com/docker/docker/client"
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -18,24 +17,24 @@ import (
|
|||
// the provided multi-platform image. This is only has effect if the input image
|
||||
// is a multi-platform image.
|
||||
func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, opts image.LoadOptions) (image.LoadResponse, error) {
|
||||
v := url.Values{}
|
||||
v.Set("quiet", "0")
|
||||
query := url.Values{}
|
||||
query.Set("quiet", "0")
|
||||
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 {
|
||||
return image.LoadResponse{}, err
|
||||
}
|
||||
|
||||
p, err := json.Marshal(*opts.Platform)
|
||||
p, err := encodePlatforms(opts.Platforms...)
|
||||
if err != nil {
|
||||
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"},
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -2,8 +2,6 @@ package client // import "github.com/docker/docker/client"
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
|
@ -17,16 +15,15 @@ func (cli *Client) ImageSave(ctx context.Context, imageIDs []string, opts image.
|
|||
"names": imageIDs,
|
||||
}
|
||||
|
||||
if opts.Platform != nil {
|
||||
if len(opts.Platforms) > 0 {
|
||||
if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p, err := json.Marshal(*opts.Platform)
|
||||
p, err := encodePlatforms(opts.Platforms...)
|
||||
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)
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package client // import "github.com/docker/docker/client"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
|
||||
"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`)
|
||||
|
@ -32,3 +36,43 @@ func getFiltersQuery(f filters.Args) (url.Values, error) {
|
|||
}
|
||||
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) {
|
||||
origlen := len(buf)
|
||||
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:]
|
||||
if dirent.Ino == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
name := string(bytes[0:clen(bytes[:])])
|
||||
b := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) // #nosec G103 -- Ignore "G103: Use of unsafe calls should be audited"
|
||||
name := string(b[0:clen(b[:])])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -22,11 +22,11 @@ type subIDRange struct {
|
|||
Length int
|
||||
}
|
||||
|
||||
type ranges []subIDRange
|
||||
type subIDRanges []subIDRange
|
||||
|
||||
func (e ranges) Len() int { return len(e) }
|
||||
func (e ranges) 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) Len() int { return len(e) }
|
||||
func (e subIDRanges) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
|
||||
func (e subIDRanges) Less(i, j int) bool { return e[i].Start < e[j].Start }
|
||||
|
||||
const (
|
||||
subuidFileName = "/etc/subuid"
|
||||
|
@ -162,7 +162,7 @@ func (i IdentityMapping) Empty() bool {
|
|||
return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0
|
||||
}
|
||||
|
||||
func createIDMap(subidRanges ranges) []IDMap {
|
||||
func createIDMap(subidRanges subIDRanges) []IDMap {
|
||||
idMap := []IDMap{}
|
||||
|
||||
containerID := 0
|
||||
|
@ -177,19 +177,19 @@ func createIDMap(subidRanges ranges) []IDMap {
|
|||
return idMap
|
||||
}
|
||||
|
||||
func parseSubuid(username string) (ranges, error) {
|
||||
func parseSubuid(username string) (subIDRanges, error) {
|
||||
return parseSubidFile(subuidFileName, username)
|
||||
}
|
||||
|
||||
func parseSubgid(username string) (ranges, error) {
|
||||
func parseSubgid(username string) (subIDRanges, error) {
|
||||
return parseSubidFile(subgidFileName, username)
|
||||
}
|
||||
|
||||
// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid)
|
||||
// and return all found ranges for a specified username. If the special value
|
||||
// "ALL" is supplied for username, then all ranges in the file will be returned
|
||||
func parseSubidFile(path, username string) (ranges, error) {
|
||||
var rangeList ranges
|
||||
// and return all found subIDRanges for a specified username. If the special value
|
||||
// "ALL" is supplied for username, then all subIDRanges in the file will be returned
|
||||
func parseSubidFile(path, username string) (subIDRanges, error) {
|
||||
var rangeList subIDRanges
|
||||
|
||||
subidFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
|
@ -145,7 +145,7 @@ func findNextGIDRange() (int, error) {
|
|||
return findNextRangeStart(ranges)
|
||||
}
|
||||
|
||||
func findNextRangeStart(rangeList ranges) (int, error) {
|
||||
func findNextRangeStart(rangeList subIDRanges) (int, error) {
|
||||
startID := defaultRangeStart
|
||||
for _, arange := range rangeList {
|
||||
if wouldOverlap(arange, startID) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/moby/term"
|
||||
"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.
|
||||
var containerdRuntimeSupported = false
|
||||
|
||||
// InitContainerdRuntime sets whether to use containerd for runtime on Windows.
|
||||
func InitContainerdRuntime(cdPath string) {
|
||||
// EnableContainerdRuntime sets whether to use containerd for runtime on Windows.
|
||||
func EnableContainerdRuntime(cdPath string) {
|
||||
if len(cdPath) > 0 {
|
||||
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/memory
|
||||
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
|
||||
github.com/docker/docker/api
|
||||
github.com/docker/docker/api/types
|
||||
|
|
Loading…
Reference in New Issue