filter.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package events
  2. import (
  3. "github.com/docker/distribution/reference"
  4. "github.com/docker/docker/api/types/events"
  5. "github.com/docker/docker/api/types/filters"
  6. )
  7. // Filter can filter out docker events from a stream
  8. type Filter struct {
  9. filter filters.Args
  10. }
  11. // NewFilter creates a new Filter
  12. func NewFilter(filter filters.Args) *Filter {
  13. return &Filter{filter: filter}
  14. }
  15. // Include returns true when the event ev is included by the filters
  16. func (ef *Filter) Include(ev events.Message) bool {
  17. return ef.matchEvent(ev) &&
  18. ef.filter.ExactMatch("type", ev.Type) &&
  19. ef.matchDaemon(ev) &&
  20. ef.matchContainer(ev) &&
  21. ef.matchPlugin(ev) &&
  22. ef.matchVolume(ev) &&
  23. ef.matchNetwork(ev) &&
  24. ef.matchImage(ev) &&
  25. ef.matchLabels(ev.Actor.Attributes)
  26. }
  27. func (ef *Filter) matchEvent(ev events.Message) bool {
  28. // #25798 if an event filter contains either health_status, exec_create or exec_start without a colon
  29. // Let's to a FuzzyMatch instead of an ExactMatch.
  30. if ef.filterContains("event", map[string]struct{}{"health_status": {}, "exec_create": {}, "exec_start": {}}) {
  31. return ef.filter.FuzzyMatch("event", ev.Action)
  32. }
  33. return ef.filter.ExactMatch("event", ev.Action)
  34. }
  35. func (ef *Filter) filterContains(field string, values map[string]struct{}) bool {
  36. for _, v := range ef.filter.Get(field) {
  37. if _, ok := values[v]; ok {
  38. return true
  39. }
  40. }
  41. return false
  42. }
  43. func (ef *Filter) matchLabels(attributes map[string]string) bool {
  44. if !ef.filter.Include("label") {
  45. return true
  46. }
  47. return ef.filter.MatchKVList("label", attributes)
  48. }
  49. func (ef *Filter) matchDaemon(ev events.Message) bool {
  50. return ef.fuzzyMatchName(ev, events.DaemonEventType)
  51. }
  52. func (ef *Filter) matchContainer(ev events.Message) bool {
  53. return ef.fuzzyMatchName(ev, events.ContainerEventType)
  54. }
  55. func (ef *Filter) matchPlugin(ev events.Message) bool {
  56. return ef.fuzzyMatchName(ev, events.PluginEventType)
  57. }
  58. func (ef *Filter) matchVolume(ev events.Message) bool {
  59. return ef.fuzzyMatchName(ev, events.VolumeEventType)
  60. }
  61. func (ef *Filter) matchNetwork(ev events.Message) bool {
  62. return ef.fuzzyMatchName(ev, events.NetworkEventType)
  63. }
  64. func (ef *Filter) fuzzyMatchName(ev events.Message, eventType string) bool {
  65. return ef.filter.FuzzyMatch(eventType, ev.Actor.ID) ||
  66. ef.filter.FuzzyMatch(eventType, ev.Actor.Attributes["name"])
  67. }
  68. // matchImage matches against both event.Actor.ID (for image events)
  69. // and event.Actor.Attributes["image"] (for container events), so that any container that was created
  70. // from an image will be included in the image events. Also compare both
  71. // against the stripped repo name without any tags.
  72. func (ef *Filter) matchImage(ev events.Message) bool {
  73. id := ev.Actor.ID
  74. nameAttr := "image"
  75. var imageName string
  76. if ev.Type == events.ImageEventType {
  77. nameAttr = "name"
  78. }
  79. if n, ok := ev.Actor.Attributes[nameAttr]; ok {
  80. imageName = n
  81. }
  82. return ef.filter.ExactMatch("image", id) ||
  83. ef.filter.ExactMatch("image", imageName) ||
  84. ef.filter.ExactMatch("image", stripTag(id)) ||
  85. ef.filter.ExactMatch("image", stripTag(imageName))
  86. }
  87. func stripTag(image string) string {
  88. ref, err := reference.ParseNormalizedNamed(image)
  89. if err != nil {
  90. return image
  91. }
  92. return reference.FamiliarName(ref)
  93. }