mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
support registry mirror config reload
Signed-off-by: allencloud <allen.sun@daocloud.io>
This commit is contained in:
parent
355f2ae972
commit
5b9348c553
8 changed files with 174 additions and 18 deletions
|
@ -995,14 +995,15 @@ func (daemon *Daemon) initDiscovery(config *Config) error {
|
|||
// Reload reads configuration changes and modifies the
|
||||
// daemon according to those changes.
|
||||
// These are the settings that Reload changes:
|
||||
// - Daemon labels.
|
||||
// - Daemon debug log level.
|
||||
// - Daemon insecure registries.
|
||||
// - Daemon labels
|
||||
// - Daemon debug log level
|
||||
// - Insecure registries
|
||||
// - Registry mirrors
|
||||
// - Daemon max concurrent downloads
|
||||
// - Daemon max concurrent uploads
|
||||
// - Cluster discovery (reconfigure and restart).
|
||||
// - Cluster discovery (reconfigure and restart)
|
||||
// - Daemon live restore
|
||||
// - Daemon shutdown timeout (in seconds).
|
||||
// - Daemon shutdown timeout (in seconds)
|
||||
func (daemon *Daemon) Reload(config *Config) (err error) {
|
||||
|
||||
daemon.configStore.reloadLock.Lock()
|
||||
|
@ -1035,6 +1036,14 @@ func (daemon *Daemon) Reload(config *Config) (err error) {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if config.IsValueSet("registry-mirrors") {
|
||||
daemon.configStore.Mirrors = config.Mirrors
|
||||
if err := daemon.RegistryService.LoadMirrors(config.Mirrors); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if config.IsValueSet("live-restore") {
|
||||
daemon.configStore.LiveRestoreEnabled = config.LiveRestoreEnabled
|
||||
if err := daemon.containerdRemote.UpdateOptions(libcontainerd.WithLiveRestore(config.LiveRestoreEnabled)); err != nil {
|
||||
|
@ -1087,6 +1096,16 @@ func (daemon *Daemon) Reload(config *Config) (err error) {
|
|||
attributes["insecure-registries"] = "[]"
|
||||
}
|
||||
|
||||
if daemon.configStore.Mirrors != nil {
|
||||
mirrors, err := json.Marshal(daemon.configStore.Mirrors)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attributes["registry-mirrors"] = string(mirrors)
|
||||
} else {
|
||||
attributes["registry-mirrors"] = "[]"
|
||||
}
|
||||
|
||||
attributes["cluster-store"] = daemon.configStore.ClusterStore
|
||||
if daemon.configStore.ClusterOpts != nil {
|
||||
opts, err := json.Marshal(daemon.configStore.ClusterOpts)
|
||||
|
|
|
@ -341,6 +341,100 @@ func TestDaemonReloadLabels(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDaemonReloadMirrors(t *testing.T) {
|
||||
daemon := &Daemon{}
|
||||
|
||||
daemon.RegistryService = registry.NewService(registry.ServiceOptions{
|
||||
InsecureRegistries: []string{},
|
||||
Mirrors: []string{
|
||||
"https://mirror.test1.com",
|
||||
"https://mirror.test2.com", // this will be removed when reloading
|
||||
"https://mirror.test3.com", // this will be removed when reloading
|
||||
},
|
||||
})
|
||||
|
||||
daemon.configStore = &Config{}
|
||||
|
||||
type pair struct {
|
||||
valid bool
|
||||
mirrors []string
|
||||
after []string
|
||||
}
|
||||
|
||||
loadMirrors := []pair{
|
||||
{
|
||||
valid: false,
|
||||
mirrors: []string{"10.10.1.11:5000"}, // this mirror is invalid
|
||||
after: []string{},
|
||||
},
|
||||
{
|
||||
valid: false,
|
||||
mirrors: []string{"mirror.test1.com"}, // this mirror is invalid
|
||||
after: []string{},
|
||||
},
|
||||
{
|
||||
valid: false,
|
||||
mirrors: []string{"10.10.1.11:5000", "mirror.test1.com"}, // mirrors are invalid
|
||||
after: []string{},
|
||||
},
|
||||
{
|
||||
valid: true,
|
||||
mirrors: []string{"https://mirror.test1.com", "https://mirror.test4.com"},
|
||||
after: []string{"https://mirror.test1.com/", "https://mirror.test4.com/"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, value := range loadMirrors {
|
||||
valuesSets := make(map[string]interface{})
|
||||
valuesSets["registry-mirrors"] = value.mirrors
|
||||
|
||||
newConfig := &Config{
|
||||
CommonConfig: CommonConfig{
|
||||
ServiceOptions: registry.ServiceOptions{
|
||||
Mirrors: value.mirrors,
|
||||
},
|
||||
valuesSet: valuesSets,
|
||||
},
|
||||
}
|
||||
|
||||
err := daemon.Reload(newConfig)
|
||||
if !value.valid && err == nil {
|
||||
// mirrors should be invalid, should be a non-nil error
|
||||
t.Fatalf("Expected daemon reload error with invalid mirrors: %s, while get nil", value.mirrors)
|
||||
}
|
||||
|
||||
if value.valid {
|
||||
if err != nil {
|
||||
// mirrors should be valid, should be no error
|
||||
t.Fatal(err)
|
||||
}
|
||||
registryService := daemon.RegistryService.ServiceConfig()
|
||||
|
||||
if len(registryService.Mirrors) != len(value.after) {
|
||||
t.Fatalf("Expected %d daemon mirrors %s while get %d with %s",
|
||||
len(value.after),
|
||||
value.after,
|
||||
len(registryService.Mirrors),
|
||||
registryService.Mirrors)
|
||||
}
|
||||
|
||||
dataMap := map[string]struct{}{}
|
||||
|
||||
for _, mirror := range registryService.Mirrors {
|
||||
if _, exist := dataMap[mirror]; !exist {
|
||||
dataMap[mirror] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for _, address := range value.after {
|
||||
if _, exist := dataMap[address]; !exist {
|
||||
t.Fatalf("Expected %s in daemon mirrors, while get none", address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaemonReloadInsecureRegistries(t *testing.T) {
|
||||
daemon := &Daemon{}
|
||||
// initialize daemon with existing insecure registries: "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000"
|
||||
|
|
|
@ -1289,6 +1289,7 @@ The list of currently supported options that can be reconfigured is this:
|
|||
be used to run containers
|
||||
- `authorization-plugin`: specifies the authorization plugins to use.
|
||||
- `insecure-registries`: it replaces the daemon insecure registries with a new set of insecure registries. If some existing insecure registries in daemon's configuration are not in newly reloaded insecure resgitries, these existing ones will be removed from daemon's config.
|
||||
- `registry-mirrors`: it replaces the daemon registry mirrors with a new set of registry mirrors. If some existing registry mirrors in daemon's configuration are not in newly reloaded registry mirrors, these existing ones will be removed from daemon's config.
|
||||
|
||||
Updating and reloading the cluster configurations such as `--cluster-store`,
|
||||
`--cluster-advertise` and `--cluster-store-opts` will take effect only if
|
||||
|
|
|
@ -429,7 +429,7 @@ func (s *DockerDaemonSuite) TestDaemonEvents(c *check.C) {
|
|||
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s (cluster-advertise=, cluster-store=, cluster-store-opts={}, debug=true, default-runtime=runc, insecure-registries=[], labels=[\"bar=foo\"], live-restore=false, max-concurrent-downloads=1, max-concurrent-uploads=5, name=%s, runtimes=runc:{docker-runc []}, shutdown-timeout=10)", daemonID, daemonName))
|
||||
c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s (cluster-advertise=, cluster-store=, cluster-store-opts={}, debug=true, default-runtime=runc, insecure-registries=[], labels=[\"bar=foo\"], live-restore=false, max-concurrent-downloads=1, max-concurrent-uploads=5, name=%s, registry-mirrors=[], runtimes=runc:{docker-runc []}, shutdown-timeout=10)", daemonID, daemonName))
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestDaemonEventsWithFilters(c *check.C) {
|
||||
|
|
|
@ -84,16 +84,46 @@ func newServiceConfig(options ServiceOptions) *serviceConfig {
|
|||
IndexConfigs: make(map[string]*registrytypes.IndexInfo, 0),
|
||||
// Hack: Bypass setting the mirrors to IndexConfigs since they are going away
|
||||
// and Mirrors are only for the official registry anyways.
|
||||
Mirrors: options.Mirrors,
|
||||
},
|
||||
V2Only: options.V2Only,
|
||||
}
|
||||
|
||||
config.LoadMirrors(options.Mirrors)
|
||||
config.LoadInsecureRegistries(options.InsecureRegistries)
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// LoadMirrors loads mirrors to config, after removing duplicates.
|
||||
// Returns an error if mirrors contains an invalid mirror.
|
||||
func (config *serviceConfig) LoadMirrors(mirrors []string) error {
|
||||
mMap := map[string]struct{}{}
|
||||
unique := []string{}
|
||||
|
||||
for _, mirror := range mirrors {
|
||||
m, err := ValidateMirror(mirror)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, exist := mMap[m]; !exist {
|
||||
mMap[m] = struct{}{}
|
||||
unique = append(unique, m)
|
||||
}
|
||||
}
|
||||
|
||||
config.Mirrors = unique
|
||||
|
||||
// Configure public registry since mirrors may have changed.
|
||||
config.IndexConfigs[IndexName] = ®istrytypes.IndexInfo{
|
||||
Name: IndexName,
|
||||
Mirrors: config.Mirrors,
|
||||
Secure: true,
|
||||
Official: true,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadInsecureRegistries loads insecure registries to config
|
||||
func (config *serviceConfig) LoadInsecureRegistries(registries []string) error {
|
||||
// Localhost is by default considered as an insecure registry
|
||||
|
@ -208,18 +238,20 @@ func isSecureIndex(config *serviceConfig, indexName string) bool {
|
|||
func ValidateMirror(val string) (string, error) {
|
||||
uri, err := url.Parse(val)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%s is not a valid URI", val)
|
||||
return "", fmt.Errorf("invalid mirror: %q is not a valid URI", val)
|
||||
}
|
||||
|
||||
if uri.Scheme != "http" && uri.Scheme != "https" {
|
||||
return "", fmt.Errorf("Unsupported scheme %s", uri.Scheme)
|
||||
return "", fmt.Errorf("invalid mirror: unsupported scheme %q in %q", uri.Scheme, uri)
|
||||
}
|
||||
|
||||
if uri.Path != "" || uri.RawQuery != "" || uri.Fragment != "" {
|
||||
return "", fmt.Errorf("Unsupported path/query/fragment at end of the URI")
|
||||
if (uri.Path != "" && uri.Path != "/") || uri.RawQuery != "" || uri.Fragment != "" {
|
||||
return "", fmt.Errorf("invalid mirror: path, query, or fragment at end of the URI %q", uri)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s://%s/", uri.Scheme, uri.Host), nil
|
||||
if uri.User != nil {
|
||||
// strip password from output
|
||||
uri.User = url.UserPassword(uri.User.Username(), "xxxxx")
|
||||
return "", fmt.Errorf("invalid mirror: username/password not allowed in URI %q", uri)
|
||||
}
|
||||
return strings.TrimSuffix(val, "/") + "/", nil
|
||||
}
|
||||
|
||||
// ValidateIndexName validates an index name.
|
||||
|
|
|
@ -7,7 +7,9 @@ import (
|
|||
func TestValidateMirror(t *testing.T) {
|
||||
valid := []string{
|
||||
"http://mirror-1.com",
|
||||
"http://mirror-1.com/",
|
||||
"https://mirror-1.com",
|
||||
"https://mirror-1.com/",
|
||||
"http://localhost",
|
||||
"https://localhost",
|
||||
"http://localhost:5000",
|
||||
|
@ -21,15 +23,14 @@ func TestValidateMirror(t *testing.T) {
|
|||
invalid := []string{
|
||||
"!invalid!://%as%",
|
||||
"ftp://mirror-1.com",
|
||||
"http://mirror-1.com/",
|
||||
"http://mirror-1.com/?q=foo",
|
||||
"http://mirror-1.com/v1/",
|
||||
"http://mirror-1.com/v1/?q=foo",
|
||||
"http://mirror-1.com/v1/?q=foo#frag",
|
||||
"http://mirror-1.com?q=foo",
|
||||
"https://mirror-1.com#frag",
|
||||
"https://mirror-1.com/",
|
||||
"https://mirror-1.com/#frag",
|
||||
"http://foo:bar@mirror-1.com/",
|
||||
"https://mirror-1.com/v1/",
|
||||
"https://mirror-1.com/v1/#",
|
||||
"https://mirror-1.com?q",
|
||||
|
|
|
@ -663,7 +663,7 @@ func TestMirrorEndpointLookup(t *testing.T) {
|
|||
}
|
||||
return false
|
||||
}
|
||||
s := DefaultService{config: makeServiceConfig([]string{"my.mirror"}, nil)}
|
||||
s := DefaultService{config: makeServiceConfig([]string{"https://my.mirror"}, nil)}
|
||||
|
||||
imageName, err := reference.WithName(IndexName + "/test/image")
|
||||
if err != nil {
|
||||
|
|
|
@ -31,6 +31,7 @@ type Service interface {
|
|||
Search(ctx context.Context, term string, limit int, authConfig *types.AuthConfig, userAgent string, headers map[string][]string) (*registrytypes.SearchResults, error)
|
||||
ServiceConfig() *registrytypes.ServiceConfig
|
||||
TLSConfig(hostname string) (*tls.Config, error)
|
||||
LoadMirrors([]string) error
|
||||
LoadInsecureRegistries([]string) error
|
||||
}
|
||||
|
||||
|
@ -73,6 +74,14 @@ func (s *DefaultService) ServiceConfig() *registrytypes.ServiceConfig {
|
|||
return &servConfig
|
||||
}
|
||||
|
||||
// LoadMirrors loads registry mirrors for Service
|
||||
func (s *DefaultService) LoadMirrors(mirrors []string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
return s.config.LoadMirrors(mirrors)
|
||||
}
|
||||
|
||||
// LoadInsecureRegistries loads insecure registries for Service
|
||||
func (s *DefaultService) LoadInsecureRegistries(registries []string) error {
|
||||
s.mu.Lock()
|
||||
|
|
Loading…
Add table
Reference in a new issue