aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2020-10-21 11:59:35 -0500
committerbaude <bbaude@redhat.com>2020-10-23 12:07:34 -0500
commitc593e49701b3a4bb48050f3d8829f2fe6ac457ef (patch)
treef69648182082c37d4416efdb5405a9431984463c /libpod
parent51fa8ded9ffb7924288a2728ce92af7f6cc66d34 (diff)
downloadpodman-c593e49701b3a4bb48050f3d8829f2fe6ac457ef.tar.gz
podman-c593e49701b3a4bb48050f3d8829f2fe6ac457ef.tar.bz2
podman-c593e49701b3a4bb48050f3d8829f2fe6ac457ef.zip
filter events by labels
adding the ability to filter evens by the container labels. this requires that container labels be added to the events data being recorded and subsequently read. Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r--libpod/events.go6
-rw-r--r--libpod/events/config.go12
-rw-r--r--libpod/events/events.go9
-rw-r--r--libpod/events/filters.go20
-rw-r--r--libpod/events/journal_linux.go23
5 files changed, 68 insertions, 2 deletions
diff --git a/libpod/events.go b/libpod/events.go
index b519fe324..95317eb01 100644
--- a/libpod/events.go
+++ b/libpod/events.go
@@ -26,6 +26,12 @@ func (c *Container) newContainerEvent(status events.Status) {
e.Name = c.Name()
e.Image = c.config.RootfsImageName
e.Type = events.Container
+
+ e.Details = events.Details{
+ ID: e.ID,
+ Attributes: c.Labels(),
+ }
+
if err := c.runtime.eventer.Write(e); err != nil {
logrus.Errorf("unable to write pod event: %q", err)
}
diff --git a/libpod/events/config.go b/libpod/events/config.go
index bb35c03c0..2ec3111fe 100644
--- a/libpod/events/config.go
+++ b/libpod/events/config.go
@@ -36,6 +36,18 @@ type Event struct {
Time time.Time
// Type of event that occurred
Type Type
+
+ Details
+}
+
+// Details describes specifics about certain events, specifically around
+// container events
+type Details struct {
+ // ID is the event ID
+ ID string
+ // Attributes can be used to describe specifics about the event
+ // in the case of a container event, labels for example
+ Attributes map[string]string
}
// EventerOptions describe options that need to be passed to create
diff --git a/libpod/events/events.go b/libpod/events/events.go
index 722c9595e..42939d64c 100644
--- a/libpod/events/events.go
+++ b/libpod/events/events.go
@@ -69,7 +69,14 @@ func (e *Event) ToHumanReadable() string {
var humanFormat string
switch e.Type {
case Container, Pod:
- humanFormat = fmt.Sprintf("%s %s %s %s (image=%s, name=%s)", e.Time, e.Type, e.Status, e.ID, e.Image, e.Name)
+ humanFormat = fmt.Sprintf("%s %s %s %s (image=%s, name=%s", e.Time, e.Type, e.Status, e.ID, e.Image, e.Name)
+ // check if the container has labels and add it to the output
+ if len(e.Attributes) > 0 {
+ for k, v := range e.Attributes {
+ humanFormat += fmt.Sprintf(", %s=%s", k, v)
+ }
+ }
+ humanFormat += ")"
case Image:
humanFormat = fmt.Sprintf("%s %s %s %s %s", e.Time, e.Type, e.Status, e.ID, e.Name)
case System:
diff --git a/libpod/events/filters.go b/libpod/events/filters.go
index 171e2237f..62891d32c 100644
--- a/libpod/events/filters.go
+++ b/libpod/events/filters.go
@@ -55,6 +55,24 @@ func generateEventFilter(filter, filterValue string) (func(e *Event) bool, error
return func(e *Event) bool {
return string(e.Type) == filterValue
}, nil
+
+ case "LABEL":
+ return func(e *Event) bool {
+ var found bool
+ // iterate labels and see if we match a key and value
+ for eventKey, eventValue := range e.Attributes {
+ filterValueSplit := strings.SplitN(filterValue, "=", 2)
+ // if the filter isn't right, just return false
+ if len(filterValueSplit) < 2 {
+ return false
+ }
+ if eventKey == filterValueSplit[0] && eventValue == filterValueSplit[1] {
+ found = true
+ break
+ }
+ }
+ return found
+ }, nil
}
return nil, errors.Errorf("%s is an invalid filter", filter)
}
@@ -74,7 +92,7 @@ func generateEventUntilOption(timeUntil time.Time) func(e *Event) bool {
func parseFilter(filter string) (string, string, error) {
filterSplit := strings.SplitN(filter, "=", 2)
- if len(filterSplit) == 1 {
+ if len(filterSplit) != 2 {
return "", "", errors.Errorf("%s is an invalid filter", filter)
}
return filterSplit[0], filterSplit[1], nil
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index dc55dbc77..5d17a85b4 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -4,6 +4,7 @@ package events
import (
"context"
+ "encoding/json"
"strconv"
"time"
@@ -46,6 +47,15 @@ func (e EventJournalD) Write(ee Event) error {
if ee.ContainerExitCode != 0 {
m["PODMAN_EXIT_CODE"] = strconv.Itoa(ee.ContainerExitCode)
}
+ // If we have container labels, we need to convert them to a string so they
+ // can be recorded with the event
+ if len(ee.Details.Attributes) > 0 {
+ b, err := json.Marshal(ee.Details.Attributes)
+ if err != nil {
+ return err
+ }
+ m["PODMAN_LABELS"] = string(b)
+ }
case Volume:
m["PODMAN_NAME"] = ee.Name
}
@@ -174,6 +184,19 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) { /
newEvent.ContainerExitCode = intCode
}
}
+
+ // we need to check for the presence of labels recorded to a container event
+ if stringLabels, ok := entry.Fields["PODMAN_LABELS"]; ok && len(stringLabels) > 0 {
+ labels := make(map[string]string, 0)
+ if err := json.Unmarshal([]byte(stringLabels), &labels); err != nil {
+ return nil, err
+ }
+
+ // if we have labels, add them to the event
+ if len(labels) > 0 {
+ newEvent.Details = Details{Attributes: labels}
+ }
+ }
case Image:
newEvent.ID = entry.Fields["PODMAN_ID"]
}