mirror of
https://github.com/containers/skopeo.git
synced 2025-07-12 14:08:37 +00:00
Bump github.com/containers/image/v5 from 5.6.0 to 5.8.0
Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.6.0 to 5.8.0. - [Release notes](https://github.com/containers/image/releases) - [Commits](https://github.com/containers/image/compare/v5.6.0...v5.8.0) Signed-off-by: dependabot-preview[bot] <support@dependabot.com> Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
parent
7fee9122fb
commit
e30abff31b
2
go.mod
2
go.mod
@ -4,7 +4,7 @@ go 1.12
|
||||
|
||||
require (
|
||||
github.com/containers/common v0.27.0
|
||||
github.com/containers/image/v5 v5.7.0
|
||||
github.com/containers/image/v5 v5.8.0
|
||||
github.com/containers/ocicrypt v1.0.3
|
||||
github.com/containers/storage v1.24.0
|
||||
github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f
|
||||
|
12
go.sum
12
go.sum
@ -43,6 +43,9 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.0.2/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.0.0-20200507155900-a9f01edf17e3/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s=
|
||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
@ -59,13 +62,15 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
|
||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||
github.com/containers/common v0.27.0 h1:+QlYEOitVYtU9/x8xebRgxdGqt4sLaIqV6MBOns+zLk=
|
||||
github.com/containers/common v0.27.0/go.mod h1:ZTswJJfu4aGF6Anyi2yON8Getda9NDYcdIzurOEHHXI=
|
||||
github.com/containers/image/v5 v5.7.0 h1:fiTC8/Xbr+zEP6njGTZtPW/3UD7MC93nC9DbUoWdxkA=
|
||||
github.com/containers/image/v5 v5.7.0/go.mod h1:8aOy+YaItukxghRORkvhq5ibWttHErzDLy6egrKfKos=
|
||||
github.com/containers/image/v5 v5.8.0 h1:B3FGHi0bdGXgg698kBIGOlHCXN5n+scJr6/5354GOPU=
|
||||
github.com/containers/image/v5 v5.8.0/go.mod h1:jKxdRtyIDumVa56hdsZvV+gwx4zB50hRou6pIuCWLkg=
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
|
||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
||||
github.com/containers/ocicrypt v1.0.3 h1:vYgl+RZ9Q3DPMuTfxmN+qp0X2Bj52uuY2vnt6GzVe1c=
|
||||
github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g=
|
||||
github.com/containers/storage v1.23.6/go.mod h1:haFs0HRowKwyzvWEx9EgI3WsL8XCSnBDb5f8P5CAxJY=
|
||||
github.com/containers/storage v1.23.7/go.mod h1:cUT2zHjtx+WlVri30obWmM2gpqpi8jfPsmIzP1TVpEI=
|
||||
github.com/containers/storage v1.23.9/go.mod h1:3b2ktpB6pw53SEeIoFfO0sQfP9+IoJJKPq5iJk74gxE=
|
||||
github.com/containers/storage v1.24.0 h1:Fo2LkF7tkMLmo38sTZ/G8wHjcn8JfUFPfyTxM4WwMfk=
|
||||
github.com/containers/storage v1.24.0/go.mod h1:A4d3BzuZK9b3oLVEsiSRhZLPIx3z7utgiPyXLK/YMhY=
|
||||
@ -191,6 +196,7 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
@ -210,9 +216,12 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
|
||||
@ -450,6 +459,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
17
vendor/github.com/containers/image/v5/copy/copy.go
generated
vendored
17
vendor/github.com/containers/image/v5/copy/copy.go
generated
vendored
@ -1166,6 +1166,21 @@ func computeDiffID(stream io.Reader, decompressor compression.DecompressorFunc)
|
||||
return digest.Canonical.FromReader(stream)
|
||||
}
|
||||
|
||||
// errorAnnotationReader wraps the io.Reader passed to PutBlob for annotating the error happened during read.
|
||||
// These errors are reported as PutBlob errors, so we would otherwise misleadingly attribute them to the copy destination.
|
||||
type errorAnnotationReader struct {
|
||||
reader io.Reader
|
||||
}
|
||||
|
||||
// Read annotates the error happened during read
|
||||
func (r errorAnnotationReader) Read(b []byte) (n int, err error) {
|
||||
n, err = r.reader.Read(b)
|
||||
if err != io.EOF {
|
||||
return n, errors.Wrapf(err, "error happened during read")
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// copyBlobFromStream copies a blob with srcInfo (with known Digest and Annotations and possibly known Size) from srcStream to dest,
|
||||
// perhaps sending a copy to an io.Writer if getOriginalLayerCopyWriter != nil,
|
||||
// perhaps compressing it if canCompress,
|
||||
@ -1335,7 +1350,7 @@ func (c *copier) copyBlobFromStream(ctx context.Context, srcStream io.Reader, sr
|
||||
}
|
||||
|
||||
// === Finally, send the layer stream to dest.
|
||||
uploadedInfo, err := c.dest.PutBlob(ctx, destStream, inputInfo, c.blobInfoCache, isConfig)
|
||||
uploadedInfo, err := c.dest.PutBlob(ctx, &errorAnnotationReader{destStream}, inputInfo, c.blobInfoCache, isConfig)
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, errors.Wrap(err, "Error writing blob")
|
||||
}
|
||||
|
47
vendor/github.com/containers/image/v5/docker/docker_image.go
generated
vendored
47
vendor/github.com/containers/image/v5/docker/docker_image.go
generated
vendored
@ -4,12 +4,15 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/image"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -103,3 +106,47 @@ func GetRepositoryTags(ctx context.Context, sys *types.SystemContext, ref types.
|
||||
}
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
// GetDigest returns the image's digest
|
||||
// Use this to optimize and avoid use of an ImageSource based on the returned digest;
|
||||
// if you are going to use an ImageSource anyway, it’s more efficient to create it first
|
||||
// and compute the digest from the value returned by GetManifest.
|
||||
// NOTE: Implemented to avoid Docker Hub API limits, and mirror configuration may be
|
||||
// ignored (but may be implemented in the future)
|
||||
func GetDigest(ctx context.Context, sys *types.SystemContext, ref types.ImageReference) (digest.Digest, error) {
|
||||
dr, ok := ref.(dockerReference)
|
||||
if !ok {
|
||||
return "", errors.Errorf("ref must be a dockerReference")
|
||||
}
|
||||
|
||||
tagOrDigest, err := dr.tagOrDigest()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
client, err := newDockerClientFromRef(sys, dr, false, "pull")
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to create client")
|
||||
}
|
||||
|
||||
path := fmt.Sprintf(manifestPath, reference.Path(dr.ref), tagOrDigest)
|
||||
headers := map[string][]string{
|
||||
"Accept": manifest.DefaultRequestedManifestMIMETypes,
|
||||
}
|
||||
|
||||
res, err := client.makeRequest(ctx, "HEAD", path, headers, nil, v2Auth, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return "", errors.Wrapf(registryHTTPResponseToError(res), "Error reading digest %s in %s", tagOrDigest, dr.ref.Name())
|
||||
}
|
||||
|
||||
dig, err := digest.Parse(res.Header.Get("Docker-Content-Digest"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return dig, nil
|
||||
}
|
||||
|
328
vendor/github.com/containers/image/v5/pkg/sysregistriesv2/shortnames.go
generated
vendored
Normal file
328
vendor/github.com/containers/image/v5/pkg/sysregistriesv2/shortnames.go
generated
vendored
Normal file
@ -0,0 +1,328 @@
|
||||
package sysregistriesv2
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage/pkg/lockfile"
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// defaultShortNameMode is the default mode of registries.conf files if the
|
||||
// corresponding field is left empty.
|
||||
const defaultShortNameMode = types.ShortNameModePermissive
|
||||
|
||||
// userShortNamesFile is the user-specific config file to store aliases.
|
||||
var userShortNamesFile = filepath.FromSlash("containers/short-name-aliases.conf")
|
||||
|
||||
// shortNameAliasesConfPath returns the path to the machine-generated
|
||||
// short-name-aliases.conf file.
|
||||
func shortNameAliasesConfPath(ctx *types.SystemContext) (string, error) {
|
||||
if ctx != nil && len(ctx.UserShortNameAliasConfPath) > 0 {
|
||||
return ctx.UserShortNameAliasConfPath, nil
|
||||
}
|
||||
|
||||
configHome, err := homedir.GetConfigHome()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filepath.Join(configHome, userShortNamesFile), nil
|
||||
}
|
||||
|
||||
// shortNameAliasConf is a subset of the `V2RegistriesConf` format. It's used in the
|
||||
// software-maintained `userShortNamesFile`.
|
||||
type shortNameAliasConf struct {
|
||||
// A map for aliasing short names to their fully-qualified image
|
||||
// reference counter parts.
|
||||
// Note that Aliases is niled after being loaded from a file.
|
||||
Aliases map[string]string `toml:"aliases"`
|
||||
}
|
||||
|
||||
// alias combines the parsed value of an alias with the config file it has been
|
||||
// specified in. The config file is crucial for an improved user experience
|
||||
// such that users are able to resolve potential pull errors.
|
||||
type alias struct {
|
||||
// The parsed value of an alias. May be nil if set to "" in a config.
|
||||
value reference.Named
|
||||
// The config file the alias originates from.
|
||||
configOrigin string
|
||||
}
|
||||
|
||||
// shortNameAliasCache is the result of parsing shortNameAliasConf,
|
||||
// pre-processed for faster usage.
|
||||
type shortNameAliasCache struct {
|
||||
// Note that an alias value may be nil iff it's set as an empty string
|
||||
// in the config.
|
||||
namedAliases map[string]alias
|
||||
}
|
||||
|
||||
// ResolveShortNameAlias performs an alias resolution of the specified name.
|
||||
// The user-specific short-name-aliases.conf has precedence over aliases in the
|
||||
// assembled registries.conf. It returns the possibly resolved alias or nil, a
|
||||
// human-readable description of the config where the alias is specified, and
|
||||
// an error. The origin of the config file is crucial for an improved user
|
||||
// experience such that users are able to resolve potential pull errors.
|
||||
// Almost all callers should use pkg/shortnames instead.
|
||||
//
|
||||
// Note that it’s the caller’s responsibility to pass only a repository
|
||||
// (reference.IsNameOnly) as the short name.
|
||||
func ResolveShortNameAlias(ctx *types.SystemContext, name string) (reference.Named, string, error) {
|
||||
if err := validateShortName(name); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
confPath, lock, err := shortNameAliasesConfPathAndLock(ctx)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// Acquire the lock as a reader to allow for multiple routines in the
|
||||
// same process space to read simultaneously.
|
||||
lock.RLock()
|
||||
defer lock.Unlock()
|
||||
|
||||
_, aliasCache, err := loadShortNameAliasConf(confPath)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// First look up the short-name-aliases.conf. Note that a value may be
|
||||
// nil iff it's set as an empty string in the config.
|
||||
alias, resolved := aliasCache.namedAliases[name]
|
||||
if resolved {
|
||||
return alias.value, alias.configOrigin, nil
|
||||
}
|
||||
|
||||
config, err := getConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
alias, resolved = config.aliasCache.namedAliases[name]
|
||||
if resolved {
|
||||
return alias.value, alias.configOrigin, nil
|
||||
}
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
// editShortNameAlias loads the aliases.conf file and changes it. If value is
|
||||
// set, it adds the name-value pair as a new alias. Otherwise, it will remove
|
||||
// name from the config.
|
||||
func editShortNameAlias(ctx *types.SystemContext, name string, value *string) error {
|
||||
if err := validateShortName(name); err != nil {
|
||||
return err
|
||||
}
|
||||
if value != nil {
|
||||
if _, err := parseShortNameValue(*value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
confPath, lock, err := shortNameAliasesConfPathAndLock(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Acquire the lock as a writer to prevent data corruption.
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
// Load the short-name-alias.conf, add the specified name-value pair,
|
||||
// and write it back to the file.
|
||||
conf, _, err := loadShortNameAliasConf(confPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if conf.Aliases == nil { // Ensure we have a map to update.
|
||||
conf.Aliases = make(map[string]string)
|
||||
}
|
||||
if value != nil {
|
||||
conf.Aliases[name] = *value
|
||||
} else {
|
||||
// If the name does not exist, throw an error.
|
||||
if _, exists := conf.Aliases[name]; !exists {
|
||||
return errors.Errorf("short-name alias %q not found in %q: please check registries.conf files", name, confPath)
|
||||
}
|
||||
|
||||
delete(conf.Aliases, name)
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(confPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
encoder := toml.NewEncoder(f)
|
||||
return encoder.Encode(conf)
|
||||
}
|
||||
|
||||
// AddShortNameAlias adds the specified name-value pair as a new alias to the
|
||||
// user-specific aliases.conf. It may override an existing alias for `name`.
|
||||
//
|
||||
// Note that it’s the caller’s responsibility to pass only a repository
|
||||
// (reference.IsNameOnly) as the short name.
|
||||
func AddShortNameAlias(ctx *types.SystemContext, name string, value string) error {
|
||||
return editShortNameAlias(ctx, name, &value)
|
||||
}
|
||||
|
||||
// RemoveShortNameAlias clears the alias for the specified name. It throws an
|
||||
// error in case name does not exist in the machine-generated
|
||||
// short-name-alias.conf. In such case, the alias must be specified in one of
|
||||
// the registries.conf files, which is the users' responsibility.
|
||||
//
|
||||
// Note that it’s the caller’s responsibility to pass only a repository
|
||||
// (reference.IsNameOnly) as the short name.
|
||||
func RemoveShortNameAlias(ctx *types.SystemContext, name string) error {
|
||||
return editShortNameAlias(ctx, name, nil)
|
||||
}
|
||||
|
||||
// parseShortNameValue parses the specified alias into a reference.Named. The alias is
|
||||
// expected to not be tagged or carry a digest and *must* include a
|
||||
// domain/registry.
|
||||
//
|
||||
// Note that the returned reference is always normalized.
|
||||
func parseShortNameValue(alias string) (reference.Named, error) {
|
||||
ref, err := reference.Parse(alias)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing alias %q", alias)
|
||||
}
|
||||
|
||||
if _, ok := ref.(reference.Digested); ok {
|
||||
return nil, errors.Errorf("invalid alias %q: must not contain digest", alias)
|
||||
}
|
||||
|
||||
if _, ok := ref.(reference.Tagged); ok {
|
||||
return nil, errors.Errorf("invalid alias %q: must not contain tag", alias)
|
||||
}
|
||||
|
||||
named, ok := ref.(reference.Named)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("invalid alias %q: must contain registry and repository", alias)
|
||||
}
|
||||
|
||||
registry := reference.Domain(named)
|
||||
if !(strings.ContainsAny(registry, ".:") || registry == "localhost") {
|
||||
return nil, errors.Errorf("invalid alias %q: must contain registry and repository", alias)
|
||||
}
|
||||
|
||||
// A final parse to make sure that docker.io references are correctly
|
||||
// normalized (e.g., docker.io/alpine to docker.io/library/alpine.
|
||||
named, err = reference.ParseNormalizedNamed(alias)
|
||||
return named, err
|
||||
}
|
||||
|
||||
// validateShortName parses the specified `name` of an alias (i.e., the left-hand
|
||||
// side) and checks if it's a short name and does not include a tag or digest.
|
||||
func validateShortName(name string) error {
|
||||
repo, err := reference.Parse(name)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cannot parse short name: %q", name)
|
||||
}
|
||||
|
||||
if _, ok := repo.(reference.Digested); ok {
|
||||
return errors.Errorf("invalid short name %q: must not contain digest", name)
|
||||
}
|
||||
|
||||
if _, ok := repo.(reference.Tagged); ok {
|
||||
return errors.Errorf("invalid short name %q: must not contain tag", name)
|
||||
}
|
||||
|
||||
named, ok := repo.(reference.Named)
|
||||
if !ok {
|
||||
return errors.Errorf("invalid short name %q: no name", name)
|
||||
}
|
||||
|
||||
registry := reference.Domain(named)
|
||||
if strings.ContainsAny(registry, ".:") || registry == "localhost" {
|
||||
return errors.Errorf("invalid short name %q: must not contain registry", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// newShortNameAliasCache parses shortNameAliasConf and returns the corresponding internal
|
||||
// representation.
|
||||
func newShortNameAliasCache(path string, conf *shortNameAliasConf) (*shortNameAliasCache, error) {
|
||||
res := shortNameAliasCache{
|
||||
namedAliases: make(map[string]alias),
|
||||
}
|
||||
errs := []error{}
|
||||
for name, value := range conf.Aliases {
|
||||
if err := validateShortName(name); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
// Empty right-hand side values in config files allow to reset
|
||||
// an alias in a previously loaded config. This way, drop-in
|
||||
// config files from registries.conf.d can reset potentially
|
||||
// malconfigured aliases.
|
||||
if value == "" {
|
||||
res.namedAliases[name] = alias{nil, path}
|
||||
continue
|
||||
}
|
||||
|
||||
named, err := parseShortNameValue(value)
|
||||
if err != nil {
|
||||
// We want to report *all* malformed entries to avoid a
|
||||
// whack-a-mole for the user.
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
res.namedAliases[name] = alias{named, path}
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
err := errs[0]
|
||||
for i := 1; i < len(errs); i++ {
|
||||
err = errors.Wrapf(err, "%v\n", errs[i])
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// updateWithConfigurationFrom updates c with configuration from updates.
|
||||
// In case of conflict, updates is preferred.
|
||||
func (c *shortNameAliasCache) updateWithConfigurationFrom(updates *shortNameAliasCache) {
|
||||
for name, value := range updates.namedAliases {
|
||||
c.namedAliases[name] = value
|
||||
}
|
||||
}
|
||||
|
||||
func loadShortNameAliasConf(confPath string) (*shortNameAliasConf, *shortNameAliasCache, error) {
|
||||
conf := shortNameAliasConf{}
|
||||
|
||||
_, err := toml.DecodeFile(confPath, &conf)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
// It's okay if the config doesn't exist. Other errors are not.
|
||||
return nil, nil, errors.Wrapf(err, "error loading short-name aliases config file %q", confPath)
|
||||
}
|
||||
|
||||
// Even if we don’t always need the cache, doing so validates the machine-generated config. The
|
||||
// file could still be corrupted by another process or user.
|
||||
cache, err := newShortNameAliasCache(confPath, &conf)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "error loading short-name aliases config file %q", confPath)
|
||||
}
|
||||
|
||||
return &conf, cache, nil
|
||||
}
|
||||
|
||||
func shortNameAliasesConfPathAndLock(ctx *types.SystemContext) (string, lockfile.Locker, error) {
|
||||
shortNameAliasesConfPath, err := shortNameAliasesConfPath(ctx)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
// Make sure the path to file exists.
|
||||
if err := os.MkdirAll(filepath.Dir(shortNameAliasesConfPath), 0700); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
lockPath := shortNameAliasesConfPath + ".lock"
|
||||
locker, err := lockfile.GetLockfile(lockPath)
|
||||
return shortNameAliasesConfPath, locker, err
|
||||
}
|
252
vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go
generated
vendored
252
vendor/github.com/containers/image/v5/pkg/sysregistriesv2/system_registries_v2.go
generated
vendored
@ -154,6 +154,19 @@ type V2RegistriesConf struct {
|
||||
Registries []Registry `toml:"registry"`
|
||||
// An array of host[:port] (not prefix!) entries to use for resolving unqualified image references
|
||||
UnqualifiedSearchRegistries []string `toml:"unqualified-search-registries"`
|
||||
|
||||
// ShortNameMode defines how short-name resolution should be handled by
|
||||
// _consumers_ of this package. Depending on the mode, the user should
|
||||
// be prompted with a choice of using one of the unqualified-search
|
||||
// registries when referring to a short name.
|
||||
//
|
||||
// Valid modes are: * "prompt": prompt if stdout is a TTY, otherwise
|
||||
// use all unqualified-search registries * "enforcing": always prompt
|
||||
// and error if stdout is not a TTY * "disabled": do not prompt and
|
||||
// potentially use all unqualified-search registries
|
||||
ShortNameMode string `toml:"short-name-mode"`
|
||||
|
||||
shortNameAliasConf
|
||||
}
|
||||
|
||||
// Nonempty returns true if config contains at least one configuration entry.
|
||||
@ -162,10 +175,23 @@ func (config *V2RegistriesConf) Nonempty() bool {
|
||||
len(config.UnqualifiedSearchRegistries) != 0)
|
||||
}
|
||||
|
||||
// tomlConfig is the data type used to unmarshal the toml config.
|
||||
type tomlConfig struct {
|
||||
V2RegistriesConf
|
||||
V1RegistriesConf // for backwards compatibility with sysregistries v1
|
||||
// parsedConfig is the result of parsing, and possibly merging, configuration files;
|
||||
// it is the boundary between the process of reading+ingesting the files, and
|
||||
// later interpreting the configuraiton based on caller’s requests.
|
||||
type parsedConfig struct {
|
||||
// NOTE: Update also parsedConfig.updateWithConfigurationFrom!
|
||||
|
||||
// partialV2 must continue to exist to maintain the return value of TryUpdatingCache
|
||||
// for compatibility with existing callers.
|
||||
// We store the authoritative Registries and UnqualifiedSearchRegistries values there as well.
|
||||
partialV2 V2RegistriesConf
|
||||
// Absolute path to the configuration file that set the UnqualifiedSearchRegistries.
|
||||
unqualifiedSearchRegistriesOrigin string
|
||||
// Result of parsing of partialV2.ShortNameMode.
|
||||
// NOTE: May be ShortNameModeInvalid to represent ShortNameMode == "" in intermediate values;
|
||||
// the full configuration in configCache / getConfig() always contains a valid value.
|
||||
shortNameMode types.ShortNameMode
|
||||
aliasCache *shortNameAliasCache
|
||||
}
|
||||
|
||||
// InvalidRegistries represents an invalid registry configurations. An example
|
||||
@ -254,7 +280,7 @@ var anchoredDomainRegexp = regexp.MustCompile("^" + reference.DomainRegexp.Strin
|
||||
|
||||
// postProcess checks the consistency of all the configuration, looks for conflicts,
|
||||
// and normalizes the configuration (e.g., sets the Prefix to Location if not set).
|
||||
func (config *V2RegistriesConf) postProcess() error {
|
||||
func (config *V2RegistriesConf) postProcessRegistries() error {
|
||||
regMap := make(map[string][]*Registry)
|
||||
|
||||
for i := range config.Registries {
|
||||
@ -301,6 +327,7 @@ func (config *V2RegistriesConf) postProcess() error {
|
||||
msg := fmt.Sprintf("registry '%s' is defined multiple times with conflicting 'insecure' setting", reg.Location)
|
||||
return &InvalidRegistries{s: msg}
|
||||
}
|
||||
|
||||
if reg.Blocked != other.Blocked {
|
||||
msg := fmt.Sprintf("registry '%s' is defined multiple times with conflicting 'blocked' setting", reg.Location)
|
||||
return &InvalidRegistries{s: msg}
|
||||
@ -323,16 +350,25 @@ func (config *V2RegistriesConf) postProcess() error {
|
||||
// rendering later items with the same prefix non-existent. We cannot error
|
||||
// out anymore as this might break existing users, so let's just ignore them
|
||||
// to guarantee that the same prefix exists only once.
|
||||
knownPrefixes := make(map[string]bool)
|
||||
uniqueRegistries := []Registry{}
|
||||
//
|
||||
// As a side effect of parsedConfig.updateWithConfigurationFrom, the Registries slice
|
||||
// is always sorted. To be consistent in situations where it is not called (no drop-ins),
|
||||
// sort it here as well.
|
||||
prefixes := []string{}
|
||||
uniqueRegistries := make(map[string]Registry)
|
||||
for i := range config.Registries {
|
||||
// TODO: should we warn if we see the same prefix being used multiple times?
|
||||
if _, exists := knownPrefixes[config.Registries[i].Prefix]; !exists {
|
||||
knownPrefixes[config.Registries[i].Prefix] = true
|
||||
uniqueRegistries = append(uniqueRegistries, config.Registries[i])
|
||||
prefix := config.Registries[i].Prefix
|
||||
if _, exists := uniqueRegistries[prefix]; !exists {
|
||||
uniqueRegistries[prefix] = config.Registries[i]
|
||||
prefixes = append(prefixes, prefix)
|
||||
}
|
||||
}
|
||||
config.Registries = uniqueRegistries
|
||||
sort.Strings(prefixes)
|
||||
config.Registries = []Registry{}
|
||||
for _, prefix := range prefixes {
|
||||
config.Registries = append(config.Registries, uniqueRegistries[prefix])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -385,6 +421,7 @@ func newConfigWrapper(ctx *types.SystemContext) configWrapper {
|
||||
} else {
|
||||
wrapper.userConfigDirPath = userRegistriesDirPath
|
||||
}
|
||||
|
||||
return wrapper
|
||||
} else if ctx != nil && ctx.RootForImplicitAbsolutePaths != "" {
|
||||
wrapper.configPath = filepath.Join(ctx.RootForImplicitAbsolutePaths, systemRegistriesConfPath)
|
||||
@ -426,7 +463,7 @@ var configMutex = sync.Mutex{}
|
||||
// configCache caches already loaded configs with config paths as keys and is
|
||||
// used to avoid redundantly parsing configs. Concurrent accesses to the cache
|
||||
// are synchronized via configMutex.
|
||||
var configCache = make(map[configWrapper]*V2RegistriesConf)
|
||||
var configCache = make(map[configWrapper]*parsedConfig)
|
||||
|
||||
// InvalidateCache invalidates the registry cache. This function is meant to be
|
||||
// used for long-running processes that need to reload potential changes made to
|
||||
@ -434,11 +471,11 @@ var configCache = make(map[configWrapper]*V2RegistriesConf)
|
||||
func InvalidateCache() {
|
||||
configMutex.Lock()
|
||||
defer configMutex.Unlock()
|
||||
configCache = make(map[configWrapper]*V2RegistriesConf)
|
||||
configCache = make(map[configWrapper]*parsedConfig)
|
||||
}
|
||||
|
||||
// getConfig returns the config object corresponding to ctx, loading it if it is not yet cached.
|
||||
func getConfig(ctx *types.SystemContext) (*V2RegistriesConf, error) {
|
||||
func getConfig(ctx *types.SystemContext) (*parsedConfig, error) {
|
||||
wrapper := newConfigWrapper(ctx)
|
||||
configMutex.Lock()
|
||||
if config, inCache := configCache[wrapper]; inCache {
|
||||
@ -504,27 +541,37 @@ func dropInConfigs(wrapper configWrapper) ([]string, error) {
|
||||
// TryUpdatingCache loads the configuration from the provided `SystemContext`
|
||||
// without using the internal cache. On success, the loaded configuration will
|
||||
// be added into the internal registry cache.
|
||||
// It returns the resulting configuration; this is DEPRECATED and may not correctly
|
||||
// reflect any future data handled by this package.
|
||||
func TryUpdatingCache(ctx *types.SystemContext) (*V2RegistriesConf, error) {
|
||||
return tryUpdatingCache(ctx, newConfigWrapper(ctx))
|
||||
config, err := tryUpdatingCache(ctx, newConfigWrapper(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &config.partialV2, err
|
||||
}
|
||||
|
||||
// tryUpdatingCache implements TryUpdatingCache with an additional configWrapper
|
||||
// argument to avoid redundantly calculating the config paths.
|
||||
func tryUpdatingCache(ctx *types.SystemContext, wrapper configWrapper) (*V2RegistriesConf, error) {
|
||||
func tryUpdatingCache(ctx *types.SystemContext, wrapper configWrapper) (*parsedConfig, error) {
|
||||
configMutex.Lock()
|
||||
defer configMutex.Unlock()
|
||||
|
||||
// load the config
|
||||
config := &tomlConfig{}
|
||||
if err := config.loadConfig(wrapper.configPath, false); err != nil {
|
||||
config, err := loadConfigFile(wrapper.configPath, false)
|
||||
if err != nil {
|
||||
// Continue with an empty []Registry if we use the default config, which
|
||||
// implies that the config path of the SystemContext isn't set.
|
||||
//
|
||||
// Note: if ctx.SystemRegistriesConfPath points to the default config,
|
||||
// we will still return an error.
|
||||
if os.IsNotExist(err) && (ctx == nil || ctx.SystemRegistriesConfPath == "") {
|
||||
config = &tomlConfig{}
|
||||
config.V2RegistriesConf = V2RegistriesConf{Registries: []Registry{}}
|
||||
config = &parsedConfig{}
|
||||
config.partialV2 = V2RegistriesConf{Registries: []Registry{}}
|
||||
config.aliasCache, err = newShortNameAliasCache("", &shortNameAliasConf{})
|
||||
if err != nil {
|
||||
return nil, err // Should never happen
|
||||
}
|
||||
} else {
|
||||
return nil, errors.Wrapf(err, "error loading registries configuration %q", wrapper.configPath)
|
||||
}
|
||||
@ -537,16 +584,20 @@ func tryUpdatingCache(ctx *types.SystemContext, wrapper configWrapper) (*V2Regis
|
||||
}
|
||||
for _, path := range dinConfigs {
|
||||
// Enforce v2 format for drop-in-configs.
|
||||
if err := config.loadConfig(path, true); err != nil {
|
||||
dropIn, err := loadConfigFile(path, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error loading drop-in registries configuration %q", path)
|
||||
}
|
||||
config.updateWithConfigurationFrom(dropIn)
|
||||
}
|
||||
|
||||
v2Config := &config.V2RegistriesConf
|
||||
if config.shortNameMode == types.ShortNameModeInvalid {
|
||||
config.shortNameMode = defaultShortNameMode
|
||||
}
|
||||
|
||||
// populate the cache
|
||||
configCache[wrapper] = v2Config
|
||||
return v2Config, nil
|
||||
configCache[wrapper] = config
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// GetRegistries loads and returns the registries specified in the config.
|
||||
@ -557,17 +608,53 @@ func GetRegistries(ctx *types.SystemContext) ([]Registry, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config.Registries, nil
|
||||
return config.partialV2.Registries, nil
|
||||
}
|
||||
|
||||
// UnqualifiedSearchRegistries returns a list of host[:port] entries to try
|
||||
// for unqualified image search, in the returned order)
|
||||
func UnqualifiedSearchRegistries(ctx *types.SystemContext) ([]string, error) {
|
||||
registries, _, err := UnqualifiedSearchRegistriesWithOrigin(ctx)
|
||||
return registries, err
|
||||
}
|
||||
|
||||
// UnqualifiedSearchRegistriesWithOrigin returns a list of host[:port] entries
|
||||
// to try for unqualified image search, in the returned order. It also returns
|
||||
// a human-readable description of where these entries are specified (e.g., a
|
||||
// registries.conf file).
|
||||
func UnqualifiedSearchRegistriesWithOrigin(ctx *types.SystemContext) ([]string, string, error) {
|
||||
config, err := getConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
return config.UnqualifiedSearchRegistries, nil
|
||||
return config.partialV2.UnqualifiedSearchRegistries, config.unqualifiedSearchRegistriesOrigin, nil
|
||||
}
|
||||
|
||||
// parseShortNameMode translates the string into well-typed
|
||||
// types.ShortNameMode.
|
||||
func parseShortNameMode(mode string) (types.ShortNameMode, error) {
|
||||
switch mode {
|
||||
case "disabled":
|
||||
return types.ShortNameModeDisabled, nil
|
||||
case "enforcing":
|
||||
return types.ShortNameModeEnforcing, nil
|
||||
case "permissive":
|
||||
return types.ShortNameModePermissive, nil
|
||||
default:
|
||||
return types.ShortNameModeInvalid, errors.Errorf("invalid short-name mode: %q", mode)
|
||||
}
|
||||
}
|
||||
|
||||
// GetShortNameMode returns the configured types.ShortNameMode.
|
||||
func GetShortNameMode(ctx *types.SystemContext) (types.ShortNameMode, error) {
|
||||
if ctx != nil && ctx.ShortNameMode != nil {
|
||||
return *ctx.ShortNameMode, nil
|
||||
}
|
||||
config, err := getConfig(ctx)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return config.shortNameMode, err
|
||||
}
|
||||
|
||||
// refMatchesPrefix returns true iff ref,
|
||||
@ -609,7 +696,7 @@ func FindRegistry(ctx *types.SystemContext, ref string) (*Registry, error) {
|
||||
|
||||
reg := Registry{}
|
||||
prefixLen := 0
|
||||
for _, r := range config.Registries {
|
||||
for _, r := range config.partialV2.Registries {
|
||||
if refMatchesPrefix(ref, r.Prefix) {
|
||||
length := len(r.Prefix)
|
||||
if length > prefixLen {
|
||||
@ -624,55 +711,87 @@ func FindRegistry(ctx *types.SystemContext, ref string) (*Registry, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// loadConfig loads and unmarshals the configuration at the specified path. Note
|
||||
// that v1 configs are translated into v2 and are cleared. Use forceV2 if the
|
||||
// config must in the v2 format.
|
||||
//
|
||||
// Note that specified fields in path will replace already set fields in the
|
||||
// tomlConfig. Only the [[registry]] tables are merged by prefix.
|
||||
func (c *tomlConfig) loadConfig(path string, forceV2 bool) error {
|
||||
// loadConfigFile loads and unmarshals a single config file.
|
||||
// Use forceV2 if the config must in the v2 format.
|
||||
func loadConfigFile(path string, forceV2 bool) (*parsedConfig, error) {
|
||||
logrus.Debugf("Loading registries configuration %q", path)
|
||||
|
||||
// Save the registries before decoding the file where they could be lost.
|
||||
// We merge them later again.
|
||||
registryMap := make(map[string]Registry)
|
||||
for i := range c.Registries {
|
||||
registryMap[c.Registries[i].Prefix] = c.Registries[i]
|
||||
// tomlConfig allows us to unmarshal either V1 or V2 simultaneously.
|
||||
type tomlConfig struct {
|
||||
V2RegistriesConf
|
||||
V1RegistriesConf // for backwards compatibility with sysregistries v1
|
||||
}
|
||||
|
||||
// Load the tomlConfig. Note that `DecodeFile` will overwrite set fields.
|
||||
c.Registries = nil // important to clear the memory to prevent us from overlapping fields
|
||||
_, err := toml.DecodeFile(path, c)
|
||||
var combinedTOML tomlConfig
|
||||
_, err := toml.DecodeFile(path, &combinedTOML)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.V1RegistriesConf.Nonempty() {
|
||||
if combinedTOML.V1RegistriesConf.Nonempty() {
|
||||
// Enforce the v2 format if requested.
|
||||
if forceV2 {
|
||||
return &InvalidRegistries{s: "registry must be in v2 format but is in v1"}
|
||||
return nil, &InvalidRegistries{s: "registry must be in v2 format but is in v1"}
|
||||
}
|
||||
|
||||
// Convert a v1 config into a v2 config.
|
||||
if c.V2RegistriesConf.Nonempty() {
|
||||
return &InvalidRegistries{s: "mixing sysregistry v1/v2 is not supported"}
|
||||
if combinedTOML.V2RegistriesConf.Nonempty() {
|
||||
return nil, &InvalidRegistries{s: "mixing sysregistry v1/v2 is not supported"}
|
||||
}
|
||||
v2, err := c.V1RegistriesConf.ConvertToV2()
|
||||
converted, err := combinedTOML.V1RegistriesConf.ConvertToV2()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
c.V1RegistriesConf = V1RegistriesConf{}
|
||||
c.V2RegistriesConf = *v2
|
||||
combinedTOML.V1RegistriesConf = V1RegistriesConf{}
|
||||
combinedTOML.V2RegistriesConf = *converted
|
||||
}
|
||||
|
||||
res := parsedConfig{partialV2: combinedTOML.V2RegistriesConf}
|
||||
|
||||
// Post process registries, set the correct prefixes, sanity checks, etc.
|
||||
if err := c.postProcess(); err != nil {
|
||||
return err
|
||||
if err := res.partialV2.postProcessRegistries(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res.unqualifiedSearchRegistriesOrigin = path
|
||||
|
||||
if len(res.partialV2.ShortNameMode) > 0 {
|
||||
mode, err := parseShortNameMode(res.partialV2.ShortNameMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.shortNameMode = mode
|
||||
} else {
|
||||
res.shortNameMode = types.ShortNameModeInvalid
|
||||
}
|
||||
|
||||
// Parse and validate short-name aliases.
|
||||
cache, err := newShortNameAliasCache(path, &res.partialV2.shortNameAliasConf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error validating short-name aliases")
|
||||
}
|
||||
res.aliasCache = cache
|
||||
// Clear conf.partialV2.shortNameAliasConf to make it available for garbage collection and
|
||||
// reduce memory consumption. We're consulting aliasCache for lookups.
|
||||
res.partialV2.shortNameAliasConf = shortNameAliasConf{}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// updateWithConfigurationFrom updates c with configuration from updates.
|
||||
//
|
||||
// Fields present in updates will typically replace already set fields in c.
|
||||
// The [[registry]] and alias tables are merged.
|
||||
func (c *parsedConfig) updateWithConfigurationFrom(updates *parsedConfig) {
|
||||
// == Merge Registries:
|
||||
registryMap := make(map[string]Registry)
|
||||
for i := range c.partialV2.Registries {
|
||||
registryMap[c.partialV2.Registries[i].Prefix] = c.partialV2.Registries[i]
|
||||
}
|
||||
// Merge the freshly loaded registries.
|
||||
for i := range c.Registries {
|
||||
registryMap[c.Registries[i].Prefix] = c.Registries[i]
|
||||
for i := range updates.partialV2.Registries {
|
||||
registryMap[updates.partialV2.Registries[i].Prefix] = updates.partialV2.Registries[i]
|
||||
}
|
||||
|
||||
// Go maps have a non-deterministic order when iterating the keys, so
|
||||
@ -686,10 +805,27 @@ func (c *tomlConfig) loadConfig(path string, forceV2 bool) error {
|
||||
}
|
||||
sort.Strings(prefixes)
|
||||
|
||||
c.Registries = []Registry{}
|
||||
c.partialV2.Registries = []Registry{}
|
||||
for _, prefix := range prefixes {
|
||||
c.Registries = append(c.Registries, registryMap[prefix])
|
||||
c.partialV2.Registries = append(c.partialV2.Registries, registryMap[prefix])
|
||||
}
|
||||
|
||||
return nil
|
||||
// == Merge UnqualifiedSearchRegistries:
|
||||
// This depends on an subtlety of the behavior of the TOML decoder, where a missing array field
|
||||
// is not modified while unmarshaling (in our case remains to nil), while an [] is unmarshaled
|
||||
// as a non-nil []string{}.
|
||||
if updates.partialV2.UnqualifiedSearchRegistries != nil {
|
||||
c.partialV2.UnqualifiedSearchRegistries = updates.partialV2.UnqualifiedSearchRegistries
|
||||
c.unqualifiedSearchRegistriesOrigin = updates.unqualifiedSearchRegistriesOrigin
|
||||
}
|
||||
|
||||
// == Merge shortNameMode:
|
||||
// We don’t maintain c.partialV2.ShortNameMode.
|
||||
if updates.shortNameMode != types.ShortNameModeInvalid {
|
||||
c.shortNameMode = updates.shortNameMode
|
||||
}
|
||||
|
||||
// == Merge aliasCache:
|
||||
// We don’t maintain (in fact we actively clear) c.partialV2.shortNameAliasConf.
|
||||
c.aliasCache.updateWithConfigurationFrom(updates.aliasCache)
|
||||
}
|
||||
|
34
vendor/github.com/containers/image/v5/types/types.go
generated
vendored
34
vendor/github.com/containers/image/v5/types/types.go
generated
vendored
@ -486,6 +486,36 @@ func NewOptionalBool(b bool) OptionalBool {
|
||||
return o
|
||||
}
|
||||
|
||||
// ShortNameMode defines the mode of short-name resolution.
|
||||
//
|
||||
// The use of unqualified-search registries entails an ambiguity as it's
|
||||
// unclear from which registry a given image, referenced by a short name, may
|
||||
// be pulled from.
|
||||
//
|
||||
// The ShortNameMode type defines how short names should resolve.
|
||||
type ShortNameMode int
|
||||
|
||||
const (
|
||||
ShortNameModeInvalid ShortNameMode = iota
|
||||
// Use all configured unqualified-search registries without prompting
|
||||
// the user.
|
||||
ShortNameModeDisabled
|
||||
// If stdout and stdin are a TTY, prompt the user to select a configured
|
||||
// unqualified-search registry. Otherwise, use all configured
|
||||
// unqualified-search registries.
|
||||
//
|
||||
// Note that if only one unqualified-search registry is set, it will be
|
||||
// used without prompting.
|
||||
ShortNameModePermissive
|
||||
// Always prompt the user to select a configured unqualified-search
|
||||
// registry. Throw an error if stdout or stdin is not a TTY as
|
||||
// prompting isn't possible.
|
||||
//
|
||||
// Note that if only one unqualified-search registry is set, it will be
|
||||
// used without prompting.
|
||||
ShortNameModeEnforcing
|
||||
)
|
||||
|
||||
// SystemContext allows parameterizing access to implicitly-accessed resources,
|
||||
// like configuration files in /etc and users' login state in their home directory.
|
||||
// Various components can share the same field only if their semantics is exactly
|
||||
@ -509,6 +539,10 @@ type SystemContext struct {
|
||||
SystemRegistriesConfPath string
|
||||
// Path to the system-wide registries configuration directory
|
||||
SystemRegistriesConfDirPath string
|
||||
// Path to the user-specific short-names configuration file
|
||||
UserShortNameAliasConfPath string
|
||||
// If set, short-name resolution in pkg/shortnames must follow the specified mode
|
||||
ShortNameMode *ShortNameMode
|
||||
// If not "", overrides the default path for the authentication file, but only new format files
|
||||
AuthFilePath string
|
||||
// if not "", overrides the default path for the authentication file, but with the legacy format;
|
||||
|
2
vendor/github.com/containers/image/v5/version/version.go
generated
vendored
2
vendor/github.com/containers/image/v5/version/version.go
generated
vendored
@ -6,7 +6,7 @@ const (
|
||||
// VersionMajor is for an API incompatible changes
|
||||
VersionMajor = 5
|
||||
// VersionMinor is for functionality in a backwards-compatible manner
|
||||
VersionMinor = 7
|
||||
VersionMinor = 8
|
||||
// VersionPatch is for backwards-compatible bug fixes
|
||||
VersionPatch = 0
|
||||
|
||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -39,7 +39,7 @@ github.com/containers/common/pkg/auth
|
||||
github.com/containers/common/pkg/capabilities
|
||||
github.com/containers/common/pkg/completion
|
||||
github.com/containers/common/pkg/retry
|
||||
# github.com/containers/image/v5 v5.7.0
|
||||
# github.com/containers/image/v5 v5.8.0
|
||||
github.com/containers/image/v5/copy
|
||||
github.com/containers/image/v5/directory
|
||||
github.com/containers/image/v5/directory/explicitfilepath
|
||||
|
Loading…
Reference in New Issue
Block a user