mirror of https://github.com/docker/cli.git
vendor: github.com/docker/docker 6ac445c42bad (master, v28.0-dev)
full diff: 36a3bd0904...6ac445c42b
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
10c5a57927
commit
5f1311ae8d
|
@ -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.20241018142220-36a3bd090489+incompatible // master (v-next)
|
github.com/docker/docker v27.0.2-0.20241031194140-6ac445c42bad+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.20241018142220-36a3bd090489+incompatible h1:utxxyIvPGk7UmtlGHirUyNUP2Spf8yL660PCbmb7tsk=
|
github.com/docker/docker v27.0.2-0.20241031194140-6ac445c42bad+incompatible h1:kSQ4U+63JfFxIOrTo6wMW1mqkOkPpiTe/7ZfvUdNLVE=
|
||||||
github.com/docker/docker v27.0.2-0.20241018142220-36a3bd090489+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v27.0.2-0.20241031194140-6ac445c42bad+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=
|
||||||
|
|
|
@ -22,16 +22,3 @@ func (e invalidFilter) Error() string {
|
||||||
|
|
||||||
// InvalidParameter marks this error as ErrInvalidParameter
|
// InvalidParameter marks this error as ErrInvalidParameter
|
||||||
func (e invalidFilter) InvalidParameter() {}
|
func (e invalidFilter) InvalidParameter() {}
|
||||||
|
|
||||||
// unreachableCode is an error indicating that the code path was not expected to be reached.
|
|
||||||
type unreachableCode struct {
|
|
||||||
Filter string
|
|
||||||
Value []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// System marks this error as ErrSystem
|
|
||||||
func (e unreachableCode) System() {}
|
|
||||||
|
|
||||||
func (e unreachableCode) Error() string {
|
|
||||||
return fmt.Sprintf("unreachable code reached for filter: %q with values: %s", e.Filter, e.Value)
|
|
||||||
}
|
|
||||||
|
|
|
@ -200,7 +200,6 @@ func (args Args) Match(field, source string) bool {
|
||||||
// Error is not nil only if the filter values are not valid boolean or are conflicting.
|
// Error is not nil only if the filter values are not valid boolean or are conflicting.
|
||||||
func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) {
|
func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) {
|
||||||
fieldValues, ok := args.fields[key]
|
fieldValues, ok := args.fields[key]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return defaultValue, nil
|
return defaultValue, nil
|
||||||
}
|
}
|
||||||
|
@ -211,20 +210,11 @@ func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) {
|
||||||
|
|
||||||
isFalse := fieldValues["0"] || fieldValues["false"]
|
isFalse := fieldValues["0"] || fieldValues["false"]
|
||||||
isTrue := fieldValues["1"] || fieldValues["true"]
|
isTrue := fieldValues["1"] || fieldValues["true"]
|
||||||
|
if isFalse == isTrue {
|
||||||
conflicting := isFalse && isTrue
|
// Either no or conflicting truthy/falsy value were provided
|
||||||
invalid := !isFalse && !isTrue
|
|
||||||
|
|
||||||
if conflicting || invalid {
|
|
||||||
return defaultValue, &invalidFilter{key, args.Get(key)}
|
return defaultValue, &invalidFilter{key, args.Get(key)}
|
||||||
} else if isFalse {
|
|
||||||
return false, nil
|
|
||||||
} else if isTrue {
|
|
||||||
return true, nil
|
|
||||||
}
|
}
|
||||||
|
return isTrue, nil
|
||||||
// This code shouldn't be reached.
|
|
||||||
return defaultValue, &unreachableCode{Filter: key, Value: args.Get(key)}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExactMatch returns true if the source matches exactly one of the values.
|
// ExactMatch returns true if the source matches exactly one of the values.
|
||||||
|
|
|
@ -17,8 +17,6 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePru
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
report := types.BuildCachePruneReport{}
|
|
||||||
|
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
if opts.All {
|
if opts.All {
|
||||||
query.Set("all", "1")
|
query.Set("all", "1")
|
||||||
|
@ -37,6 +35,7 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePru
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
report := types.BuildCachePruneReport{}
|
||||||
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
||||||
return nil, errors.Wrap(err, "error retrieving disk usage")
|
return nil, errors.Wrap(err, "error retrieving disk usage")
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,6 +247,14 @@ func (cli *Client) tlsConfig() *tls.Config {
|
||||||
|
|
||||||
func defaultHTTPClient(hostURL *url.URL) (*http.Client, error) {
|
func defaultHTTPClient(hostURL *url.URL) (*http.Client, error) {
|
||||||
transport := &http.Transport{}
|
transport := &http.Transport{}
|
||||||
|
// Necessary to prevent long-lived processes using the
|
||||||
|
// client from leaking connections due to idle connections
|
||||||
|
// not being released.
|
||||||
|
// TODO: see if we can also address this from the server side,
|
||||||
|
// or in go-connections.
|
||||||
|
// see: https://github.com/moby/moby/issues/45539
|
||||||
|
transport.MaxIdleConns = 6
|
||||||
|
transport.IdleConnTimeout = 30 * time.Second
|
||||||
err := sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host)
|
err := sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -11,25 +11,24 @@ import (
|
||||||
|
|
||||||
// ContainersPrune requests the daemon to delete unused data
|
// ContainersPrune requests the daemon to delete unused data
|
||||||
func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error) {
|
func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error) {
|
||||||
var report container.PruneReport
|
|
||||||
|
|
||||||
if err := cli.NewVersionError(ctx, "1.25", "container prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "container prune"); err != nil {
|
||||||
return report, err
|
return container.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query, err := getFiltersQuery(pruneFilters)
|
query, err := getFiltersQuery(pruneFilters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report, err
|
return container.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil)
|
serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil)
|
||||||
defer ensureReaderClosed(serverResp)
|
defer ensureReaderClosed(serverResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report, err
|
return container.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var report container.PruneReport
|
||||||
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
||||||
return report, fmt.Errorf("Error retrieving disk usage: %v", err)
|
return container.PruneReport{}, fmt.Errorf("Error retrieving disk usage: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return report, nil
|
return report, nil
|
||||||
|
|
|
@ -11,25 +11,24 @@ import (
|
||||||
|
|
||||||
// ImagesPrune requests the daemon to delete unused data
|
// ImagesPrune requests the daemon to delete unused data
|
||||||
func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (image.PruneReport, error) {
|
func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (image.PruneReport, error) {
|
||||||
var report image.PruneReport
|
|
||||||
|
|
||||||
if err := cli.NewVersionError(ctx, "1.25", "image prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "image prune"); err != nil {
|
||||||
return report, err
|
return image.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query, err := getFiltersQuery(pruneFilters)
|
query, err := getFiltersQuery(pruneFilters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report, err
|
return image.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil)
|
serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil)
|
||||||
defer ensureReaderClosed(serverResp)
|
defer ensureReaderClosed(serverResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report, err
|
return image.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var report image.PruneReport
|
||||||
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
||||||
return report, fmt.Errorf("Error retrieving disk usage: %v", err)
|
return image.PruneReport{}, fmt.Errorf("Error retrieving disk usage: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return report, nil
|
return report, nil
|
||||||
|
|
|
@ -11,25 +11,24 @@ import (
|
||||||
|
|
||||||
// NetworksPrune requests the daemon to delete unused networks
|
// NetworksPrune requests the daemon to delete unused networks
|
||||||
func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (network.PruneReport, error) {
|
func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (network.PruneReport, error) {
|
||||||
var report network.PruneReport
|
|
||||||
|
|
||||||
if err := cli.NewVersionError(ctx, "1.25", "network prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "network prune"); err != nil {
|
||||||
return report, err
|
return network.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query, err := getFiltersQuery(pruneFilters)
|
query, err := getFiltersQuery(pruneFilters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report, err
|
return network.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil)
|
serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil)
|
||||||
defer ensureReaderClosed(serverResp)
|
defer ensureReaderClosed(serverResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report, err
|
return network.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var report network.PruneReport
|
||||||
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
||||||
return report, fmt.Errorf("Error retrieving network prune report: %v", err)
|
return network.PruneReport{}, fmt.Errorf("Error retrieving network prune report: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return report, nil
|
return report, nil
|
||||||
|
|
|
@ -11,25 +11,24 @@ import (
|
||||||
|
|
||||||
// VolumesPrune requests the daemon to delete unused data
|
// VolumesPrune requests the daemon to delete unused data
|
||||||
func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (volume.PruneReport, error) {
|
func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (volume.PruneReport, error) {
|
||||||
var report volume.PruneReport
|
|
||||||
|
|
||||||
if err := cli.NewVersionError(ctx, "1.25", "volume prune"); err != nil {
|
if err := cli.NewVersionError(ctx, "1.25", "volume prune"); err != nil {
|
||||||
return report, err
|
return volume.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
query, err := getFiltersQuery(pruneFilters)
|
query, err := getFiltersQuery(pruneFilters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report, err
|
return volume.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil)
|
serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil)
|
||||||
defer ensureReaderClosed(serverResp)
|
defer ensureReaderClosed(serverResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report, err
|
return volume.PruneReport{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var report volume.PruneReport
|
||||||
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
||||||
return report, fmt.Errorf("Error retrieving volume prune report: %v", err)
|
return volume.PruneReport{}, fmt.Errorf("Error retrieving volume prune report: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return report, nil
|
return report, nil
|
||||||
|
|
|
@ -531,15 +531,6 @@ func newTarAppender(idMapping idtools.IdentityMapping, writer io.Writer, chownOp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanonicalTarNameForPath canonicalizes relativePath to a POSIX-style path using
|
|
||||||
// forward slashes. It is an alias for [filepath.ToSlash], which is a no-op on
|
|
||||||
// Linux and Unix.
|
|
||||||
//
|
|
||||||
// Deprecated: use [filepath.ToSlash]. This function will be removed in the next release.
|
|
||||||
func CanonicalTarNameForPath(relativePath string) string {
|
|
||||||
return filepath.ToSlash(relativePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// canonicalTarName provides a platform-independent and consistent POSIX-style
|
// canonicalTarName provides a platform-independent and consistent POSIX-style
|
||||||
// path for files and directories to be archived regardless of the platform.
|
// path for files and directories to be archived regardless of the platform.
|
||||||
func canonicalTarName(name string, isDir bool) string {
|
func canonicalTarName(name string, isDir bool) string {
|
||||||
|
@ -1441,60 +1432,3 @@ func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, error) {
|
||||||
return err
|
return err
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTempArchive reads the content of src into a temporary file, and returns the contents
|
|
||||||
// of that file as an archive. The archive can only be read once - as soon as reading completes,
|
|
||||||
// the file will be deleted.
|
|
||||||
//
|
|
||||||
// Deprecated: NewTempArchive is only used in tests and will be removed in the next release.
|
|
||||||
func NewTempArchive(src io.Reader, dir string) (*TempArchive, error) {
|
|
||||||
f, err := os.CreateTemp(dir, "")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if _, err := io.Copy(f, src); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if _, err := f.Seek(0, 0); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
st, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
size := st.Size()
|
|
||||||
return &TempArchive{File: f, Size: size}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TempArchive is a temporary archive. The archive can only be read once - as soon as reading completes,
|
|
||||||
// the file will be deleted.
|
|
||||||
//
|
|
||||||
// Deprecated: TempArchive is only used in tests and will be removed in the next release.
|
|
||||||
type TempArchive struct {
|
|
||||||
*os.File
|
|
||||||
Size int64 // Pre-computed from Stat().Size() as a convenience
|
|
||||||
read int64
|
|
||||||
closed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the underlying file if it's still open, or does a no-op
|
|
||||||
// to allow callers to try to close the TempArchive multiple times safely.
|
|
||||||
func (archive *TempArchive) Close() error {
|
|
||||||
if archive.closed {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
archive.closed = true
|
|
||||||
|
|
||||||
return archive.File.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (archive *TempArchive) Read(data []byte) (int, error) {
|
|
||||||
n, err := archive.File.Read(data)
|
|
||||||
archive.read += int64(n)
|
|
||||||
if err != nil || archive.read == archive.Size {
|
|
||||||
archive.Close()
|
|
||||||
os.Remove(archive.File.Name())
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,11 +11,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Prefix is the longpath prefix for Windows file paths.
|
|
||||||
//
|
|
||||||
// Deprecated: this const is only used internally, and will be removed in the next release
|
|
||||||
const Prefix = longPathPrefix
|
|
||||||
|
|
||||||
// longPathPrefix is the longpath prefix for Windows file paths.
|
// longPathPrefix is the longpath prefix for Windows file paths.
|
||||||
const longPathPrefix = `\\?\`
|
const longPathPrefix = `\\?\`
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,6 @@ package stringid // import "github.com/docker/docker/pkg/stringid"
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,22 +12,6 @@ const (
|
||||||
fullLen = 64
|
fullLen = 64
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
validShortID = regexp.MustCompile("^[a-f0-9]{12}$")
|
|
||||||
validHex = regexp.MustCompile(`^[a-f0-9]{64}$`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsShortID determines if id has the correct format and length for a short ID.
|
|
||||||
// It checks the IDs length and if it consists of valid characters for IDs (a-f0-9).
|
|
||||||
//
|
|
||||||
// Deprecated: this function is no longer used, and will be removed in the next release.
|
|
||||||
func IsShortID(id string) bool {
|
|
||||||
if len(id) != shortLen {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return validShortID.MatchString(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TruncateID returns a shorthand version of a string identifier for convenience.
|
// TruncateID returns a shorthand version of a string identifier for convenience.
|
||||||
// A collision with other shorthands is very unlikely, but possible.
|
// A collision with other shorthands is very unlikely, but possible.
|
||||||
// In case of a collision a lookup with TruncIndex.Get() will fail, and the caller
|
// In case of a collision a lookup with TruncIndex.Get() will fail, and the caller
|
||||||
|
@ -45,7 +26,10 @@ func TruncateID(id string) string {
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRandomID returns a unique id.
|
// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9.
|
||||||
|
// It guarantees that the ID, when truncated ([TruncateID]) does not consist
|
||||||
|
// of numbers only, so that the truncated ID can be used as hostname for
|
||||||
|
// containers.
|
||||||
func GenerateRandomID() string {
|
func GenerateRandomID() string {
|
||||||
b := make([]byte, 32)
|
b := make([]byte, 32)
|
||||||
for {
|
for {
|
||||||
|
@ -53,25 +37,27 @@ func GenerateRandomID() string {
|
||||||
panic(err) // This shouldn't happen
|
panic(err) // This shouldn't happen
|
||||||
}
|
}
|
||||||
id := hex.EncodeToString(b)
|
id := hex.EncodeToString(b)
|
||||||
// if we try to parse the truncated for as an int and we don't have
|
|
||||||
// an error then the value is all numeric and causes issues when
|
// make sure that the truncated ID does not consist of only numeric
|
||||||
// used as a hostname. ref #3869
|
// characters, as it's used as default hostname for containers.
|
||||||
if _, err := strconv.ParseInt(TruncateID(id), 10, 64); err == nil {
|
//
|
||||||
|
// See:
|
||||||
|
// - https://github.com/moby/moby/issues/3869
|
||||||
|
// - https://bugzilla.redhat.com/show_bug.cgi?id=1059122
|
||||||
|
if allNum(id[:shortLen]) {
|
||||||
|
// all numbers; try again
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateID checks whether an ID string is a valid, full-length image ID.
|
// allNum checks whether id consists of only numbers (0-9).
|
||||||
//
|
func allNum(id string) bool {
|
||||||
// Deprecated: use [github.com/docker/docker/image/v1.ValidateID] instead. Will be removed in the next release.
|
for _, c := range []byte(id) {
|
||||||
func ValidateID(id string) error {
|
if c > '9' || c < '0' {
|
||||||
if len(id) != fullLen {
|
return false
|
||||||
return errors.New("image ID '" + id + "' is invalid")
|
|
||||||
}
|
}
|
||||||
if !validHex.MatchString(id) {
|
|
||||||
return errors.New("image ID '" + id + "' is invalid")
|
|
||||||
}
|
}
|
||||||
return nil
|
return 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.20241018142220-36a3bd090489+incompatible
|
# github.com/docker/docker v27.0.2-0.20241031194140-6ac445c42bad+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