Skip to content

Commit

Permalink
Emit events for docker daemon
Browse files Browse the repository at this point in the history
This fix tries to cover the issue raised in moby#22463 by emitting
events for docker daemon so that user could be notified by
scenarios like config reload, etc.

This fix adds the `daemon reload`, and events for docker daemon.

Additional tests have been added to cover the changes in this fix.

This fix fixes moby#22463.

Signed-off-by: Yong Tang <[email protected]>
  • Loading branch information
yongtang committed May 24, 2016
1 parent 9bc6c4e commit 382c152
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 1 deletion.
27 changes: 26 additions & 1 deletion daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package daemon

import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 11 additions & 0 deletions daemon/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions docs/reference/api/docker_remote_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions docs/reference/api/docker_remote_api_v1.24.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/commandline/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
42 changes: 42 additions & 0 deletions integration-cli/docker_cli_events_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"os/exec"
"strings"
"syscall"
"time"
"unicode"

Expand Down Expand Up @@ -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))
}

0 comments on commit 382c152

Please sign in to comment.