mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add filter for events emitted by docker daemon
This fix tries to cover the issue raised in #22463 by adding filter for events emitted by docker daemon so that user could utilize filter to receive events of interest. Documentations have been updated for this fix. Additional tests have been added to cover the changes in this fix. This fix fixes #22463. Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
parent
382c152a73
commit
62014aaf9a
7 changed files with 74 additions and 6 deletions
|
@ -1393,6 +1393,8 @@ func (daemon *Daemon) Reload(config *Config) error {
|
||||||
} else {
|
} else {
|
||||||
attributes["labels"] = "[]"
|
attributes["labels"] = "[]"
|
||||||
}
|
}
|
||||||
|
attributes["max-concurrent-downloads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentDownloads)
|
||||||
|
attributes["max-concurrent-uploads"] = fmt.Sprintf("%d", *daemon.configStore.MaxConcurrentUploads)
|
||||||
daemon.LogDaemonEventWithAttributes("reload", attributes)
|
daemon.LogDaemonEventWithAttributes("reload", attributes)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -83,6 +83,9 @@ func (daemon *Daemon) LogNetworkEventWithAttributes(nw libnetwork.Network, actio
|
||||||
// LogDaemonEventWithAttributes generates an event related to the daemon itself with specific given attributes.
|
// LogDaemonEventWithAttributes generates an event related to the daemon itself with specific given attributes.
|
||||||
func (daemon *Daemon) LogDaemonEventWithAttributes(action string, attributes map[string]string) {
|
func (daemon *Daemon) LogDaemonEventWithAttributes(action string, attributes map[string]string) {
|
||||||
if daemon.EventsService != nil {
|
if daemon.EventsService != nil {
|
||||||
|
if info, err := daemon.SystemInfo(); err == nil && info.Name != "" {
|
||||||
|
attributes["name"] = info.Name
|
||||||
|
}
|
||||||
actor := events.Actor{
|
actor := events.Actor{
|
||||||
ID: daemon.ID,
|
ID: daemon.ID,
|
||||||
Attributes: attributes,
|
Attributes: attributes,
|
||||||
|
|
|
@ -20,6 +20,7 @@ func NewFilter(filter filters.Args) *Filter {
|
||||||
func (ef *Filter) Include(ev events.Message) bool {
|
func (ef *Filter) Include(ev events.Message) bool {
|
||||||
return ef.filter.ExactMatch("event", ev.Action) &&
|
return ef.filter.ExactMatch("event", ev.Action) &&
|
||||||
ef.filter.ExactMatch("type", ev.Type) &&
|
ef.filter.ExactMatch("type", ev.Type) &&
|
||||||
|
ef.matchDaemon(ev) &&
|
||||||
ef.matchContainer(ev) &&
|
ef.matchContainer(ev) &&
|
||||||
ef.matchVolume(ev) &&
|
ef.matchVolume(ev) &&
|
||||||
ef.matchNetwork(ev) &&
|
ef.matchNetwork(ev) &&
|
||||||
|
@ -34,6 +35,10 @@ func (ef *Filter) matchLabels(attributes map[string]string) bool {
|
||||||
return ef.filter.MatchKVList("label", attributes)
|
return ef.filter.MatchKVList("label", attributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ef *Filter) matchDaemon(ev events.Message) bool {
|
||||||
|
return ef.fuzzyMatchName(ev, events.DaemonEventType)
|
||||||
|
}
|
||||||
|
|
||||||
func (ef *Filter) matchContainer(ev events.Message) bool {
|
func (ef *Filter) matchContainer(ev events.Message) bool {
|
||||||
return ef.fuzzyMatchName(ev, events.ContainerEventType)
|
return ef.fuzzyMatchName(ev, events.ContainerEventType)
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,8 @@ This section lists each version from latest to oldest. Each listing includes a
|
||||||
* `POST /containers/create` now returns a HTTP 400 "bad parameter" message
|
* `POST /containers/create` now returns a HTTP 400 "bad parameter" message
|
||||||
if no command is specified (instead of a HTTP 500 "server error")
|
if no command is specified (instead of a HTTP 500 "server error")
|
||||||
* `GET /images/search` now takes a `filters` query parameter.
|
* `GET /images/search` now takes a `filters` query parameter.
|
||||||
* `GET /events` now supports daemon events of `reload`.
|
* `GET /events` now supports a `reload` event that is emitted when the daemon configuration is reloaded.
|
||||||
|
* `GET /events` now supports filtering by daemon name or ID.
|
||||||
|
|
||||||
### v1.23 API changes
|
### v1.23 API changes
|
||||||
|
|
||||||
|
|
|
@ -2593,9 +2593,10 @@ Query Parameters:
|
||||||
- `event=<string>`; -- event to filter
|
- `event=<string>`; -- event to filter
|
||||||
- `image=<string>`; -- image to filter
|
- `image=<string>`; -- image to filter
|
||||||
- `label=<string>`; -- image and container label to filter
|
- `label=<string>`; -- image and container label to filter
|
||||||
- `type=<string>`; -- either `container` or `image` or `volume` or `network`
|
- `type=<string>`; -- either `container` or `image` or `volume` or `network` or `daemon`
|
||||||
- `volume=<string>`; -- volume to filter
|
- `volume=<string>`; -- volume to filter
|
||||||
- `network=<string>`; -- network to filter
|
- `network=<string>`; -- network to filter
|
||||||
|
- `daemon=<string>`; -- daemon name or id to filter
|
||||||
|
|
||||||
Status Codes:
|
Status Codes:
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,10 @@ The currently supported filters are:
|
||||||
* event (`event=<event action>`)
|
* event (`event=<event action>`)
|
||||||
* image (`image=<tag or id>`)
|
* image (`image=<tag or id>`)
|
||||||
* label (`label=<key>` or `label=<key>=<value>`)
|
* label (`label=<key>` or `label=<key>=<value>`)
|
||||||
* type (`type=<container or image or volume or network>`)
|
* type (`type=<container or image or volume or network or daemon>`)
|
||||||
* volume (`volume=<name or id>`)
|
* volume (`volume=<name or id>`)
|
||||||
* network (`network=<name or id>`)
|
* network (`network=<name or id>`)
|
||||||
|
* daemon (`daemon=<name or id>`)
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|
|
@ -386,17 +386,19 @@ func (s *DockerDaemonSuite) TestDaemonEvents(c *check.C) {
|
||||||
out, err := s.d.Cmd("info")
|
out, err := s.d.Cmd("info")
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
daemonID := ""
|
daemonID := ""
|
||||||
|
daemonName := ""
|
||||||
for _, line := range strings.Split(out, "\n") {
|
for _, line := range strings.Split(out, "\n") {
|
||||||
if strings.HasPrefix(line, "ID: ") {
|
if strings.HasPrefix(line, "ID: ") {
|
||||||
daemonID = strings.TrimPrefix(line, "ID: ")
|
daemonID = strings.TrimPrefix(line, "ID: ")
|
||||||
break
|
} else if strings.HasPrefix(line, "Name: ") {
|
||||||
|
daemonName = strings.TrimPrefix(line, "Name: ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.Assert(daemonID, checker.Not(checker.Equals), "")
|
c.Assert(daemonID, checker.Not(checker.Equals), "")
|
||||||
|
|
||||||
configFile, err = os.Create(configFilePath)
|
configFile, err = os.Create(configFilePath)
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
daemonConfig = `{"labels":["bar=foo"]}`
|
daemonConfig = `{"max-concurrent-downloads":1,"labels":["bar=foo"]}`
|
||||||
fmt.Fprintf(configFile, "%s", daemonConfig)
|
fmt.Fprintf(configFile, "%s", daemonConfig)
|
||||||
configFile.Close()
|
configFile.Close()
|
||||||
|
|
||||||
|
@ -406,5 +408,58 @@ func (s *DockerDaemonSuite) TestDaemonEvents(c *check.C) {
|
||||||
|
|
||||||
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c))
|
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c))
|
||||||
c.Assert(err, checker.IsNil)
|
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))
|
c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s (cluster-advertise=, cluster-store=, cluster-store-opts={}, debug=true, labels=[\"bar=foo\"], max-concurrent-downloads=1, max-concurrent-uploads=5, name=%s)", daemonID, daemonName))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DockerDaemonSuite) TestDaemonEventsWithFilters(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 := ""
|
||||||
|
daemonName := ""
|
||||||
|
for _, line := range strings.Split(out, "\n") {
|
||||||
|
if strings.HasPrefix(line, "ID: ") {
|
||||||
|
daemonID = strings.TrimPrefix(line, "ID: ")
|
||||||
|
} else if strings.HasPrefix(line, "Name: ") {
|
||||||
|
daemonName = strings.TrimPrefix(line, "Name: ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Assert(daemonID, checker.Not(checker.Equals), "")
|
||||||
|
|
||||||
|
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), "--filter", fmt.Sprintf("daemon=%s", daemonID))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s", daemonID))
|
||||||
|
|
||||||
|
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("daemon=%s", daemonName))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s", daemonID))
|
||||||
|
|
||||||
|
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", "daemon=foo")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(out, checker.Not(checker.Contains), fmt.Sprintf("daemon reload %s", daemonID))
|
||||||
|
|
||||||
|
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", "type=daemon")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s", daemonID))
|
||||||
|
|
||||||
|
out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", "type=container")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(out, checker.Not(checker.Contains), fmt.Sprintf("daemon reload %s", daemonID))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue