mirror of https://github.com/containers/image.git
registries.conf.d: add stances for the registries.conf
When loading the registries.conf, allow for loading additional files from `/etc/containers/registries.conf.d`. The files are loaded in alpha-numerical order and specified fields will overwrite the previous config. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
parent
143904cdaa
commit
eee0de5d00
|
|
@ -0,0 +1,33 @@
|
||||||
|
% CONTAINERS-REGISTRIES.CONF.D(5)
|
||||||
|
% Valentin Rothberg
|
||||||
|
% Mar 2020
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
containers-registries.conf.d - directory for drop-in registries.conf files
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
CONTAINERS-REGISTRIES.CONF.D is a systemd-wide directory for drop-in
|
||||||
|
configuration files in the `containers-registries.conf(5)` format.
|
||||||
|
|
||||||
|
By default, the directory is located at `/etc/containers/registries.conf.d`.
|
||||||
|
|
||||||
|
# CONFIGURATION PRECEDENCE
|
||||||
|
|
||||||
|
Once the main configuration at `/etc/containers/registries.conf` is loaded, the
|
||||||
|
files in `/etc/containers/registries.conf.d` are loaded in alpha-numerical order.
|
||||||
|
Specified fields in a config will overwrite any previous setting.
|
||||||
|
|
||||||
|
For instance, setting the `unqualified-search-registries` in
|
||||||
|
`/etc/containers/registries.conf.d/myregistries.conf` will overwrite previous
|
||||||
|
settings in `/etc/containers/registries.conf`.
|
||||||
|
|
||||||
|
Note that all files must be specified in the same version of the
|
||||||
|
`containers-registries.conf(5)` format. The entire `[[registry]]` table will
|
||||||
|
always be overridden if set.
|
||||||
|
|
||||||
|
# SEE ALSO
|
||||||
|
`containers-registries.conf(5)`
|
||||||
|
|
||||||
|
# HISTORY
|
||||||
|
|
||||||
|
Mar 2020, Originally compiled by Valentin Rothberg <rothberg@redhat.com>
|
||||||
4
go.mod
4
go.mod
|
|
@ -39,10 +39,10 @@ require (
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b // indirect
|
||||||
github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66
|
github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66
|
||||||
go.etcd.io/bbolt v1.3.3 // indirect
|
go.etcd.io/bbolt v1.3.3 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
|
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6
|
||||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||||
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
k8s.io/client-go v0.0.0-20170217214107-bcde30fb7eae
|
k8s.io/client-go v0.0.0-20170217214107-bcde30fb7eae
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package sysregistriesv2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
@ -26,6 +25,16 @@ var systemRegistriesConfPath = builtinRegistriesConfPath
|
||||||
// DO NOT change this, instead see systemRegistriesConfPath above.
|
// DO NOT change this, instead see systemRegistriesConfPath above.
|
||||||
const builtinRegistriesConfPath = "/etc/containers/registries.conf"
|
const builtinRegistriesConfPath = "/etc/containers/registries.conf"
|
||||||
|
|
||||||
|
// systemRegistriesConfDirPath is the path to the system-wide registry
|
||||||
|
// configuration directory and is used to add/subtract potential registries for
|
||||||
|
// obtaining images. You can override this at build time with
|
||||||
|
// -ldflags '-X github.com/containers/image/sysregistries.systemRegistriesConfDirecotyPath=$your_path'
|
||||||
|
var systemRegistriesConfDirPath = builtinRegistriesConfDirPath
|
||||||
|
|
||||||
|
// builtinRegistriesConfDirPath is the path to the registry configuration directory.
|
||||||
|
// DO NOT change this, instead see systemRegistriesConfDirectoryPath above.
|
||||||
|
const builtinRegistriesConfDirPath = "/etc/containers/registries.conf.d"
|
||||||
|
|
||||||
// Endpoint describes a remote location of a registry.
|
// Endpoint describes a remote location of a registry.
|
||||||
type Endpoint struct {
|
type Endpoint struct {
|
||||||
// The endpoint's remote location.
|
// The endpoint's remote location.
|
||||||
|
|
@ -360,16 +369,45 @@ func TryUpdatingCache(ctx *types.SystemContext) (*V2RegistriesConf, error) {
|
||||||
defer configMutex.Unlock()
|
defer configMutex.Unlock()
|
||||||
|
|
||||||
// load the config
|
// load the config
|
||||||
config, err := loadRegistryConf(configPath)
|
config := &tomlConfig{}
|
||||||
if err != nil {
|
if err := config.loadConfig(configPath); err != nil {
|
||||||
// Return an empty []Registry if we use the default config,
|
// Return an empty []Registry if we use the default config,
|
||||||
// which implies that the config path of the SystemContext
|
// which implies that the config path of the SystemContext
|
||||||
// isn't set. Note: if ctx.SystemRegistriesConfPath points to
|
// isn't set. Note: if ctx.SystemRegistriesConfPath points to
|
||||||
// the default config, we will still return an error.
|
// the default config, we will still return an error.
|
||||||
if os.IsNotExist(err) && (ctx == nil || ctx.SystemRegistriesConfPath == "") {
|
if os.IsNotExist(err) && (ctx == nil || ctx.SystemRegistriesConfPath == "") {
|
||||||
return &V2RegistriesConf{Registries: []Registry{}}, nil
|
config = &tomlConfig{}
|
||||||
|
config.V2RegistriesConf = V2RegistriesConf{Registries: []Registry{}}
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return nil, err
|
}
|
||||||
|
|
||||||
|
// Load the configs from the conf directory path.
|
||||||
|
confDir := systemRegistriesConfDirPath
|
||||||
|
if ctx != nil && ctx.SystemRegistriesConfDirPath != "" {
|
||||||
|
confDir = ctx.SystemRegistriesConfDirPath
|
||||||
|
}
|
||||||
|
err := filepath.Walk(confDir,
|
||||||
|
// WalkFunc to read additional
|
||||||
|
func(path string, info os.FileInfo, err error) error {
|
||||||
|
switch {
|
||||||
|
case info == nil:
|
||||||
|
// registries.conf.d doesn't exist
|
||||||
|
return nil
|
||||||
|
case info.IsDir():
|
||||||
|
// ignore directories
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
// expect all files to be a config
|
||||||
|
return config.loadConfig(path)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
// Ignore IsNotExist errors: most systems won't have a
|
||||||
|
// registries.conf.d directory.
|
||||||
|
return nil, errors.Wrapf(err, "error reading registries.conf.d")
|
||||||
}
|
}
|
||||||
|
|
||||||
v2Config := &config.V2RegistriesConf
|
v2Config := &config.V2RegistriesConf
|
||||||
|
|
@ -470,16 +508,12 @@ func FindRegistry(ctx *types.SystemContext, ref string) (*Registry, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads the registry configuration file from the filesystem and then unmarshals
|
// tomlConfig loads the unmarshals the configuration at the specified path.
|
||||||
// it. Returns the unmarshalled object.
|
// Note that the tomlConfig's fields will be overridden if they are set in
|
||||||
func loadRegistryConf(configPath string) (*tomlConfig, error) {
|
// specified path. This behavior is necessary for registries.conf.d stances
|
||||||
config := &tomlConfig{}
|
// behavior.
|
||||||
|
func (t *tomlConfig) loadConfig(path string) error {
|
||||||
configBytes, err := ioutil.ReadFile(configPath)
|
logrus.Debugf("Loading registries.conf %q", path)
|
||||||
if err != nil {
|
_, err := toml.DecodeFile(path, t)
|
||||||
return nil, err
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
err = toml.Unmarshal(configBytes, &config)
|
|
||||||
return config, err
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -463,3 +463,18 @@ func TestTryUpdatingCache(t *testing.T) {
|
||||||
assert.Nil(t, registries)
|
assert.Nil(t, registries)
|
||||||
assert.Equal(t, 1, len(configCache))
|
assert.Equal(t, 1, len(configCache))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRegistriesConfDirectory(t *testing.T) {
|
||||||
|
ctx := &types.SystemContext{
|
||||||
|
SystemRegistriesConfPath: "testdata/base-for-registries.d.conf",
|
||||||
|
SystemRegistriesConfDirPath: "testdata/registries.conf.d",
|
||||||
|
}
|
||||||
|
configCache = make(map[string]*V2RegistriesConf)
|
||||||
|
registries, err := TryUpdatingCache(ctx)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, registries)
|
||||||
|
|
||||||
|
assert.Equal(t, registries.UnqualifiedSearchRegistries, []string{"example-overwrite.com"})
|
||||||
|
assert.Equal(t, len(registries.Registries), 1)
|
||||||
|
assert.Equal(t, registries.Registries[0].Location, "2.com")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
unqualified-search-registries = ["example.com"]
|
||||||
|
|
||||||
|
[[registry]]
|
||||||
|
location = "base.com"
|
||||||
|
insecure = true
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
unqualified-search-registries = ["example-overwrite.com"]
|
||||||
|
|
||||||
|
[[registry]]
|
||||||
|
location = "1.com"
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
[[registry]]
|
||||||
|
location = "2.com"
|
||||||
|
|
@ -497,6 +497,8 @@ type SystemContext struct {
|
||||||
RegistriesDirPath string
|
RegistriesDirPath string
|
||||||
// Path to the system-wide registries configuration file
|
// Path to the system-wide registries configuration file
|
||||||
SystemRegistriesConfPath string
|
SystemRegistriesConfPath string
|
||||||
|
// Path to the system-wide registries configuration directory
|
||||||
|
SystemRegistriesConfDirPath string
|
||||||
// If not "", overrides the default path for the authentication file, but only new format files
|
// If not "", overrides the default path for the authentication file, but only new format files
|
||||||
AuthFilePath string
|
AuthFilePath string
|
||||||
// if not "", overrides the default path for the authentication file, but with the legacy format;
|
// if not "", overrides the default path for the authentication file, but with the legacy format;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue