Skip to content

Commit

Permalink
Events for containers in pods now include the pod's ID
Browse files Browse the repository at this point in the history
This allows tools like Cockpit to know that the pod in question
has also been updated, so they can refresh the list of containers
in the pod.

Fixes #15408

Signed-off-by: Matthew Heon <[email protected]>
  • Loading branch information
mheon committed Sep 22, 2022
1 parent 0899351 commit 6ee5823
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 5 deletions.
2 changes: 2 additions & 0 deletions libpod/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func (c *Container) newContainerEvent(status events.Status) {

e.Details = events.Details{
ID: e.ID,
PodID: c.PodID(),
Attributes: c.Labels(),
}

Expand All @@ -59,6 +60,7 @@ func (c *Container) newContainerExitedEvent(exitCode int32) {
e.Name = c.Name()
e.Image = c.config.RootfsImageName
e.Type = events.Container
e.PodID = c.PodID()
e.ContainerExitCode = int(exitCode)

e.Details = events.Details{
Expand Down
2 changes: 2 additions & 0 deletions libpod/events/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type Event struct {
type Details struct {
// ID is the event ID
ID string
// PodID is the ID of the pod associated with the container.
PodID string `json:",omitempty"`
// Attributes can be used to describe specifics about the event
// in the case of a container event, labels for example
Attributes map[string]string
Expand Down
8 changes: 7 additions & 1 deletion libpod/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,13 @@ func (e *Event) ToHumanReadable(truncate bool) string {
}
switch e.Type {
case Container, Pod:
humanFormat = fmt.Sprintf("%s %s %s %s (image=%s, name=%s, health_status=%s", e.Time, e.Type, e.Status, id, e.Image, e.Name, e.HealthStatus)
humanFormat = fmt.Sprintf("%s %s %s %s (image=%s, name=%s", e.Time, e.Type, e.Status, id, e.Image, e.Name)
if e.PodID != "" {
humanFormat += fmt.Sprintf(", pod_id=%s", e.PodID)
}
if e.HealthStatus != "" {
humanFormat += fmt.Sprintf(", health_status=%s", e.HealthStatus)
}
// check if the container has labels and add it to the output
if len(e.Attributes) > 0 {
for k, v := range e.Attributes {
Expand Down
6 changes: 5 additions & 1 deletion libpod/events/journal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ func (e EventJournalD) Write(ee Event) error {
if ee.ContainerExitCode != 0 {
m["PODMAN_EXIT_CODE"] = strconv.Itoa(ee.ContainerExitCode)
}
if ee.PodID != "" {
m["PODMAN_POD_ID"] = ee.PodID
}
// 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 {
Expand Down Expand Up @@ -161,6 +164,7 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) {
case Container, Pod:
newEvent.ID = entry.Fields["PODMAN_ID"]
newEvent.Image = entry.Fields["PODMAN_IMAGE"]
newEvent.PodID = entry.Fields["PODMAN_POD_ID"]
if code, ok := entry.Fields["PODMAN_EXIT_CODE"]; ok {
intCode, err := strconv.Atoi(code)
if err != nil {
Expand All @@ -179,7 +183,7 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) {

// if we have labels, add them to the event
if len(labels) > 0 {
newEvent.Details = Details{Attributes: labels}
newEvent.Attributes = labels
}
}
newEvent.HealthStatus = entry.Fields["PODMAN_HEALTH_STATUS"]
Expand Down
5 changes: 4 additions & 1 deletion pkg/domain/entities/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Event struct {
// TODO: it would be nice to have full control over the types at some
// point and fork such Docker types.
dockerEvents.Message
HealthStatus string
HealthStatus string `json:",omitempty"`
}

// ConvertToLibpodEvent converts an entities event to a libpod one.
Expand All @@ -34,6 +34,7 @@ func ConvertToLibpodEvent(e Event) *libpodEvents.Event {
image := e.Actor.Attributes["image"]
name := e.Actor.Attributes["name"]
details := e.Actor.Attributes
podID := e.Actor.Attributes["podId"]
delete(details, "image")
delete(details, "name")
delete(details, "containerExitCode")
Expand All @@ -47,6 +48,7 @@ func ConvertToLibpodEvent(e Event) *libpodEvents.Event {
Type: t,
HealthStatus: e.HealthStatus,
Details: libpodEvents.Details{
PodID: podID,
Attributes: details,
},
}
Expand All @@ -61,6 +63,7 @@ func ConvertToEntitiesEvent(e libpodEvents.Event) *Event {
attributes["image"] = e.Image
attributes["name"] = e.Name
attributes["containerExitCode"] = strconv.Itoa(e.ContainerExitCode)
attributes["podId"] = e.PodID
message := dockerEvents.Message{
// Compatibility with clients that still look for deprecated API elements
Status: e.Status.String(),
Expand Down
2 changes: 1 addition & 1 deletion test/apiv2/27-containersEvents.at
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ t GET "libpod/events?stream=false&since=$START" 200 \

t GET "libpod/events?stream=false&since=$START" 200 \
'select(.status | contains("start")).Action=start' \
'select(.status | contains("start")).HealthStatus='\
'select(.status | contains("start")).HealthStatus=null'\

# compat api, uses status=die (#12643)
t GET "events?stream=false&since=$START" 200 \
Expand Down
12 changes: 11 additions & 1 deletion test/e2e/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ var _ = Describe("Podman events", func() {
Expect(result).Should(Exit(0))
Expect(result.OutputToStringArray()).To(HaveLen(1))
Expect(result.OutputToString()).To(ContainSubstring("create"))

ctrName := "testCtr"
run := podmanTest.Podman([]string{"create", "--pod", id, "--name", ctrName, ALPINE, "top"})
run.WaitWithDefaultTimeout()
Expect(run).Should(Exit(0))

result2 := podmanTest.Podman([]string{"events", "--stream=false", "--filter", fmt.Sprintf("container=%s", ctrName), "--since", "30s"})
result2.WaitWithDefaultTimeout()
Expect(result2).Should(Exit(0))
Expect(result2.OutputToString()).To(ContainSubstring(fmt.Sprintf("pod_id=%s", id)))
})

It("podman events health_status generated", func() {
Expand All @@ -229,7 +239,7 @@ var _ = Describe("Podman events", func() {
time.Sleep(1 * time.Second)
}

result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=health_status"})
result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=health_status", "--since", "1m"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(len(result.OutputToStringArray())).To(BeNumerically(">=", 1), "Number of health_status events")
Expand Down

0 comments on commit 6ee5823

Please sign in to comment.