123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- package daemon // import "github.com/docker/docker/daemon"
- import (
- "reflect"
- "sort"
- "testing"
- "time"
- "github.com/docker/docker/daemon/config"
- "github.com/docker/docker/daemon/images"
- "github.com/docker/docker/pkg/discovery"
- _ "github.com/docker/docker/pkg/discovery/memory"
- "github.com/docker/docker/registry"
- "github.com/docker/libnetwork"
- "github.com/gotestyourself/gotestyourself/assert"
- is "github.com/gotestyourself/gotestyourself/assert/cmp"
- )
- func TestDaemonReloadLabels(t *testing.T) {
- daemon := &Daemon{
- configStore: &config.Config{
- CommonConfig: config.CommonConfig{
- Labels: []string{"foo:bar"},
- },
- },
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- valuesSets := make(map[string]interface{})
- valuesSets["labels"] = "foo:baz"
- newConfig := &config.Config{
- CommonConfig: config.CommonConfig{
- Labels: []string{"foo:baz"},
- ValuesSet: valuesSets,
- },
- }
- if err := daemon.Reload(newConfig); err != nil {
- t.Fatal(err)
- }
- label := daemon.configStore.Labels[0]
- if label != "foo:baz" {
- t.Fatalf("Expected daemon label `foo:baz`, got %s", label)
- }
- }
- func TestDaemonReloadAllowNondistributableArtifacts(t *testing.T) {
- daemon := &Daemon{
- configStore: &config.Config{},
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- var err error
- // Initialize daemon with some registries.
- daemon.RegistryService, err = registry.NewService(registry.ServiceOptions{
- AllowNondistributableArtifacts: []string{
- "127.0.0.0/8",
- "10.10.1.11:5000",
- "10.10.1.22:5000", // This will be removed during reload.
- "docker1.com",
- "docker2.com", // This will be removed during reload.
- },
- })
- if err != nil {
- t.Fatal(err)
- }
- registries := []string{
- "127.0.0.0/8",
- "10.10.1.11:5000",
- "10.10.1.33:5000", // This will be added during reload.
- "docker1.com",
- "docker3.com", // This will be added during reload.
- }
- newConfig := &config.Config{
- CommonConfig: config.CommonConfig{
- ServiceOptions: registry.ServiceOptions{
- AllowNondistributableArtifacts: registries,
- },
- ValuesSet: map[string]interface{}{
- "allow-nondistributable-artifacts": registries,
- },
- },
- }
- if err := daemon.Reload(newConfig); err != nil {
- t.Fatal(err)
- }
- var actual []string
- serviceConfig := daemon.RegistryService.ServiceConfig()
- for _, value := range serviceConfig.AllowNondistributableArtifactsCIDRs {
- actual = append(actual, value.String())
- }
- actual = append(actual, serviceConfig.AllowNondistributableArtifactsHostnames...)
- sort.Strings(registries)
- sort.Strings(actual)
- assert.Check(t, is.DeepEqual(registries, actual))
- }
- func TestDaemonReloadMirrors(t *testing.T) {
- daemon := &Daemon{
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- var err error
- daemon.RegistryService, err = 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
- },
- })
- if err != nil {
- t.Fatal(err)
- }
- daemon.configStore = &config.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.Config{
- CommonConfig: config.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{
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- var err error
- // initialize daemon with existing insecure registries: "127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000"
- daemon.RegistryService, err = registry.NewService(registry.ServiceOptions{
- InsecureRegistries: []string{
- "127.0.0.0/8",
- "10.10.1.11:5000",
- "10.10.1.22:5000", // this will be removed when reloading
- "docker1.com",
- "docker2.com", // this will be removed when reloading
- },
- })
- if err != nil {
- t.Fatal(err)
- }
- daemon.configStore = &config.Config{}
- insecureRegistries := []string{
- "127.0.0.0/8", // this will be kept
- "10.10.1.11:5000", // this will be kept
- "10.10.1.33:5000", // this will be newly added
- "docker1.com", // this will be kept
- "docker3.com", // this will be newly added
- }
- valuesSets := make(map[string]interface{})
- valuesSets["insecure-registries"] = insecureRegistries
- newConfig := &config.Config{
- CommonConfig: config.CommonConfig{
- ServiceOptions: registry.ServiceOptions{
- InsecureRegistries: insecureRegistries,
- },
- ValuesSet: valuesSets,
- },
- }
- if err := daemon.Reload(newConfig); err != nil {
- t.Fatal(err)
- }
- // After Reload, daemon.RegistryService will be changed which is useful
- // for registry communication in daemon.
- registries := daemon.RegistryService.ServiceConfig()
- // After Reload(), newConfig has come to registries.InsecureRegistryCIDRs and registries.IndexConfigs in daemon.
- // Then collect registries.InsecureRegistryCIDRs in dataMap.
- // When collecting, we need to convert CIDRS into string as a key,
- // while the times of key appears as value.
- dataMap := map[string]int{}
- for _, value := range registries.InsecureRegistryCIDRs {
- if _, ok := dataMap[value.String()]; !ok {
- dataMap[value.String()] = 1
- } else {
- dataMap[value.String()]++
- }
- }
- for _, value := range registries.IndexConfigs {
- if _, ok := dataMap[value.Name]; !ok {
- dataMap[value.Name] = 1
- } else {
- dataMap[value.Name]++
- }
- }
- // Finally compare dataMap with the original insecureRegistries.
- // Each value in insecureRegistries should appear in daemon's insecure registries,
- // and each can only appear exactly ONCE.
- for _, r := range insecureRegistries {
- if value, ok := dataMap[r]; !ok {
- t.Fatalf("Expected daemon insecure registry %s, got none", r)
- } else if value != 1 {
- t.Fatalf("Expected only 1 daemon insecure registry %s, got %d", r, value)
- }
- }
- // assert if "10.10.1.22:5000" is removed when reloading
- if value, ok := dataMap["10.10.1.22:5000"]; ok {
- t.Fatalf("Expected no insecure registry of 10.10.1.22:5000, got %d", value)
- }
- // assert if "docker2.com" is removed when reloading
- if value, ok := dataMap["docker2.com"]; ok {
- t.Fatalf("Expected no insecure registry of docker2.com, got %d", value)
- }
- }
- func TestDaemonReloadNotAffectOthers(t *testing.T) {
- daemon := &Daemon{
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- daemon.configStore = &config.Config{
- CommonConfig: config.CommonConfig{
- Labels: []string{"foo:bar"},
- Debug: true,
- },
- }
- valuesSets := make(map[string]interface{})
- valuesSets["labels"] = "foo:baz"
- newConfig := &config.Config{
- CommonConfig: config.CommonConfig{
- Labels: []string{"foo:baz"},
- ValuesSet: valuesSets,
- },
- }
- if err := daemon.Reload(newConfig); err != nil {
- t.Fatal(err)
- }
- label := daemon.configStore.Labels[0]
- if label != "foo:baz" {
- t.Fatalf("Expected daemon label `foo:baz`, got %s", label)
- }
- debug := daemon.configStore.Debug
- if !debug {
- t.Fatal("Expected debug 'enabled', got 'disabled'")
- }
- }
- func TestDaemonDiscoveryReload(t *testing.T) {
- daemon := &Daemon{
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- daemon.configStore = &config.Config{
- CommonConfig: config.CommonConfig{
- ClusterStore: "memory://127.0.0.1",
- ClusterAdvertise: "127.0.0.1:3333",
- },
- }
- if err := daemon.initDiscovery(daemon.configStore); err != nil {
- t.Fatal(err)
- }
- expected := discovery.Entries{
- &discovery.Entry{Host: "127.0.0.1", Port: "3333"},
- }
- select {
- case <-time.After(10 * time.Second):
- t.Fatal("timeout waiting for discovery")
- case <-daemon.discoveryWatcher.ReadyCh():
- }
- stopCh := make(chan struct{})
- defer close(stopCh)
- ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
- select {
- case <-time.After(1 * time.Second):
- t.Fatal("failed to get discovery advertisements in time")
- case e := <-ch:
- if !reflect.DeepEqual(e, expected) {
- t.Fatalf("expected %v, got %v\n", expected, e)
- }
- case e := <-errCh:
- t.Fatal(e)
- }
- valuesSets := make(map[string]interface{})
- valuesSets["cluster-store"] = "memory://127.0.0.1:2222"
- valuesSets["cluster-advertise"] = "127.0.0.1:5555"
- newConfig := &config.Config{
- CommonConfig: config.CommonConfig{
- ClusterStore: "memory://127.0.0.1:2222",
- ClusterAdvertise: "127.0.0.1:5555",
- ValuesSet: valuesSets,
- },
- }
- expected = discovery.Entries{
- &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
- }
- if err := daemon.Reload(newConfig); err != nil {
- t.Fatal(err)
- }
- select {
- case <-time.After(10 * time.Second):
- t.Fatal("timeout waiting for discovery")
- case <-daemon.discoveryWatcher.ReadyCh():
- }
- ch, errCh = daemon.discoveryWatcher.Watch(stopCh)
- select {
- case <-time.After(1 * time.Second):
- t.Fatal("failed to get discovery advertisements in time")
- case e := <-ch:
- if !reflect.DeepEqual(e, expected) {
- t.Fatalf("expected %v, got %v\n", expected, e)
- }
- case e := <-errCh:
- t.Fatal(e)
- }
- }
- func TestDaemonDiscoveryReloadFromEmptyDiscovery(t *testing.T) {
- daemon := &Daemon{
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- daemon.configStore = &config.Config{}
- valuesSet := make(map[string]interface{})
- valuesSet["cluster-store"] = "memory://127.0.0.1:2222"
- valuesSet["cluster-advertise"] = "127.0.0.1:5555"
- newConfig := &config.Config{
- CommonConfig: config.CommonConfig{
- ClusterStore: "memory://127.0.0.1:2222",
- ClusterAdvertise: "127.0.0.1:5555",
- ValuesSet: valuesSet,
- },
- }
- expected := discovery.Entries{
- &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
- }
- if err := daemon.Reload(newConfig); err != nil {
- t.Fatal(err)
- }
- select {
- case <-time.After(10 * time.Second):
- t.Fatal("timeout waiting for discovery")
- case <-daemon.discoveryWatcher.ReadyCh():
- }
- stopCh := make(chan struct{})
- defer close(stopCh)
- ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
- select {
- case <-time.After(1 * time.Second):
- t.Fatal("failed to get discovery advertisements in time")
- case e := <-ch:
- if !reflect.DeepEqual(e, expected) {
- t.Fatalf("expected %v, got %v\n", expected, e)
- }
- case e := <-errCh:
- t.Fatal(e)
- }
- }
- func TestDaemonDiscoveryReloadOnlyClusterAdvertise(t *testing.T) {
- daemon := &Daemon{
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- daemon.configStore = &config.Config{
- CommonConfig: config.CommonConfig{
- ClusterStore: "memory://127.0.0.1",
- },
- }
- valuesSets := make(map[string]interface{})
- valuesSets["cluster-advertise"] = "127.0.0.1:5555"
- newConfig := &config.Config{
- CommonConfig: config.CommonConfig{
- ClusterAdvertise: "127.0.0.1:5555",
- ValuesSet: valuesSets,
- },
- }
- expected := discovery.Entries{
- &discovery.Entry{Host: "127.0.0.1", Port: "5555"},
- }
- if err := daemon.Reload(newConfig); err != nil {
- t.Fatal(err)
- }
- select {
- case <-daemon.discoveryWatcher.ReadyCh():
- case <-time.After(10 * time.Second):
- t.Fatal("Timeout waiting for discovery")
- }
- stopCh := make(chan struct{})
- defer close(stopCh)
- ch, errCh := daemon.discoveryWatcher.Watch(stopCh)
- select {
- case <-time.After(1 * time.Second):
- t.Fatal("failed to get discovery advertisements in time")
- case e := <-ch:
- if !reflect.DeepEqual(e, expected) {
- t.Fatalf("expected %v, got %v\n", expected, e)
- }
- case e := <-errCh:
- t.Fatal(e)
- }
- }
- func TestDaemonReloadNetworkDiagnosticPort(t *testing.T) {
- daemon := &Daemon{
- imageService: images.NewImageService(images.ImageServiceConfig{}),
- }
- daemon.configStore = &config.Config{}
- valuesSet := make(map[string]interface{})
- valuesSet["network-diagnostic-port"] = 2000
- enableConfig := &config.Config{
- CommonConfig: config.CommonConfig{
- NetworkDiagnosticPort: 2000,
- ValuesSet: valuesSet,
- },
- }
- disableConfig := &config.Config{
- CommonConfig: config.CommonConfig{},
- }
- netOptions, err := daemon.networkOptions(enableConfig, nil, nil)
- if err != nil {
- t.Fatal(err)
- }
- controller, err := libnetwork.New(netOptions...)
- if err != nil {
- t.Fatal(err)
- }
- daemon.netController = controller
- // Enable/Disable the server for some iterations
- for i := 0; i < 10; i++ {
- enableConfig.CommonConfig.NetworkDiagnosticPort++
- if err := daemon.Reload(enableConfig); err != nil {
- t.Fatal(err)
- }
- // Check that the diagnostic is enabled
- if !daemon.netController.IsDiagnosticEnabled() {
- t.Fatalf("diagnostic should be enable")
- }
- // Reload
- if err := daemon.Reload(disableConfig); err != nil {
- t.Fatal(err)
- }
- // Check that the diagnostic is disabled
- if daemon.netController.IsDiagnosticEnabled() {
- t.Fatalf("diagnostic should be disable")
- }
- }
- enableConfig.CommonConfig.NetworkDiagnosticPort++
- // 2 times the enable should not create problems
- if err := daemon.Reload(enableConfig); err != nil {
- t.Fatal(err)
- }
- // Check that the diagnostic is enabled
- if !daemon.netController.IsDiagnosticEnabled() {
- t.Fatalf("diagnostic should be enable")
- }
- // Check that another reload does not cause issues
- if err := daemon.Reload(enableConfig); err != nil {
- t.Fatal(err)
- }
- // Check that the diagnostic is enable
- if !daemon.netController.IsDiagnosticEnabled() {
- t.Fatalf("diagnostic should be enable")
- }
- }
|