github.com/containers/podman/v4@v4.9.4/libpod/events/filters.go (about) 1 package events 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/containers/podman/v4/pkg/util" 9 ) 10 11 func generateEventFilter(filter, filterValue string) (func(e *Event) bool, error) { 12 switch strings.ToUpper(filter) { 13 case "CONTAINER": 14 return func(e *Event) bool { 15 if e.Type != Container { 16 return false 17 } 18 if e.Name == filterValue { 19 return true 20 } 21 return strings.HasPrefix(e.ID, filterValue) 22 }, nil 23 case "EVENT", "STATUS": 24 if filterValue == "die" { // Docker compat 25 filterValue = "died" 26 } 27 return func(e *Event) bool { 28 return string(e.Status) == filterValue 29 }, nil 30 case "IMAGE": 31 return func(e *Event) bool { 32 if e.Type != Image { 33 return false 34 } 35 if e.Name == filterValue { 36 return true 37 } 38 return strings.HasPrefix(e.ID, filterValue) 39 }, nil 40 case "POD": 41 return func(e *Event) bool { 42 if e.Type != Pod { 43 return false 44 } 45 if e.Name == filterValue { 46 return true 47 } 48 return strings.HasPrefix(e.ID, filterValue) 49 }, nil 50 case "VOLUME": 51 return func(e *Event) bool { 52 if e.Type != Volume { 53 return false 54 } 55 // Prefix match with name for consistency with docker 56 return strings.HasPrefix(e.Name, filterValue) 57 }, nil 58 case "TYPE": 59 return func(e *Event) bool { 60 return string(e.Type) == filterValue 61 }, nil 62 63 case "LABEL": 64 return func(e *Event) bool { 65 var found bool 66 // iterate labels and see if we match a key and value 67 for eventKey, eventValue := range e.Attributes { 68 filterValueSplit := strings.SplitN(filterValue, "=", 2) 69 // if the filter isn't right, just return false 70 if len(filterValueSplit) < 2 { 71 return false 72 } 73 if eventKey == filterValueSplit[0] && eventValue == filterValueSplit[1] { 74 found = true 75 break 76 } 77 } 78 return found 79 }, nil 80 } 81 return nil, fmt.Errorf("%s is an invalid filter", filter) 82 } 83 84 func generateEventSinceOption(timeSince time.Time) func(e *Event) bool { 85 return func(e *Event) bool { 86 return e.Time.After(timeSince) 87 } 88 } 89 90 func generateEventUntilOption(timeUntil time.Time) func(e *Event) bool { 91 return func(e *Event) bool { 92 return e.Time.Before(timeUntil) 93 } 94 } 95 96 func parseFilter(filter string) (string, string, error) { 97 filterSplit := strings.SplitN(filter, "=", 2) 98 if len(filterSplit) != 2 { 99 return "", "", fmt.Errorf("%s is an invalid filter", filter) 100 } 101 return filterSplit[0], filterSplit[1], nil 102 } 103 104 // applyFilters applies the EventFilter slices in sequence. Filters under the 105 // same key are disjunctive while each key must match (conjuctive). 106 func applyFilters(event *Event, filterMap map[string][]EventFilter) bool { 107 for _, filters := range filterMap { 108 success := false 109 for _, filter := range filters { 110 if filter(event) { 111 success = true 112 break 113 } 114 } 115 if !success { 116 return false 117 } 118 } 119 return true 120 } 121 122 // generateEventFilter parses the specified filters into a filter map that can 123 // later on be used to filter events. Keys are conjunctive, values are 124 // disjunctive. 125 func generateEventFilters(filters []string, since, until string) (map[string][]EventFilter, error) { 126 filterMap := make(map[string][]EventFilter) 127 for _, filter := range filters { 128 key, val, err := parseFilter(filter) 129 if err != nil { 130 return nil, err 131 } 132 filterFunc, err := generateEventFilter(key, val) 133 if err != nil { 134 return nil, err 135 } 136 filterSlice := filterMap[key] 137 filterSlice = append(filterSlice, filterFunc) 138 filterMap[key] = filterSlice 139 } 140 141 if len(since) > 0 { 142 timeSince, err := util.ParseInputTime(since, true) 143 if err != nil { 144 return nil, fmt.Errorf("unable to convert since time of %s: %w", since, err) 145 } 146 filterFunc := generateEventSinceOption(timeSince) 147 filterMap["since"] = []EventFilter{filterFunc} 148 } 149 150 if len(until) > 0 { 151 timeUntil, err := util.ParseInputTime(until, false) 152 if err != nil { 153 return nil, fmt.Errorf("unable to convert until time of %s: %w", until, err) 154 } 155 filterFunc := generateEventUntilOption(timeUntil) 156 filterMap["until"] = []EventFilter{filterFunc} 157 } 158 return filterMap, nil 159 }