mirror of
https://github.com/containers/skopeo.git
synced 2025-06-27 07:07:31 +00:00
Merge pull request #666 from mtrmac/registries.conf-mirrors
Rebase containers/image to v2.0.0
This commit is contained in:
commit
d2d1796eb5
@ -2,7 +2,7 @@
|
||||
github.com/urfave/cli v1.20.0
|
||||
github.com/kr/pretty v0.1.0
|
||||
github.com/kr/text v0.1.0
|
||||
github.com/containers/image 2c0349c99af7d90694b3faa0e9bde404d407b145
|
||||
github.com/containers/image v2.0.0
|
||||
github.com/containers/buildah 810efa340ab43753034e2ed08ec290e4abab7e72
|
||||
github.com/vbauerster/mpb v3.3.4
|
||||
github.com/mattn/go-isatty v0.0.4
|
||||
|
61
vendor/github.com/containers/image/docker/docker_image_src.go
generated
vendored
61
vendor/github.com/containers/image/docker/docker_image_src.go
generated
vendored
@ -29,44 +29,16 @@ type dockerImageSource struct {
|
||||
cachedManifestMIMEType string // Only valid if cachedManifest != nil
|
||||
}
|
||||
|
||||
// newImageSource creates a new `ImageSource` for the specified image reference
|
||||
// `ref`.
|
||||
//
|
||||
// The following steps will be done during the instance creation:
|
||||
//
|
||||
// - Lookup the registry within the configured location in
|
||||
// `sys.SystemRegistriesConfPath`. If there is no configured registry available,
|
||||
// we fallback to the provided docker reference `ref`.
|
||||
//
|
||||
// - References which contain a configured prefix will be automatically rewritten
|
||||
// to the correct target reference. For example, if the configured
|
||||
// `prefix = "example.com/foo"`, `location = "example.com"` and the image will be
|
||||
// pulled from the ref `example.com/foo/image`, then the resulting pull will
|
||||
// effectively point to `example.com/image`.
|
||||
//
|
||||
// - If the rewritten reference succeeds, it will be used as the `dockerRef`
|
||||
// in the client. If the rewrite fails, the function immediately returns an error.
|
||||
//
|
||||
// - Each mirror will be used (in the configured order) to test the
|
||||
// availability of the image manifest on the remote location. For example,
|
||||
// if the manifest is not reachable due to connectivity issues, then the next
|
||||
// mirror will be tested instead. If no mirror is configured or contains the
|
||||
// target manifest, then the initial `ref` will be tested as fallback. The
|
||||
// creation of the new `dockerImageSource` only succeeds if a remote
|
||||
// location with the available manifest was found.
|
||||
//
|
||||
// A cleanup call to `.Close()` is needed if the caller is done using the returned
|
||||
// `ImageSource`.
|
||||
// newImageSource creates a new ImageSource for the specified image reference.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerReference) (*dockerImageSource, error) {
|
||||
registry, err := sysregistriesv2.FindRegistry(sys, ref.ref.Name())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error loading registries configuration")
|
||||
}
|
||||
|
||||
if registry == nil {
|
||||
// No configuration was found for the provided reference, so we create
|
||||
// a fallback registry by hand to make the client creation below work
|
||||
// as intended.
|
||||
// No configuration was found for the provided reference, so use the
|
||||
// equivalent of a default configuration.
|
||||
registry = &sysregistriesv2.Registry{
|
||||
Endpoint: sysregistriesv2.Endpoint{
|
||||
Location: ref.ref.String(),
|
||||
@ -76,18 +48,19 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
|
||||
}
|
||||
|
||||
primaryDomain := reference.Domain(ref.ref)
|
||||
// Found the registry within the sysregistriesv2 configuration. Now we test
|
||||
// all endpoints for the manifest availability. If a working image source
|
||||
// was found, it will be used for all future pull actions.
|
||||
// Check all endpoints for the manifest availability. If we find one that does
|
||||
// contain the image, it will be used for all future pull actions. Always try the
|
||||
// non-mirror original location last; this both transparently handles the case
|
||||
// of no mirrors configured, and ensures we return the error encountered when
|
||||
// acessing the upstream location if all endpoints fail.
|
||||
manifestLoadErr := errors.New("Internal error: newImageSource returned without trying any endpoint")
|
||||
for _, endpoint := range append(registry.Mirrors, registry.Endpoint) {
|
||||
logrus.Debugf("Trying to pull %q from endpoint %q", ref.ref, endpoint.Location)
|
||||
|
||||
newRef, err := endpoint.RewriteReference(ref.ref, registry.Prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dockerRef, err := newReference(newRef)
|
||||
pullSources, err := registry.PullSourcesFromReference(ref.ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, pullSource := range pullSources {
|
||||
logrus.Debugf("Trying to pull %q", pullSource.Reference)
|
||||
dockerRef, err := newReference(pullSource.Reference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -104,7 +77,7 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.tlsClientConfig.InsecureSkipVerify = endpoint.Insecure
|
||||
client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure
|
||||
|
||||
testImageSource := &dockerImageSource{
|
||||
ref: dockerRef,
|
||||
|
2
vendor/github.com/containers/image/docker/reference/README.md
generated
vendored
2
vendor/github.com/containers/image/docker/reference/README.md
generated
vendored
@ -1,2 +1,2 @@
|
||||
This is a copy of github.com/docker/distribution/reference as of commit fb0bebc4b64e3881cc52a2478d749845ed76d2a8,
|
||||
This is a copy of github.com/docker/distribution/reference as of commit 3226863cbcba6dbc2f6c83a37b28126c934af3f8,
|
||||
except that ParseAnyReferenceWithSet has been removed to drop the dependency on github.com/docker/distribution/digestset.
|
29
vendor/github.com/containers/image/docker/reference/normalize.go
generated
vendored
29
vendor/github.com/containers/image/docker/reference/normalize.go
generated
vendored
@ -55,6 +55,35 @@ func ParseNormalizedNamed(s string) (Named, error) {
|
||||
return named, nil
|
||||
}
|
||||
|
||||
// ParseDockerRef normalizes the image reference following the docker convention. This is added
|
||||
// mainly for backward compatibility.
|
||||
// The reference returned can only be either tagged or digested. For reference contains both tag
|
||||
// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
|
||||
// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
|
||||
// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
|
||||
func ParseDockerRef(ref string) (Named, error) {
|
||||
named, err := ParseNormalizedNamed(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := named.(NamedTagged); ok {
|
||||
if canonical, ok := named.(Canonical); ok {
|
||||
// The reference is both tagged and digested, only
|
||||
// return digested.
|
||||
newNamed, err := WithName(canonical.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newCanonical, err := WithDigest(newNamed, canonical.Digest())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newCanonical, nil
|
||||
}
|
||||
}
|
||||
return TagNameOnly(named), nil
|
||||
}
|
||||
|
||||
// splitDockerDomain splits a repository name to domain and remotename string.
|
||||
// If no valid domain is found, the default domain is used. Repository name
|
||||
// needs to be already validated before.
|
||||
|
4
vendor/github.com/containers/image/docker/reference/reference.go
generated
vendored
4
vendor/github.com/containers/image/docker/reference/reference.go
generated
vendored
@ -15,7 +15,7 @@
|
||||
// tag := /[\w][\w.-]{0,127}/
|
||||
//
|
||||
// digest := digest-algorithm ":" digest-hex
|
||||
// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]
|
||||
// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]*
|
||||
// digest-algorithm-separator := /[+.-_]/
|
||||
// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/
|
||||
// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
|
||||
@ -205,7 +205,7 @@ func Parse(s string) (Reference, error) {
|
||||
var repo repository
|
||||
|
||||
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
|
||||
if nameMatch != nil && len(nameMatch) == 3 {
|
||||
if len(nameMatch) == 3 {
|
||||
repo.domain = nameMatch[1]
|
||||
repo.path = nameMatch[2]
|
||||
} else {
|
||||
|
10
vendor/github.com/containers/image/docker/reference/regexp.go
generated
vendored
10
vendor/github.com/containers/image/docker/reference/regexp.go
generated
vendored
@ -20,15 +20,15 @@ var (
|
||||
optional(repeated(separatorRegexp, alphaNumericRegexp)))
|
||||
|
||||
// domainComponentRegexp restricts the registry domain component of a
|
||||
// repository name to start with a component as defined by domainRegexp
|
||||
// repository name to start with a component as defined by DomainRegexp
|
||||
// and followed by an optional port.
|
||||
domainComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
|
||||
|
||||
// domainRegexp defines the structure of potential domain components
|
||||
// DomainRegexp defines the structure of potential domain components
|
||||
// that may be part of image names. This is purposely a subset of what is
|
||||
// allowed by DNS to ensure backwards compatibility with Docker image
|
||||
// names.
|
||||
domainRegexp = expression(
|
||||
DomainRegexp = expression(
|
||||
domainComponentRegexp,
|
||||
optional(repeated(literal(`.`), domainComponentRegexp)),
|
||||
optional(literal(`:`), match(`[0-9]+`)))
|
||||
@ -51,14 +51,14 @@ var (
|
||||
// regexp has capturing groups for the domain and name part omitting
|
||||
// the separating forward slash from either.
|
||||
NameRegexp = expression(
|
||||
optional(domainRegexp, literal(`/`)),
|
||||
optional(DomainRegexp, literal(`/`)),
|
||||
nameComponentRegexp,
|
||||
optional(repeated(literal(`/`), nameComponentRegexp)))
|
||||
|
||||
// anchoredNameRegexp is used to parse a name value, capturing the
|
||||
// domain and trailing components.
|
||||
anchoredNameRegexp = anchored(
|
||||
optional(capture(domainRegexp), literal(`/`)),
|
||||
optional(capture(DomainRegexp), literal(`/`)),
|
||||
capture(nameComponentRegexp,
|
||||
optional(repeated(literal(`/`), nameComponentRegexp))))
|
||||
|
||||
|
148
vendor/github.com/containers/image/docs/containers-registries.conf.5.md
generated
vendored
148
vendor/github.com/containers/image/docs/containers-registries.conf.5.md
generated
vendored
@ -18,57 +18,127 @@ VERSION 2 is the latest format of the `registries.conf` and is currently in
|
||||
beta. This means in general VERSION 1 should be used in production environments
|
||||
for now.
|
||||
|
||||
Every registry can have its own mirrors configured. The mirrors will be tested
|
||||
in order for the availability of the remote manifest. This happens currently
|
||||
only during an image pull. If the manifest is not reachable due to connectivity
|
||||
issues or the unavailability of the remote manifest, then the next mirror will
|
||||
be tested instead. If no mirror is configured or contains the manifest to be
|
||||
pulled, then the initially provided reference will be used as fallback. It is
|
||||
possible to set the `insecure` option per mirror, too.
|
||||
### GLOBAL SETTINGS
|
||||
|
||||
Furthermore it is possible to specify a `prefix` for a registry. The `prefix`
|
||||
is used to find the relevant target registry from where the image has to be
|
||||
pulled. During the test for the availability of the image, the prefixed
|
||||
location will be rewritten to the correct remote location. This applies to
|
||||
mirrors as well as the fallback `location`. If no prefix is specified, it
|
||||
defaults to the specified `location`. For example, if
|
||||
`prefix = "example.com/foo"`, `location = "example.com"` and the image will be
|
||||
pulled from `example.com/foo/image`, then the resulting pull will be effectively
|
||||
point to `example.com/image`.
|
||||
`unqualified-search-registries`
|
||||
: An array of _host_[`:`_port_] registries to try when pulling an unqualified image, in order.
|
||||
|
||||
By default container runtimes use TLS when retrieving images from a registry.
|
||||
If the registry is not setup with TLS, then the container runtime will fail to
|
||||
pull images from the registry. If you set `insecure = true` for a registry or a
|
||||
mirror you overwrite the `insecure` flag for that specific entry. This means
|
||||
that the container runtime will attempt use unencrypted HTTP to pull the image.
|
||||
It also allows you to pull from a registry with self-signed certificates.
|
||||
### NAMESPACED `[[registry]]` SETTINGS
|
||||
|
||||
If you set the `unqualified-search = true` for the registry, then it is possible
|
||||
to omit the registry hostname when pulling images. This feature does not work
|
||||
together with a specified `prefix`.
|
||||
The bulk of the configuration is represented as an array of `[[registry]]`
|
||||
TOML tables; the settings may therefore differ among different registries
|
||||
as well as among different namespaces/repositories within a registry.
|
||||
|
||||
If `blocked = true` then it is not allowed to pull images from that registry.
|
||||
#### Choosing a `[[registry]]` TOML table
|
||||
|
||||
Given an image name, a single `[[registry]]` TOML table is chosen based on its `prefix` field.
|
||||
|
||||
`prefix`
|
||||
: A prefix of the user-specified image name, i.e. using one of the following formats:
|
||||
- _host_[`:`_port_]
|
||||
- _host_[`:`_port_]`/`_namespace_[`/`_namespace_…]
|
||||
- _host_[`:`_port_]`/`_namespace_[`/`_namespace_…]`/`_repo_
|
||||
- _host_[`:`_port_]`/`_namespace_[`/`_namespace_…]`/`_repo_(`:`_tag|`@`_digest_)
|
||||
|
||||
The user-specified image name must start with the specified `prefix` (and continue
|
||||
with the appropriate separator) for a particular `[[registry]]` TOML table to be
|
||||
considered; (only) the TOML table with the longest match is used.
|
||||
|
||||
As a special case, the `prefix` field can be missing; if so, it defaults to the value
|
||||
of the `location` field (described below).
|
||||
|
||||
#### Per-namespace settings
|
||||
|
||||
`insecure`
|
||||
: `true` or `false`.
|
||||
By default, container runtimes require TLS when retrieving images from a registry.
|
||||
If `insecure` is set to `true`, unencrypted HTTP as well as TLS connections with untrusted
|
||||
certificates are allowed.
|
||||
|
||||
`blocked`
|
||||
: `true` or `false`.
|
||||
If `true`, pulling images with matching names is forbidden.
|
||||
|
||||
#### Remapping and mirroring registries
|
||||
|
||||
The user-specified image reference is, primarily, a "logical" image name, always used for naming
|
||||
the image. By default, the image reference also directly specifies the registry and repository
|
||||
to use, but the following options can be used to redirect the underlying accesses
|
||||
to different registry servers or locations (e.g. to support configurations with no access to the
|
||||
internet without having to change `Dockerfile`s, or to add redundancy).
|
||||
|
||||
`location`
|
||||
: Accepts the same format as the `prefix` field, and specifies the physical location
|
||||
of the `prefix`-rooted namespace.
|
||||
|
||||
By default, this equal to `prefix` (in which case `prefix` can be omitted and the
|
||||
`[[registry]]` TOML table can only specify `location`).
|
||||
|
||||
Example: Given
|
||||
```
|
||||
prefix = "example.com/foo"
|
||||
location = "internal-registry-for-example.net/bar"
|
||||
```
|
||||
requests for the image `example.com/foo/myimage:latest` will actually work with the
|
||||
`internal-registry-for-example.net/bar/myimage:latest` image.
|
||||
|
||||
`mirror`
|
||||
: An array of TOML tables specifiying (possibly-partial) mirrors for the
|
||||
`prefix`-rooted namespace.
|
||||
|
||||
The mirrors are attempted in the specified order; the first one that can be
|
||||
contacted and contains the image will be used (and if none of the mirrors contains the image,
|
||||
the primary location specified by the `registry.location` field, or using the unmodified
|
||||
user-specified reference, is tried last).
|
||||
|
||||
Each TOML table in the `mirror` array can contain the following fields, with the same semantics
|
||||
as if specified in the `[[registry]]` TOML table directly:
|
||||
- `location`
|
||||
- `insecure`
|
||||
|
||||
`mirror-by-digest-only`
|
||||
: `true` or `false`.
|
||||
If `true`, mirrors will only be used during pulling if the image reference includes a digest.
|
||||
Referencing an image by digest ensures that the same is always used
|
||||
(whereas referencing an image by a tag may cause different registries to return
|
||||
different images if the tag mapping is out of sync).
|
||||
|
||||
Note that if this is `true`, images referenced by a tag will only use the primary
|
||||
registry, failing if that registry is not accessible.
|
||||
|
||||
*Note*: Redirection and mirrors are currently processed only when reading images, not when pushing
|
||||
to a registry; that may change in the future.
|
||||
|
||||
### EXAMPLE
|
||||
|
||||
```
|
||||
unqualified-search-registries = ["example.com"]
|
||||
|
||||
[[registry]]
|
||||
location = "example.com"
|
||||
insecure = false
|
||||
prefix = "example.com/foo"
|
||||
unqualified-search = false
|
||||
insecure = false
|
||||
blocked = false
|
||||
mirror = [
|
||||
{ location = "example-mirror-0.local", insecure = false },
|
||||
{ location = "example-mirror-1.local", insecure = true }
|
||||
]
|
||||
location = "internal-registry-for-example.com/bar"
|
||||
|
||||
[[registry.mirror]]
|
||||
location = "example-mirror-0.local/mirror-for-foo"
|
||||
|
||||
[[registry.mirror]]
|
||||
location = "example-mirror-1.local/mirrors/foo"
|
||||
insecure = true
|
||||
```
|
||||
Given the above, a pull of `example.com/foo/image:latest` will try:
|
||||
1. `example-mirror-0.local/mirror-for-foo/image:latest`
|
||||
2. `example-mirror-1.local/mirrors/foo/image:latest`
|
||||
3. `internal-registry-for-example.net/bar/myimage:latest`
|
||||
|
||||
in order, and use the first one that exists.
|
||||
|
||||
## VERSION 1
|
||||
VERSION 1 can be used as alternative to the VERSION 2, but it is not capable in
|
||||
using registry mirrors or a prefix.
|
||||
VERSION 1 can be used as alternative to the VERSION 2, but it does not support
|
||||
using registry mirrors, longest-prefix matches, or location rewriting.
|
||||
|
||||
The TOML_format is used to build a simple list for registries under three
|
||||
The TOML format is used to build a simple list of registries under three
|
||||
categories: `registries.search`, `registries.insecure`, and `registries.block`.
|
||||
You can list multiple registries using a comma separated list.
|
||||
|
||||
@ -76,11 +146,11 @@ Search registries are used when the caller of a container runtime does not fully
|
||||
container image that they want to execute. These registries are prepended onto the front
|
||||
of the specified container image until the named image is found at a registry.
|
||||
|
||||
Note insecure registries can be used for any registry, not just the registries listed
|
||||
Note that insecure registries can be used for any registry, not just the registries listed
|
||||
under search.
|
||||
|
||||
The fields `registries.insecure` and `registries.block` work as like as the
|
||||
`insecure` and `blocked` from VERSION 2.
|
||||
The `registries.insecure` and `registries.block` lists have the same meaning as the
|
||||
`insecure` and `blocked` fields in VERSION 2.
|
||||
|
||||
### EXAMPLE
|
||||
The following example configuration defines two searchable registries, one
|
||||
|
224
vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go
generated
vendored
224
vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@ -35,10 +36,10 @@ type Endpoint struct {
|
||||
Insecure bool `toml:"insecure"`
|
||||
}
|
||||
|
||||
// RewriteReference will substitute the provided reference `prefix` to the
|
||||
// rewriteReference will substitute the provided reference `prefix` to the
|
||||
// endpoints `location` from the `ref` and creates a new named reference from it.
|
||||
// The function errors if the newly created reference is not parsable.
|
||||
func (e *Endpoint) RewriteReference(ref reference.Named, prefix string) (reference.Named, error) {
|
||||
func (e *Endpoint) rewriteReference(ref reference.Named, prefix string) (reference.Named, error) {
|
||||
refString := ref.String()
|
||||
if !refMatchesPrefix(refString, prefix) {
|
||||
return nil, fmt.Errorf("invalid prefix '%v' for reference '%v'", prefix, refString)
|
||||
@ -61,8 +62,10 @@ type Registry struct {
|
||||
Mirrors []Endpoint `toml:"mirror"`
|
||||
// If true, pulling from the registry will be blocked.
|
||||
Blocked bool `toml:"blocked"`
|
||||
// If true, the registry can be used when pulling an unqualified image.
|
||||
Search bool `toml:"unqualified-search"`
|
||||
// If true, mirrors will only be used for digest pulls. Pulling images by
|
||||
// tag can potentially yield different images, depending on which endpoint
|
||||
// we pull from. Forcing digest-pulls for mirrors avoids that issue.
|
||||
MirrorByDigestOnly bool `toml:"mirror-by-digest-only"`
|
||||
// Prefix is used for matching images, and to translate one namespace to
|
||||
// another. If `Prefix="example.com/bar"`, `location="example.com/foo/bar"`
|
||||
// and we pull from "example.com/bar/myimage:latest", the image will
|
||||
@ -71,6 +74,41 @@ type Registry struct {
|
||||
Prefix string `toml:"prefix"`
|
||||
}
|
||||
|
||||
// PullSource consists of an Endpoint and a Reference. Note that the reference is
|
||||
// rewritten according to the registries prefix and the Endpoint's location.
|
||||
type PullSource struct {
|
||||
Endpoint Endpoint
|
||||
Reference reference.Named
|
||||
}
|
||||
|
||||
// PullSourcesFromReference returns a slice of PullSource's based on the passed
|
||||
// reference.
|
||||
func (r *Registry) PullSourcesFromReference(ref reference.Named) ([]PullSource, error) {
|
||||
var endpoints []Endpoint
|
||||
|
||||
if r.MirrorByDigestOnly {
|
||||
// Only use mirrors when the reference is a digest one.
|
||||
if _, isDigested := ref.(reference.Canonical); isDigested {
|
||||
endpoints = append(r.Mirrors, r.Endpoint)
|
||||
} else {
|
||||
endpoints = []Endpoint{r.Endpoint}
|
||||
}
|
||||
} else {
|
||||
endpoints = append(r.Mirrors, r.Endpoint)
|
||||
}
|
||||
|
||||
sources := []PullSource{}
|
||||
for _, ep := range endpoints {
|
||||
rewritten, err := ep.rewriteReference(ref, r.Prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sources = append(sources, PullSource{Endpoint: ep, Reference: rewritten})
|
||||
}
|
||||
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
// V1TOMLregistries is for backwards compatibility to sysregistries v1
|
||||
type V1TOMLregistries struct {
|
||||
Registries []string `toml:"registries"`
|
||||
@ -83,11 +121,35 @@ type V1TOMLConfig struct {
|
||||
Block V1TOMLregistries `toml:"block"`
|
||||
}
|
||||
|
||||
// V1RegistriesConf is the sysregistries v1 configuration format.
|
||||
type V1RegistriesConf struct {
|
||||
V1TOMLConfig `toml:"registries"`
|
||||
}
|
||||
|
||||
// Nonempty returns true if config contains at least one configuration entry.
|
||||
func (config *V1RegistriesConf) Nonempty() bool {
|
||||
return (len(config.V1TOMLConfig.Search.Registries) != 0 ||
|
||||
len(config.V1TOMLConfig.Insecure.Registries) != 0 ||
|
||||
len(config.V1TOMLConfig.Block.Registries) != 0)
|
||||
}
|
||||
|
||||
// V2RegistriesConf is the sysregistries v2 configuration format.
|
||||
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"`
|
||||
}
|
||||
|
||||
// Nonempty returns true if config contains at least one configuration entry.
|
||||
func (config *V2RegistriesConf) Nonempty() bool {
|
||||
return (len(config.Registries) != 0 ||
|
||||
len(config.UnqualifiedSearchRegistries) != 0)
|
||||
}
|
||||
|
||||
// tomlConfig is the data type used to unmarshal the toml config.
|
||||
type tomlConfig struct {
|
||||
Registries []Registry `toml:"registry"`
|
||||
// backwards compatability to sysregistries v1
|
||||
V1TOMLConfig `toml:"registries"`
|
||||
V2RegistriesConf
|
||||
V1RegistriesConf // for backwards compatibility with sysregistries v1
|
||||
}
|
||||
|
||||
// InvalidRegistries represents an invalid registry configurations. An example
|
||||
@ -120,12 +182,10 @@ func parseLocation(input string) (string, error) {
|
||||
return trimmed, nil
|
||||
}
|
||||
|
||||
// getV1Registries transforms v1 registries in the config into an array of v2
|
||||
// registries of type Registry.
|
||||
func getV1Registries(config *tomlConfig) ([]Registry, error) {
|
||||
// ConvertToV2 returns a v2 config corresponding to a v1 one.
|
||||
func (config *V1RegistriesConf) ConvertToV2() (*V2RegistriesConf, error) {
|
||||
regMap := make(map[string]*Registry)
|
||||
// We must preserve the order of config.V1Registries.Search.Registries at least. The order of the
|
||||
// other registries is not really important, but make it deterministic (the same for the same config file)
|
||||
// The order of the registries is not really important, but make it deterministic (the same for the same config file)
|
||||
// to minimize behavior inconsistency and not contribute to difficult-to-reproduce situations.
|
||||
registryOrder := []string{}
|
||||
|
||||
@ -148,15 +208,6 @@ func getV1Registries(config *tomlConfig) ([]Registry, error) {
|
||||
return reg, nil
|
||||
}
|
||||
|
||||
// Note: config.V1Registries.Search needs to be processed first to ensure registryOrder is populated in the right order
|
||||
// if one of the search registries is also in one of the other lists.
|
||||
for _, search := range config.V1TOMLConfig.Search.Registries {
|
||||
reg, err := getRegistry(search)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reg.Search = true
|
||||
}
|
||||
for _, blocked := range config.V1TOMLConfig.Block.Registries {
|
||||
reg, err := getRegistry(blocked)
|
||||
if err != nil {
|
||||
@ -172,28 +223,31 @@ func getV1Registries(config *tomlConfig) ([]Registry, error) {
|
||||
reg.Insecure = true
|
||||
}
|
||||
|
||||
registries := []Registry{}
|
||||
res := &V2RegistriesConf{
|
||||
UnqualifiedSearchRegistries: config.V1TOMLConfig.Search.Registries,
|
||||
}
|
||||
for _, location := range registryOrder {
|
||||
reg := regMap[location]
|
||||
registries = append(registries, *reg)
|
||||
res.Registries = append(res.Registries, *reg)
|
||||
}
|
||||
return registries, nil
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// postProcessRegistries checks the consistency of all registries (e.g., set
|
||||
// the Prefix to Location if not set) and applies conflict checks. It returns an
|
||||
// array of cleaned registries and error in case of conflicts.
|
||||
func postProcessRegistries(regs []Registry) ([]Registry, error) {
|
||||
var registries []Registry
|
||||
regMap := make(map[string][]Registry)
|
||||
// anchoredDomainRegexp is an internal implementation detail of postProcess, defining the valid values of elements of UnqualifiedSearchRegistries.
|
||||
var anchoredDomainRegexp = regexp.MustCompile("^" + reference.DomainRegexp.String() + "$")
|
||||
|
||||
for _, reg := range regs {
|
||||
var err error
|
||||
// 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 {
|
||||
regMap := make(map[string][]*Registry)
|
||||
|
||||
for i := range config.Registries {
|
||||
reg := &config.Registries[i]
|
||||
// make sure Location and Prefix are valid
|
||||
var err error
|
||||
reg.Location, err = parseLocation(reg.Location)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if reg.Prefix == "" {
|
||||
@ -201,7 +255,7 @@ func postProcessRegistries(regs []Registry) ([]Registry, error) {
|
||||
} else {
|
||||
reg.Prefix, err = parseLocation(reg.Prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,10 +263,9 @@ func postProcessRegistries(regs []Registry) ([]Registry, error) {
|
||||
for _, mir := range reg.Mirrors {
|
||||
mir.Location, err = parseLocation(mir.Location)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
registries = append(registries, reg)
|
||||
regMap[reg.Location] = append(regMap[reg.Location], reg)
|
||||
}
|
||||
|
||||
@ -222,22 +275,32 @@ func postProcessRegistries(regs []Registry) ([]Registry, error) {
|
||||
//
|
||||
// Note: we need to iterate over the registries array to ensure a
|
||||
// deterministic behavior which is not guaranteed by maps.
|
||||
for _, reg := range registries {
|
||||
for _, reg := range config.Registries {
|
||||
others, _ := regMap[reg.Location]
|
||||
for _, other := range others {
|
||||
if reg.Insecure != other.Insecure {
|
||||
msg := fmt.Sprintf("registry '%s' is defined multiple times with conflicting 'insecure' setting", reg.Location)
|
||||
|
||||
return nil, &InvalidRegistries{s: msg}
|
||||
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 nil, &InvalidRegistries{s: msg}
|
||||
return &InvalidRegistries{s: msg}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return registries, nil
|
||||
for i := range config.UnqualifiedSearchRegistries {
|
||||
registry, err := parseLocation(config.UnqualifiedSearchRegistries[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !anchoredDomainRegexp.MatchString(registry) {
|
||||
return &InvalidRegistries{fmt.Sprintf("Invalid unqualified-search-registries entry %#v", registry)}
|
||||
}
|
||||
config.UnqualifiedSearchRegistries[i] = registry
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getConfigPath returns the system-registries config path if specified.
|
||||
@ -260,7 +323,7 @@ var configMutex = sync.Mutex{}
|
||||
// configCache caches already loaded configs with config paths as keys and is
|
||||
// used to avoid redudantly parsing configs. Concurrent accesses to the cache
|
||||
// are synchronized via configMutex.
|
||||
var configCache = make(map[string][]Registry)
|
||||
var configCache = make(map[string]*V2RegistriesConf)
|
||||
|
||||
// InvalidateCache invalidates the registry cache. This function is meant to be
|
||||
// used for long-running processes that need to reload potential changes made to
|
||||
@ -268,20 +331,18 @@ var configCache = make(map[string][]Registry)
|
||||
func InvalidateCache() {
|
||||
configMutex.Lock()
|
||||
defer configMutex.Unlock()
|
||||
configCache = make(map[string][]Registry)
|
||||
configCache = make(map[string]*V2RegistriesConf)
|
||||
}
|
||||
|
||||
// GetRegistries loads and returns the registries specified in the config.
|
||||
// Note the parsed content of registry config files is cached. For reloading,
|
||||
// use `InvalidateCache` and re-call `GetRegistries`.
|
||||
func GetRegistries(ctx *types.SystemContext) ([]Registry, error) {
|
||||
// getConfig returns the config object corresponding to ctx, loading it if it is not yet cached.
|
||||
func getConfig(ctx *types.SystemContext) (*V2RegistriesConf, error) {
|
||||
configPath := getConfigPath(ctx)
|
||||
|
||||
configMutex.Lock()
|
||||
defer configMutex.Unlock()
|
||||
// if the config has already been loaded, return the cached registries
|
||||
if registries, inCache := configCache[configPath]; inCache {
|
||||
return registries, nil
|
||||
if config, inCache := configCache[configPath]; inCache {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// load the config
|
||||
@ -292,51 +353,53 @@ func GetRegistries(ctx *types.SystemContext) ([]Registry, error) {
|
||||
// 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 == "") {
|
||||
return []Registry{}, nil
|
||||
return &V2RegistriesConf{Registries: []Registry{}}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
registries := config.Registries
|
||||
v2Config := &config.V2RegistriesConf
|
||||
|
||||
// backwards compatibility for v1 configs
|
||||
v1Registries, err := getV1Registries(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(v1Registries) > 0 {
|
||||
if len(registries) > 0 {
|
||||
if config.V1RegistriesConf.Nonempty() {
|
||||
if config.V2RegistriesConf.Nonempty() {
|
||||
return nil, &InvalidRegistries{s: "mixing sysregistry v1/v2 is not supported"}
|
||||
}
|
||||
registries = v1Registries
|
||||
v2, err := config.V1RegistriesConf.ConvertToV2()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v2Config = v2
|
||||
}
|
||||
|
||||
registries, err = postProcessRegistries(registries)
|
||||
if err != nil {
|
||||
if err := v2Config.postProcess(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// populate the cache
|
||||
configCache[configPath] = registries
|
||||
|
||||
return registries, err
|
||||
configCache[configPath] = v2Config
|
||||
return v2Config, nil
|
||||
}
|
||||
|
||||
// FindUnqualifiedSearchRegistries returns all registries that are configured
|
||||
// for unqualified image search (i.e., with Registry.Search == true).
|
||||
func FindUnqualifiedSearchRegistries(ctx *types.SystemContext) ([]Registry, error) {
|
||||
registries, err := GetRegistries(ctx)
|
||||
// GetRegistries loads and returns the registries specified in the config.
|
||||
// Note the parsed content of registry config files is cached. For reloading,
|
||||
// use `InvalidateCache` and re-call `GetRegistries`.
|
||||
func GetRegistries(ctx *types.SystemContext) ([]Registry, error) {
|
||||
config, err := getConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config.Registries, nil
|
||||
}
|
||||
|
||||
unqualified := []Registry{}
|
||||
for _, reg := range registries {
|
||||
if reg.Search {
|
||||
unqualified = append(unqualified, reg)
|
||||
}
|
||||
// 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) {
|
||||
config, err := getConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return unqualified, nil
|
||||
return config.UnqualifiedSearchRegistries, nil
|
||||
}
|
||||
|
||||
// refMatchesPrefix returns true iff ref,
|
||||
@ -371,14 +434,14 @@ func refMatchesPrefix(ref, prefix string) bool {
|
||||
// — note that this requires the name to start with an explicit hostname!).
|
||||
// If no Registry prefixes the image, nil is returned.
|
||||
func FindRegistry(ctx *types.SystemContext, ref string) (*Registry, error) {
|
||||
registries, err := GetRegistries(ctx)
|
||||
config, err := getConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reg := Registry{}
|
||||
prefixLen := 0
|
||||
for _, r := range registries {
|
||||
for _, r := range config.Registries {
|
||||
if refMatchesPrefix(ref, r.Prefix) {
|
||||
length := len(r.Prefix)
|
||||
if length > prefixLen {
|
||||
@ -393,21 +456,12 @@ func FindRegistry(ctx *types.SystemContext, ref string) (*Registry, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Reads the global registry file from the filesystem. Returns a byte array.
|
||||
func readRegistryConf(configPath string) ([]byte, error) {
|
||||
configBytes, err := ioutil.ReadFile(configPath)
|
||||
return configBytes, err
|
||||
}
|
||||
|
||||
// Used in unittests to parse custom configs without a types.SystemContext.
|
||||
var readConf = readRegistryConf
|
||||
|
||||
// Loads the registry configuration file from the filesystem and then unmarshals
|
||||
// it. Returns the unmarshalled object.
|
||||
func loadRegistryConf(configPath string) (*tomlConfig, error) {
|
||||
config := &tomlConfig{}
|
||||
|
||||
configBytes, err := readConf(configPath)
|
||||
configBytes, err := ioutil.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
73
vendor/github.com/containers/image/registries.conf
generated
vendored
73
vendor/github.com/containers/image/registries.conf
generated
vendored
@ -29,37 +29,54 @@ registries = []
|
||||
# The second version of the configuration format allows to specify registry
|
||||
# mirrors:
|
||||
#
|
||||
# # An array of host[:port] registries to try when pulling an unqualified image, in order.
|
||||
# unqualified-search-registries = ["example.com"]
|
||||
#
|
||||
# [[registry]]
|
||||
# # The main location of the registry
|
||||
# location = "example.com"
|
||||
#
|
||||
# # If true, certs verification will be skipped and HTTP (non-TLS) connections
|
||||
# # will be allowed.
|
||||
# insecure = false
|
||||
#
|
||||
# # Prefix is used for matching images, and to translate one namespace to
|
||||
# # another. If `prefix = "example.com/foo"`, `location = "example.com"` and
|
||||
# # we pull from "example.com/foo/myimage:latest", the image will effectively be
|
||||
# # pulled from "example.com/myimage:latest". If no Prefix is specified,
|
||||
# # it defaults to the specified `location`. When a prefix is used, then a pull
|
||||
# # without specifying the prefix is not possible any more.
|
||||
# # The "prefix" field is used to choose the relevant [[registry]] TOML table;
|
||||
# # (only) the TOML table with the longest match for the input image name
|
||||
# # (taking into account namespace/repo/tag/digest separators) is used.
|
||||
# #
|
||||
# # If the prefix field is missing, it defaults to be the same as the "location" field.
|
||||
# prefix = "example.com/foo"
|
||||
#
|
||||
# # If true, the registry can be used when pulling an unqualified image. If a
|
||||
# # prefix is specified, unqualified pull is not possible any more.
|
||||
# unqualified-search = false
|
||||
# # If true, unencrypted HTTP as well as TLS connections with untrusted
|
||||
# # certificates are allowed.
|
||||
# insecure = false
|
||||
#
|
||||
# # If true, pulling from the registry will be blocked.
|
||||
# # If true, pulling images with matching names is forbidden.
|
||||
# blocked = false
|
||||
#
|
||||
# # All available mirrors of the registry. The mirrors will be evaluated in
|
||||
# # order during an image pull. Furthermore it is possible to specify the
|
||||
# # `insecure` flag per registry mirror, too.
|
||||
# mirror = [
|
||||
# { location = "example-mirror-0.local", insecure = false },
|
||||
# { location = "example-mirror-1.local", insecure = true },
|
||||
# # It is also possible to specify an additional path within the `location`.
|
||||
# # A pull to `example.com/foo/image:latest` will then result in
|
||||
# # `example-mirror-2.local/path/image:latest`.
|
||||
# { location = "example-mirror-2.local/path" },
|
||||
# ]
|
||||
# # The physical location of the "prefix"-rooted namespace.
|
||||
# #
|
||||
# # By default, this equal to "prefix" (in which case "prefix" can be omitted
|
||||
# # and the [[registry]] TOML table can only specify "location").
|
||||
# #
|
||||
# # Example: Given
|
||||
# # prefix = "example.com/foo"
|
||||
# # location = "internal-registry-for-example.net/bar"
|
||||
# # requests for the image example.com/foo/myimage:latest will actually work with the
|
||||
# # internal-registry-for-example.net/bar/myimage:latest image.
|
||||
# location = internal-registry-for-example.com/bar"
|
||||
#
|
||||
# # (Possibly-partial) mirrors for the "prefix"-rooted namespace.
|
||||
# #
|
||||
# # The mirrors are attempted in the specified order; the first one that can be
|
||||
# # contacted and contains the image will be used (and if none of the mirrors contains the image,
|
||||
# # the primary location specified by the "registry.location" field, or using the unmodified
|
||||
# # user-specified reference, is tried last).
|
||||
# #
|
||||
# # Each TOML table in the "mirror" array can contain the following fields, with the same semantics
|
||||
# # as if specified in the [[registry]] TOML table directly:
|
||||
# # - location
|
||||
# # - insecure
|
||||
# [[registry.mirror]]
|
||||
# location = "example-mirror-0.local/mirror-for-foo"
|
||||
# [[registry.mirror]]
|
||||
# location = "example-mirror-1.local/mirrors/foo"
|
||||
# insecure = true
|
||||
# # Given the above, a pull of example.com/foo/image:latest will try:
|
||||
# # 1. example-mirror-0.local/mirror-for-foo/image:latest
|
||||
# # 2. example-mirror-1.local/mirrors/foo/image:latest
|
||||
# # 3. internal-registry-for-example.net/bar/myimage:latest
|
||||
# # in order, and use the first one that exists.
|
||||
|
6
vendor/github.com/containers/image/version/version.go
generated
vendored
6
vendor/github.com/containers/image/version/version.go
generated
vendored
@ -4,14 +4,14 @@ import "fmt"
|
||||
|
||||
const (
|
||||
// VersionMajor is for an API incompatible changes
|
||||
VersionMajor = 1
|
||||
VersionMajor = 2
|
||||
// VersionMinor is for functionality in a backwards-compatible manner
|
||||
VersionMinor = 7
|
||||
VersionMinor = 0
|
||||
// VersionPatch is for backwards-compatible bug fixes
|
||||
VersionPatch = 0
|
||||
|
||||
// VersionDev indicates development branch. Releases will be empty string.
|
||||
VersionDev = "-dev"
|
||||
VersionDev = ""
|
||||
)
|
||||
|
||||
// Version is the specification version that the package types support.
|
||||
|
Loading…
Reference in New Issue
Block a user