diff --git a/daemon/daemon.go b/daemon/daemon.go index dcaba0db65..a187486c5d 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -6,6 +6,7 @@ package daemon import ( + "encoding/json" "fmt" "io" "io/ioutil" @@ -1337,6 +1338,11 @@ func (daemon *Daemon) initDiscovery(config *Config) error { func (daemon *Daemon) Reload(config *Config) error { daemon.configStore.reloadLock.Lock() defer daemon.configStore.reloadLock.Unlock() + + if err := daemon.reloadClusterDiscovery(config); err != nil { + return err + } + if config.IsValueSet("labels") { daemon.configStore.Labels = config.Labels } @@ -1370,7 +1376,26 @@ func (daemon *Daemon) Reload(config *Config) error { daemon.uploadManager.SetConcurrency(*daemon.configStore.MaxConcurrentUploads) } - return daemon.reloadClusterDiscovery(config) + // We emit daemon reload event here with updatable configurations + attributes := map[string]string{} + attributes["debug"] = fmt.Sprintf("%t", daemon.configStore.Debug) + attributes["cluster-store"] = daemon.configStore.ClusterStore + if daemon.configStore.ClusterOpts != nil { + opts, _ := json.Marshal(daemon.configStore.ClusterOpts) + attributes["cluster-store-opts"] = string(opts) + } else { + attributes["cluster-store-opts"] = "{}" + } + attributes["cluster-advertise"] = daemon.configStore.ClusterAdvertise + if daemon.configStore.Labels != nil { + labels, _ := json.Marshal(daemon.configStore.Labels) + attributes["labels"] = string(labels) + } else { + attributes["labels"] = "[]" + } + daemon.LogDaemonEventWithAttributes("reload", attributes) + + return nil } func (daemon *Daemon) reloadClusterDiscovery(config *Config) error { diff --git a/daemon/events.go b/daemon/events.go index 8ee04aa21a..4cec9c1e0d 100644 --- a/daemon/events.go +++ b/daemon/events.go @@ -80,6 +80,17 @@ func (daemon *Daemon) LogNetworkEventWithAttributes(nw libnetwork.Network, actio daemon.EventsService.Log(action, events.NetworkEventType, actor) } +// LogDaemonEventWithAttributes generates an event related to the daemon itself with specific given attributes. +func (daemon *Daemon) LogDaemonEventWithAttributes(action string, attributes map[string]string) { + if daemon.EventsService != nil { + actor := events.Actor{ + ID: daemon.ID, + Attributes: attributes, + } + daemon.EventsService.Log(action, events.DaemonEventType, actor) + } +} + // SubscribeToEvents returns the currently record of events, a channel to stream new events from, and a function to cancel the stream of events. func (daemon *Daemon) SubscribeToEvents(since, until time.Time, filter filters.Args) ([]events.Message, chan interface{}) { ef := daemonevents.NewFilter(filter) diff --git a/docs/reference/api/docker_remote_api.md b/docs/reference/api/docker_remote_api.md index 386d429080..89430d9903 100644 --- a/docs/reference/api/docker_remote_api.md +++ b/docs/reference/api/docker_remote_api.md @@ -119,6 +119,7 @@ This section lists each version from latest to oldest. Each listing includes a * `POST /containers/create` now returns a HTTP 400 "bad parameter" message if no command is specified (instead of a HTTP 500 "server error") * `GET /images/search` now takes a `filters` query parameter. +* `GET /events` now supports daemon events of `reload`. ### v1.23 API changes diff --git a/docs/reference/api/docker_remote_api_v1.24.md b/docs/reference/api/docker_remote_api_v1.24.md index 088fb09738..55dcd5184b 100644 --- a/docs/reference/api/docker_remote_api_v1.24.md +++ b/docs/reference/api/docker_remote_api_v1.24.md @@ -2420,6 +2420,10 @@ Docker networks report the following events: create, connect, disconnect, destroy +Docker daemon report the following event: + + reload + **Example request**: GET /events?since=1374067924 diff --git a/docs/reference/commandline/events.md b/docs/reference/commandline/events.md index 0abfdf4377..5a7b85f3cb 100644 --- a/docs/reference/commandline/events.md +++ b/docs/reference/commandline/events.md @@ -35,6 +35,10 @@ Docker networks report the following events: create, connect, disconnect, destroy +Docker daemon report the following events: + + reload + The `--since` and `--until` parameters can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the client machine’s time. If you do not provide the `--since` option, diff --git a/integration-cli/docker_cli_events_unix_test.go b/integration-cli/docker_cli_events_unix_test.go index 8ba67f1f67..435e1a18d7 100644 --- a/integration-cli/docker_cli_events_unix_test.go +++ b/integration-cli/docker_cli_events_unix_test.go @@ -9,6 +9,7 @@ import ( "os" "os/exec" "strings" + "syscall" "time" "unicode" @@ -366,3 +367,44 @@ func (s *DockerSuite) TestEventsFilterNetworkID(c *check.C) { c.Assert(events[0], checker.Contains, "test-event-network-local") c.Assert(events[0], checker.Contains, "type=bridge") } + +func (s *DockerDaemonSuite) TestDaemonEvents(c *check.C) { + testRequires(c, SameHostDaemon, DaemonIsLinux) + + // daemon config file + configFilePath := "test.json" + configFile, err := os.Create(configFilePath) + c.Assert(err, checker.IsNil) + defer os.Remove(configFilePath) + + daemonConfig := `{"labels":["foo=bar"]}` + fmt.Fprintf(configFile, "%s", daemonConfig) + configFile.Close() + c.Assert(s.d.Start(fmt.Sprintf("--config-file=%s", configFilePath)), check.IsNil) + + // Get daemon ID + out, err := s.d.Cmd("info") + c.Assert(err, checker.IsNil) + daemonID := "" + for _, line := range strings.Split(out, "\n") { + if strings.HasPrefix(line, "ID: ") { + daemonID = strings.TrimPrefix(line, "ID: ") + break + } + } + c.Assert(daemonID, checker.Not(checker.Equals), "") + + configFile, err = os.Create(configFilePath) + c.Assert(err, checker.IsNil) + daemonConfig = `{"labels":["bar=foo"]}` + fmt.Fprintf(configFile, "%s", daemonConfig) + configFile.Close() + + syscall.Kill(s.d.cmd.Process.Pid, syscall.SIGHUP) + + time.Sleep(3 * time.Second) + + 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, labels=[\"bar=foo\"])", daemonID)) +}