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