Skip to content

Commit

Permalink
Merge pull request #8103 from baude/eventlabels
Browse files Browse the repository at this point in the history
filter events by labels
  • Loading branch information
openshift-merge-robot authored Oct 23, 2020
2 parents 51fa8de + c593e49 commit 050dcad
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/source/markdown/podman-events.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ filters are supported:
* container=name_or_id
* event=event_status (described above)
* image=name_or_id
* label=key=value
* pod=name_or_id
* volume=name_or_id
* type=event_type (described above)
Expand Down
6 changes: 6 additions & 0 deletions libpod/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
12 changes: 12 additions & 0 deletions libpod/events/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 8 additions & 1 deletion libpod/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
20 changes: 19 additions & 1 deletion libpod/events/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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
Expand Down
23 changes: 23 additions & 0 deletions libpod/events/journal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package events

import (
"context"
"encoding/json"
"strconv"
"time"

Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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"]
}
Expand Down
14 changes: 14 additions & 0 deletions test/system/090-events.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bats -*- bats -*-
#
# tests for podman events functionality
#

load helpers

@test "events with a filter by label" {
skip_if_remote "Need to talk to Ed on why this is failing on remote"
rand=$(random_string 30)
run_podman 0 run --label foo=bar --name test-$rand --rm $IMAGE ls
run_podman 0 events --filter type=container --filter container=test-$rand --filter label=foo=bar --filter event=start --stream=false
is "$output" ".*foo=bar" "check for label event on container with label"
}

0 comments on commit 050dcad

Please sign in to comment.