filter.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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.matchScope(ev.Scope) &&
  20. ef.matchDaemon(ev) &&
  21. ef.matchContainer(ev) &&
  22. ef.matchPlugin(ev) &&
  23. ef.matchVolume(ev) &&
  24. ef.matchNetwork(ev) &&
  25. ef.matchImage(ev) &&
  26. ef.matchLabels(ev.Actor.Attributes)
  27. }
  28. func (ef *Filter) matchEvent(ev events.Message) bool {
  29. // #25798 if an event filter contains either health_status, exec_create or exec_start without a colon
  30. // Let's to a FuzzyMatch instead of an ExactMatch.
  31. if ef.filterContains("event", map[string]struct{}{"health_status": {}, "exec_create": {}, "exec_start": {}}) {
  32. return ef.filter.FuzzyMatch("event", ev.Action)
  33. }
  34. return ef.filter.ExactMatch("event", ev.Action)
  35. }
  36. func (ef *Filter) filterContains(field string, values map[string]struct{}) bool {
  37. for _, v := range ef.filter.Get(field) {
  38. if _, ok := values[v]; ok {
  39. return true
  40. }
  41. }
  42. return false
  43. }
  44. func (ef *Filter) matchScope(scope string) bool {
  45. if !ef.filter.Include("scope") {
  46. return true
  47. }
  48. return ef.filter.ExactMatch("scope", scope)
  49. }
  50. func (ef *Filter) matchLabels(attributes map[string]string) bool {
  51. if !ef.filter.Include("label") {
  52. return true
  53. }
  54. return ef.filter.MatchKVList("label", attributes)
  55. }
  56. func (ef *Filter) matchDaemon(ev events.Message) bool {
  57. return ef.fuzzyMatchName(ev, events.DaemonEventType)
  58. }
  59. func (ef *Filter) matchContainer(ev events.Message) bool {
  60. return ef.fuzzyMatchName(ev, events.ContainerEventType)
  61. }
  62. func (ef *Filter) matchPlugin(ev events.Message) bool {
  63. return ef.fuzzyMatchName(ev, events.PluginEventType)
  64. }
  65. func (ef *Filter) matchVolume(ev events.Message) bool {
  66. return ef.fuzzyMatchName(ev, events.VolumeEventType)
  67. }
  68. func (ef *Filter) matchNetwork(ev events.Message) bool {
  69. return ef.fuzzyMatchName(ev, events.NetworkEventType)
  70. }
  71. func (ef *Filter) matchService(ev events.Message) bool {
  72. return ef.fuzzyMatchName(ev, events.ServiceEventType)
  73. }
  74. func (ef *Filter) matchNode(ev events.Message) bool {
  75. return ef.fuzzyMatchName(ev, events.NodeEventType)
  76. }
  77. func (ef *Filter) matchSecret(ev events.Message) bool {
  78. return ef.fuzzyMatchName(ev, events.SecretEventType)
  79. }
  80. func (ef *Filter) fuzzyMatchName(ev events.Message, eventType string) bool {
  81. return ef.filter.FuzzyMatch(eventType, ev.Actor.ID) ||
  82. ef.filter.FuzzyMatch(eventType, ev.Actor.Attributes["name"])
  83. }
  84. // matchImage matches against both event.Actor.ID (for image events)
  85. // and event.Actor.Attributes["image"] (for container events), so that any container that was created
  86. // from an image will be included in the image events. Also compare both
  87. // against the stripped repo name without any tags.
  88. func (ef *Filter) matchImage(ev events.Message) bool {
  89. id := ev.Actor.ID
  90. nameAttr := "image"
  91. var imageName string
  92. if ev.Type == events.ImageEventType {
  93. nameAttr = "name"
  94. }
  95. if n, ok := ev.Actor.Attributes[nameAttr]; ok {
  96. imageName = n
  97. }
  98. return ef.filter.ExactMatch("image", id) ||
  99. ef.filter.ExactMatch("image", imageName) ||
  100. ef.filter.ExactMatch("image", stripTag(id)) ||
  101. ef.filter.ExactMatch("image", stripTag(imageName))
  102. }
  103. func stripTag(image string) string {
  104. ref, err := reference.ParseNormalizedNamed(image)
  105. if err != nil {
  106. return image
  107. }
  108. return reference.FamiliarName(ref)
  109. }