filter.go 3.9 KB

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