Signed-off-by: allencloud <allen.sun@daocloud.io>
| ... | ... |
@@ -992,6 +992,7 @@ func (daemon *Daemon) initDiscovery(config *Config) error {
|
| 992 | 992 |
// These are the settings that Reload changes: |
| 993 | 993 |
// - Daemon labels. |
| 994 | 994 |
// - Daemon debug log level. |
| 995 |
+// - Daemon insecure registries. |
|
| 995 | 996 |
// - Daemon max concurrent downloads |
| 996 | 997 |
// - Daemon max concurrent uploads |
| 997 | 998 |
// - Cluster discovery (reconfigure and restart). |
| ... | ... |
@@ -1023,6 +1024,12 @@ func (daemon *Daemon) Reload(config *Config) (err error) {
|
| 1023 | 1023 |
if config.IsValueSet("debug") {
|
| 1024 | 1024 |
daemon.configStore.Debug = config.Debug |
| 1025 | 1025 |
} |
| 1026 |
+ if config.IsValueSet("insecure-registries") {
|
|
| 1027 |
+ daemon.configStore.InsecureRegistries = config.InsecureRegistries |
|
| 1028 |
+ if err := daemon.RegistryService.LoadInsecureRegistries(config.InsecureRegistries); err != nil {
|
|
| 1029 |
+ return err |
|
| 1030 |
+ } |
|
| 1031 |
+ } |
|
| 1026 | 1032 |
if config.IsValueSet("live-restore") {
|
| 1027 | 1033 |
daemon.configStore.LiveRestoreEnabled = config.LiveRestoreEnabled |
| 1028 | 1034 |
if err := daemon.containerdRemote.UpdateOptions(libcontainerd.WithLiveRestore(config.LiveRestoreEnabled)); err != nil {
|
| ... | ... |
@@ -1065,20 +1072,39 @@ func (daemon *Daemon) Reload(config *Config) (err error) {
|
| 1065 | 1065 |
// We emit daemon reload event here with updatable configurations |
| 1066 | 1066 |
attributes["debug"] = fmt.Sprintf("%t", daemon.configStore.Debug)
|
| 1067 | 1067 |
attributes["live-restore"] = fmt.Sprintf("%t", daemon.configStore.LiveRestoreEnabled)
|
| 1068 |
+ |
|
| 1069 |
+ if daemon.configStore.InsecureRegistries != nil {
|
|
| 1070 |
+ insecureRegistries, err := json.Marshal(daemon.configStore.InsecureRegistries) |
|
| 1071 |
+ if err != nil {
|
|
| 1072 |
+ return err |
|
| 1073 |
+ } |
|
| 1074 |
+ attributes["insecure-registries"] = string(insecureRegistries) |
|
| 1075 |
+ } else {
|
|
| 1076 |
+ attributes["insecure-registries"] = "[]" |
|
| 1077 |
+ } |
|
| 1078 |
+ |
|
| 1068 | 1079 |
attributes["cluster-store"] = daemon.configStore.ClusterStore |
| 1069 | 1080 |
if daemon.configStore.ClusterOpts != nil {
|
| 1070 |
- opts, _ := json.Marshal(daemon.configStore.ClusterOpts) |
|
| 1081 |
+ opts, err := json.Marshal(daemon.configStore.ClusterOpts) |
|
| 1082 |
+ if err != nil {
|
|
| 1083 |
+ return err |
|
| 1084 |
+ } |
|
| 1071 | 1085 |
attributes["cluster-store-opts"] = string(opts) |
| 1072 | 1086 |
} else {
|
| 1073 | 1087 |
attributes["cluster-store-opts"] = "{}"
|
| 1074 | 1088 |
} |
| 1075 | 1089 |
attributes["cluster-advertise"] = daemon.configStore.ClusterAdvertise |
| 1090 |
+ |
|
| 1076 | 1091 |
if daemon.configStore.Labels != nil {
|
| 1077 |
- labels, _ := json.Marshal(daemon.configStore.Labels) |
|
| 1092 |
+ labels, err := json.Marshal(daemon.configStore.Labels) |
|
| 1093 |
+ if err != nil {
|
|
| 1094 |
+ return err |
|
| 1095 |
+ } |
|
| 1078 | 1096 |
attributes["labels"] = string(labels) |
| 1079 | 1097 |
} else {
|
| 1080 | 1098 |
attributes["labels"] = "[]" |
| 1081 | 1099 |
} |
| 1100 |
+ |
|
| 1082 | 1101 |
attributes["max-concurrent-downloads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentDownloads)
|
| 1083 | 1102 |
attributes["max-concurrent-uploads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentUploads)
|
| 1084 | 1103 |
attributes["shutdown-timeout"] = fmt.Sprintf("%d", daemon.configStore.ShutdownTimeout)
|
| ... | ... |
@@ -14,6 +14,7 @@ import ( |
| 14 | 14 |
_ "github.com/docker/docker/pkg/discovery/memory" |
| 15 | 15 |
"github.com/docker/docker/pkg/registrar" |
| 16 | 16 |
"github.com/docker/docker/pkg/truncindex" |
| 17 |
+ "github.com/docker/docker/registry" |
|
| 17 | 18 |
"github.com/docker/docker/volume" |
| 18 | 19 |
volumedrivers "github.com/docker/docker/volume/drivers" |
| 19 | 20 |
"github.com/docker/docker/volume/local" |
| ... | ... |
@@ -328,13 +329,102 @@ func TestDaemonReloadLabels(t *testing.T) {
|
| 328 | 328 |
}, |
| 329 | 329 |
} |
| 330 | 330 |
|
| 331 |
- daemon.Reload(newConfig) |
|
| 331 |
+ if err := daemon.Reload(newConfig); err != nil {
|
|
| 332 |
+ t.Fatal(err) |
|
| 333 |
+ } |
|
| 334 |
+ |
|
| 332 | 335 |
label := daemon.configStore.Labels[0] |
| 333 | 336 |
if label != "foo:baz" {
|
| 334 | 337 |
t.Fatalf("Expected daemon label `foo:baz`, got %s", label)
|
| 335 | 338 |
} |
| 336 | 339 |
} |
| 337 | 340 |
|
| 341 |
+func TestDaemonReloadInsecureRegistries(t *testing.T) {
|
|
| 342 |
+ daemon := &Daemon{}
|
|
| 343 |
+ // initialize daemon with existing insecure registries: "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000" |
|
| 344 |
+ daemon.RegistryService = registry.NewService(registry.ServiceOptions{
|
|
| 345 |
+ InsecureRegistries: []string{
|
|
| 346 |
+ "127.0.0.0/8", |
|
| 347 |
+ "10.10.1.11:5000", |
|
| 348 |
+ "10.10.1.22:5000", // this will be removed when reloading |
|
| 349 |
+ "docker1.com", |
|
| 350 |
+ "docker2.com", // this will be removed when reloading |
|
| 351 |
+ }, |
|
| 352 |
+ }) |
|
| 353 |
+ |
|
| 354 |
+ daemon.configStore = &Config{}
|
|
| 355 |
+ |
|
| 356 |
+ insecureRegistries := []string{
|
|
| 357 |
+ "127.0.0.0/8", // this will be kept |
|
| 358 |
+ "10.10.1.11:5000", // this will be kept |
|
| 359 |
+ "10.10.1.33:5000", // this will be newly added |
|
| 360 |
+ "docker1.com", // this will be kept |
|
| 361 |
+ "docker3.com", // this will be newly added |
|
| 362 |
+ } |
|
| 363 |
+ |
|
| 364 |
+ valuesSets := make(map[string]interface{})
|
|
| 365 |
+ valuesSets["insecure-registries"] = insecureRegistries |
|
| 366 |
+ |
|
| 367 |
+ newConfig := &Config{
|
|
| 368 |
+ CommonConfig: CommonConfig{
|
|
| 369 |
+ ServiceOptions: registry.ServiceOptions{
|
|
| 370 |
+ InsecureRegistries: insecureRegistries, |
|
| 371 |
+ }, |
|
| 372 |
+ valuesSet: valuesSets, |
|
| 373 |
+ }, |
|
| 374 |
+ } |
|
| 375 |
+ |
|
| 376 |
+ if err := daemon.Reload(newConfig); err != nil {
|
|
| 377 |
+ t.Fatal(err) |
|
| 378 |
+ } |
|
| 379 |
+ |
|
| 380 |
+ // After Reload, daemon.RegistryService will be changed which is useful |
|
| 381 |
+ // for registry communication in daemon. |
|
| 382 |
+ registries := daemon.RegistryService.ServiceConfig() |
|
| 383 |
+ |
|
| 384 |
+ // After Reload(), newConfig has come to registries.InsecureRegistryCIDRs and registries.IndexConfigs in daemon. |
|
| 385 |
+ // Then collect registries.InsecureRegistryCIDRs in dataMap. |
|
| 386 |
+ // When collecting, we need to convert CIDRS into string as a key, |
|
| 387 |
+ // while the times of key appears as value. |
|
| 388 |
+ dataMap := map[string]int{}
|
|
| 389 |
+ for _, value := range registries.InsecureRegistryCIDRs {
|
|
| 390 |
+ if _, ok := dataMap[value.String()]; !ok {
|
|
| 391 |
+ dataMap[value.String()] = 1 |
|
| 392 |
+ } else {
|
|
| 393 |
+ dataMap[value.String()]++ |
|
| 394 |
+ } |
|
| 395 |
+ } |
|
| 396 |
+ |
|
| 397 |
+ for _, value := range registries.IndexConfigs {
|
|
| 398 |
+ if _, ok := dataMap[value.Name]; !ok {
|
|
| 399 |
+ dataMap[value.Name] = 1 |
|
| 400 |
+ } else {
|
|
| 401 |
+ dataMap[value.Name]++ |
|
| 402 |
+ } |
|
| 403 |
+ } |
|
| 404 |
+ |
|
| 405 |
+ // Finally compare dataMap with the original insecureRegistries. |
|
| 406 |
+ // Each value in insecureRegistries should appear in daemon's insecure registries, |
|
| 407 |
+ // and each can only appear exactly ONCE. |
|
| 408 |
+ for _, r := range insecureRegistries {
|
|
| 409 |
+ if value, ok := dataMap[r]; !ok {
|
|
| 410 |
+ t.Fatalf("Expected daemon insecure registry %s, got none", r)
|
|
| 411 |
+ } else if value != 1 {
|
|
| 412 |
+ t.Fatalf("Expected only 1 daemon insecure registry %s, got %d", r, value)
|
|
| 413 |
+ } |
|
| 414 |
+ } |
|
| 415 |
+ |
|
| 416 |
+ // assert if "10.10.1.22:5000" is removed when reloading |
|
| 417 |
+ if value, ok := dataMap["10.10.1.22:5000"]; ok {
|
|
| 418 |
+ t.Fatalf("Expected no insecure registry of 10.10.1.22:5000, got %d", value)
|
|
| 419 |
+ } |
|
| 420 |
+ |
|
| 421 |
+ // assert if "docker2.com" is removed when reloading |
|
| 422 |
+ if value, ok := dataMap["docker2.com"]; ok {
|
|
| 423 |
+ t.Fatalf("Expected no insecure registry of docker2.com, got %d", value)
|
|
| 424 |
+ } |
|
| 425 |
+} |
|
| 426 |
+ |
|
| 338 | 427 |
func TestDaemonReloadNotAffectOthers(t *testing.T) {
|
| 339 | 428 |
daemon := &Daemon{}
|
| 340 | 429 |
daemon.configStore = &Config{
|
| ... | ... |
@@ -353,7 +443,10 @@ func TestDaemonReloadNotAffectOthers(t *testing.T) {
|
| 353 | 353 |
}, |
| 354 | 354 |
} |
| 355 | 355 |
|
| 356 |
- daemon.Reload(newConfig) |
|
| 356 |
+ if err := daemon.Reload(newConfig); err != nil {
|
|
| 357 |
+ t.Fatal(err) |
|
| 358 |
+ } |
|
| 359 |
+ |
|
| 357 | 360 |
label := daemon.configStore.Labels[0] |
| 358 | 361 |
if label != "foo:baz" {
|
| 359 | 362 |
t.Fatalf("Expected daemon label `foo:baz`, got %s", label)
|
| ... | ... |
@@ -1241,12 +1241,13 @@ The list of currently supported options that can be reconfigured is this: |
| 1241 | 1241 |
- `runtimes`: it updates the list of available OCI runtimes that can |
| 1242 | 1242 |
be used to run containers |
| 1243 | 1243 |
- `authorization-plugin`: specifies the authorization plugins to use. |
| 1244 |
+- `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. |
|
| 1244 | 1245 |
|
| 1245 | 1246 |
Updating and reloading the cluster configurations such as `--cluster-store`, |
| 1246 | 1247 |
`--cluster-advertise` and `--cluster-store-opts` will take effect only if |
| 1247 | 1248 |
these configurations were not previously configured. If `--cluster-store` |
| 1248 | 1249 |
has been provided in flags and `cluster-advertise` not, `cluster-advertise` |
| 1249 |
-can be added in the configuration file without accompanied by `--cluster-store` |
|
| 1250 |
+can be added in the configuration file without accompanied by `--cluster-store`. |
|
| 1250 | 1251 |
Configuration reload will log a warning message if it detects a change in |
| 1251 | 1252 |
previously configured cluster configurations. |
| 1252 | 1253 |
|
| ... | ... |
@@ -429,7 +429,7 @@ func (s *DockerDaemonSuite) TestDaemonEvents(c *check.C) {
|
| 429 | 429 |
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c))
|
| 430 | 430 |
c.Assert(err, checker.IsNil) |
| 431 | 431 |
|
| 432 |
- c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s (cluster-advertise=, cluster-store=, cluster-store-opts={}, debug=true, default-runtime=runc, 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))
|
|
| 432 |
+ 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))
|
|
| 433 | 433 |
} |
| 434 | 434 |
|
| 435 | 435 |
func (s *DockerDaemonSuite) TestDaemonEventsWithFilters(c *check.C) {
|
| ... | ... |
@@ -82,13 +82,6 @@ func (options *ServiceOptions) InstallCliFlags(flags *pflag.FlagSet) {
|
| 82 | 82 |
|
| 83 | 83 |
// newServiceConfig returns a new instance of ServiceConfig |
| 84 | 84 |
func newServiceConfig(options ServiceOptions) *serviceConfig {
|
| 85 |
- // Localhost is by default considered as an insecure registry |
|
| 86 |
- // This is a stop-gap for people who are running a private registry on localhost (especially on Boot2docker). |
|
| 87 |
- // |
|
| 88 |
- // TODO: should we deprecate this once it is easier for people to set up a TLS registry or change |
|
| 89 |
- // daemon flags on boot2docker? |
|
| 90 |
- options.InsecureRegistries = append(options.InsecureRegistries, "127.0.0.0/8") |
|
| 91 |
- |
|
| 92 | 85 |
config := &serviceConfig{
|
| 93 | 86 |
ServiceConfig: registrytypes.ServiceConfig{
|
| 94 | 87 |
InsecureRegistryCIDRs: make([]*registrytypes.NetIPNet, 0), |
| ... | ... |
@@ -99,13 +92,51 @@ func newServiceConfig(options ServiceOptions) *serviceConfig {
|
| 99 | 99 |
}, |
| 100 | 100 |
V2Only: options.V2Only, |
| 101 | 101 |
} |
| 102 |
- // Split --insecure-registry into CIDR and registry-specific settings. |
|
| 103 |
- for _, r := range options.InsecureRegistries {
|
|
| 102 |
+ |
|
| 103 |
+ config.LoadInsecureRegistries(options.InsecureRegistries) |
|
| 104 |
+ |
|
| 105 |
+ return config |
|
| 106 |
+} |
|
| 107 |
+ |
|
| 108 |
+// LoadInsecureRegistries loads insecure registries to config |
|
| 109 |
+func (config *serviceConfig) LoadInsecureRegistries(registries []string) error {
|
|
| 110 |
+ // Localhost is by default considered as an insecure registry |
|
| 111 |
+ // This is a stop-gap for people who are running a private registry on localhost (especially on Boot2docker). |
|
| 112 |
+ // |
|
| 113 |
+ // TODO: should we deprecate this once it is easier for people to set up a TLS registry or change |
|
| 114 |
+ // daemon flags on boot2docker? |
|
| 115 |
+ registries = append(registries, "127.0.0.0/8") |
|
| 116 |
+ |
|
| 117 |
+ // Store original InsecureRegistryCIDRs and IndexConfigs |
|
| 118 |
+ // Clean InsecureRegistryCIDRs and IndexConfigs in config, as passed registries has all insecure registry info. |
|
| 119 |
+ originalCIDRs := config.ServiceConfig.InsecureRegistryCIDRs |
|
| 120 |
+ originalIndexInfos := config.ServiceConfig.IndexConfigs |
|
| 121 |
+ |
|
| 122 |
+ config.ServiceConfig.InsecureRegistryCIDRs = make([]*registrytypes.NetIPNet, 0) |
|
| 123 |
+ config.ServiceConfig.IndexConfigs = make(map[string]*registrytypes.IndexInfo, 0) |
|
| 124 |
+ |
|
| 125 |
+skip: |
|
| 126 |
+ for _, r := range registries {
|
|
| 127 |
+ // validate insecure registry |
|
| 128 |
+ if _, err := ValidateIndexName(r); err != nil {
|
|
| 129 |
+ // before returning err, roll back to original data |
|
| 130 |
+ config.ServiceConfig.InsecureRegistryCIDRs = originalCIDRs |
|
| 131 |
+ config.ServiceConfig.IndexConfigs = originalIndexInfos |
|
| 132 |
+ return err |
|
| 133 |
+ } |
|
| 104 | 134 |
// Check if CIDR was passed to --insecure-registry |
| 105 | 135 |
_, ipnet, err := net.ParseCIDR(r) |
| 106 | 136 |
if err == nil {
|
| 107 |
- // Valid CIDR. |
|
| 108 |
- config.InsecureRegistryCIDRs = append(config.InsecureRegistryCIDRs, (*registrytypes.NetIPNet)(ipnet)) |
|
| 137 |
+ // Valid CIDR. If ipnet is already in config.InsecureRegistryCIDRs, skip. |
|
| 138 |
+ data := (*registrytypes.NetIPNet)(ipnet) |
|
| 139 |
+ for _, value := range config.InsecureRegistryCIDRs {
|
|
| 140 |
+ if value.IP.String() == data.IP.String() && value.Mask.String() == data.Mask.String() {
|
|
| 141 |
+ continue skip |
|
| 142 |
+ } |
|
| 143 |
+ } |
|
| 144 |
+ // ipnet is not found, add it in config.InsecureRegistryCIDRs |
|
| 145 |
+ config.InsecureRegistryCIDRs = append(config.InsecureRegistryCIDRs, data) |
|
| 146 |
+ |
|
| 109 | 147 |
} else {
|
| 110 | 148 |
// Assume `host:port` if not CIDR. |
| 111 | 149 |
config.IndexConfigs[r] = ®istrytypes.IndexInfo{
|
| ... | ... |
@@ -125,7 +156,7 @@ func newServiceConfig(options ServiceOptions) *serviceConfig {
|
| 125 | 125 |
Official: true, |
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 |
- return config |
|
| 128 |
+ return nil |
|
| 129 | 129 |
} |
| 130 | 130 |
|
| 131 | 131 |
// isSecureIndex returns false if the provided indexName is part of the list of insecure registries |
| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"net/http" |
| 7 | 7 |
"net/url" |
| 8 | 8 |
"strings" |
| 9 |
+ "sync" |
|
| 9 | 10 |
|
| 10 | 11 |
"golang.org/x/net/context" |
| 11 | 12 |
|
| ... | ... |
@@ -30,12 +31,14 @@ type Service interface {
|
| 30 | 30 |
Search(ctx context.Context, term string, limit int, authConfig *types.AuthConfig, userAgent string, headers map[string][]string) (*registrytypes.SearchResults, error) |
| 31 | 31 |
ServiceConfig() *registrytypes.ServiceConfig |
| 32 | 32 |
TLSConfig(hostname string) (*tls.Config, error) |
| 33 |
+ LoadInsecureRegistries([]string) error |
|
| 33 | 34 |
} |
| 34 | 35 |
|
| 35 | 36 |
// DefaultService is a registry service. It tracks configuration data such as a list |
| 36 | 37 |
// of mirrors. |
| 37 | 38 |
type DefaultService struct {
|
| 38 | 39 |
config *serviceConfig |
| 40 |
+ mu sync.Mutex |
|
| 39 | 41 |
} |
| 40 | 42 |
|
| 41 | 43 |
// NewService returns a new instance of DefaultService ready to be |
| ... | ... |
@@ -48,7 +51,34 @@ func NewService(options ServiceOptions) *DefaultService {
|
| 48 | 48 |
|
| 49 | 49 |
// ServiceConfig returns the public registry service configuration. |
| 50 | 50 |
func (s *DefaultService) ServiceConfig() *registrytypes.ServiceConfig {
|
| 51 |
- return &s.config.ServiceConfig |
|
| 51 |
+ s.mu.Lock() |
|
| 52 |
+ defer s.mu.Unlock() |
|
| 53 |
+ |
|
| 54 |
+ servConfig := registrytypes.ServiceConfig{
|
|
| 55 |
+ InsecureRegistryCIDRs: make([]*(registrytypes.NetIPNet), 0), |
|
| 56 |
+ IndexConfigs: make(map[string]*(registrytypes.IndexInfo)), |
|
| 57 |
+ Mirrors: make([]string, 0), |
|
| 58 |
+ } |
|
| 59 |
+ |
|
| 60 |
+ // construct a new ServiceConfig which will not retrieve s.Config directly, |
|
| 61 |
+ // and look up items in s.config with mu locked |
|
| 62 |
+ servConfig.InsecureRegistryCIDRs = append(servConfig.InsecureRegistryCIDRs, s.config.ServiceConfig.InsecureRegistryCIDRs...) |
|
| 63 |
+ |
|
| 64 |
+ for key, value := range s.config.ServiceConfig.IndexConfigs {
|
|
| 65 |
+ servConfig.IndexConfigs[key] = value |
|
| 66 |
+ } |
|
| 67 |
+ |
|
| 68 |
+ servConfig.Mirrors = append(servConfig.Mirrors, s.config.ServiceConfig.Mirrors...) |
|
| 69 |
+ |
|
| 70 |
+ return &servConfig |
|
| 71 |
+} |
|
| 72 |
+ |
|
| 73 |
+// LoadInsecureRegistries loads insecure registries for Service |
|
| 74 |
+func (s *DefaultService) LoadInsecureRegistries(registries []string) error {
|
|
| 75 |
+ s.mu.Lock() |
|
| 76 |
+ defer s.mu.Unlock() |
|
| 77 |
+ |
|
| 78 |
+ return s.config.LoadInsecureRegistries(registries) |
|
| 52 | 79 |
} |
| 53 | 80 |
|
| 54 | 81 |
// Auth contacts the public registry with the provided credentials, |
| ... | ... |
@@ -121,7 +151,11 @@ func (s *DefaultService) Search(ctx context.Context, term string, limit int, aut |
| 121 | 121 |
|
| 122 | 122 |
indexName, remoteName := splitReposSearchTerm(term) |
| 123 | 123 |
|
| 124 |
+ // Search is a long-running operation, just lock s.config to avoid block others. |
|
| 125 |
+ s.mu.Lock() |
|
| 124 | 126 |
index, err := newIndexInfo(s.config, indexName) |
| 127 |
+ s.mu.Unlock() |
|
| 128 |
+ |
|
| 125 | 129 |
if err != nil {
|
| 126 | 130 |
return nil, err |
| 127 | 131 |
} |
| ... | ... |
@@ -185,6 +219,8 @@ func (s *DefaultService) Search(ctx context.Context, term string, limit int, aut |
| 185 | 185 |
// ResolveRepository splits a repository name into its components |
| 186 | 186 |
// and configuration of the associated registry. |
| 187 | 187 |
func (s *DefaultService) ResolveRepository(name reference.Named) (*RepositoryInfo, error) {
|
| 188 |
+ s.mu.Lock() |
|
| 189 |
+ defer s.mu.Unlock() |
|
| 188 | 190 |
return newRepositoryInfo(s.config, name) |
| 189 | 191 |
} |
| 190 | 192 |
|
| ... | ... |
@@ -205,17 +241,28 @@ func (e APIEndpoint) ToV1Endpoint(userAgent string, metaHeaders http.Header) (*V |
| 205 | 205 |
|
| 206 | 206 |
// TLSConfig constructs a client TLS configuration based on server defaults |
| 207 | 207 |
func (s *DefaultService) TLSConfig(hostname string) (*tls.Config, error) {
|
| 208 |
+ s.mu.Lock() |
|
| 209 |
+ defer s.mu.Unlock() |
|
| 210 |
+ |
|
| 211 |
+ return newTLSConfig(hostname, isSecureIndex(s.config, hostname)) |
|
| 212 |
+} |
|
| 213 |
+ |
|
| 214 |
+// tlsConfig constructs a client TLS configuration based on server defaults |
|
| 215 |
+func (s *DefaultService) tlsConfig(hostname string) (*tls.Config, error) {
|
|
| 208 | 216 |
return newTLSConfig(hostname, isSecureIndex(s.config, hostname)) |
| 209 | 217 |
} |
| 210 | 218 |
|
| 211 | 219 |
func (s *DefaultService) tlsConfigForMirror(mirrorURL *url.URL) (*tls.Config, error) {
|
| 212 |
- return s.TLSConfig(mirrorURL.Host) |
|
| 220 |
+ return s.tlsConfig(mirrorURL.Host) |
|
| 213 | 221 |
} |
| 214 | 222 |
|
| 215 | 223 |
// LookupPullEndpoints creates a list of endpoints to try to pull from, in order of preference. |
| 216 | 224 |
// It gives preference to v2 endpoints over v1, mirrors over the actual |
| 217 | 225 |
// registry, and HTTPS over plain HTTP. |
| 218 | 226 |
func (s *DefaultService) LookupPullEndpoints(hostname string) (endpoints []APIEndpoint, err error) {
|
| 227 |
+ s.mu.Lock() |
|
| 228 |
+ defer s.mu.Unlock() |
|
| 229 |
+ |
|
| 219 | 230 |
return s.lookupEndpoints(hostname) |
| 220 | 231 |
} |
| 221 | 232 |
|
| ... | ... |
@@ -223,6 +270,9 @@ func (s *DefaultService) LookupPullEndpoints(hostname string) (endpoints []APIEn |
| 223 | 223 |
// It gives preference to v2 endpoints over v1, and HTTPS over plain HTTP. |
| 224 | 224 |
// Mirrors are not included. |
| 225 | 225 |
func (s *DefaultService) LookupPushEndpoints(hostname string) (endpoints []APIEndpoint, err error) {
|
| 226 |
+ s.mu.Lock() |
|
| 227 |
+ defer s.mu.Unlock() |
|
| 228 |
+ |
|
| 226 | 229 |
allEndpoints, err := s.lookupEndpoints(hostname) |
| 227 | 230 |
if err == nil {
|
| 228 | 231 |
for _, endpoint := range allEndpoints {
|