Set correct exitcode in remove events and change ContainerExitCode from int to int ptr

Added additional check for event type to be remove and set the correct exitcode.
While it was getting difficult to maintain the omitempty notation for Event->ContainerExitCode, changing the type from int to int ptr gives us the ability to check for ContainerExitCode to be not nil and continue operations from there.

closes #19124

Signed-off-by: Chetan Giradkar <cgiradka@redhat.com>
This commit is contained in:
Chetan Giradkar 2023-11-06 15:44:57 +00:00
parent 720a0ead3a
commit 572f38c0db
11 changed files with 45 additions and 19 deletions

View File

@ -820,7 +820,7 @@ func (c *Container) exec(config *ExecConfig, streams *define.AttachStreams, resi
if err != nil { if err != nil {
return -1, fmt.Errorf("retrieving exec session %s exit code: %w", sessionID, err) return -1, fmt.Errorf("retrieving exec session %s exit code: %w", sessionID, err)
} }
return diedEvent.ContainerExitCode, nil return *diedEvent.ContainerExitCode, nil
} }
return -1, err return -1, err
} }

View File

@ -77,6 +77,14 @@ func (c *Container) newContainerEventWithInspectData(status events.Status, inspe
e.HealthStatus = containerHealthStatus e.HealthStatus = containerHealthStatus
} }
if status == events.Remove {
exitCode, err := c.runtime.state.GetContainerExitCode(c.ID())
if err == nil {
intExitCode := int(exitCode)
e.ContainerExitCode = &intExitCode
}
}
return c.runtime.eventer.Write(e) return c.runtime.eventer.Write(e)
} }
@ -88,7 +96,8 @@ func (c *Container) newContainerExitedEvent(exitCode int32) {
e.Image = c.config.RootfsImageName e.Image = c.config.RootfsImageName
e.Type = events.Container e.Type = events.Container
e.PodID = c.PodID() e.PodID = c.PodID()
e.ContainerExitCode = int(exitCode) intExitCode := int(exitCode)
e.ContainerExitCode = &intExitCode
e.Details = events.Details{ e.Details = events.Details{
ID: e.ID, ID: e.ID,
@ -107,7 +116,8 @@ func (c *Container) newExecDiedEvent(sessionID string, exitCode int) {
e.Name = c.Name() e.Name = c.Name()
e.Image = c.config.RootfsImageName e.Image = c.config.RootfsImageName
e.Type = events.Container e.Type = events.Container
e.ContainerExitCode = exitCode intExitCode := exitCode
e.ContainerExitCode = &intExitCode
e.Attributes = make(map[string]string) e.Attributes = make(map[string]string)
e.Attributes["execID"] = sessionID e.Attributes["execID"] = sessionID

View File

@ -24,7 +24,7 @@ const (
type Event struct { type Event struct {
// ContainerExitCode is for storing the exit code of a container which can // ContainerExitCode is for storing the exit code of a container which can
// be used for "internal" event notification // be used for "internal" event notification
ContainerExitCode int `json:",omitempty"` ContainerExitCode *int `json:",omitempty"`
// ID can be for the container, image, volume, etc // ID can be for the container, image, volume, etc
ID string `json:",omitempty"` ID string `json:",omitempty"`
// Image used where applicable // Image used where applicable

View File

@ -69,6 +69,9 @@ func (e *Event) ToJSONString() (string, error) {
// ToHumanReadable returns human-readable event as a formatted string // ToHumanReadable returns human-readable event as a formatted string
func (e *Event) ToHumanReadable(truncate bool) string { func (e *Event) ToHumanReadable(truncate bool) string {
if e == nil {
return ""
}
var humanFormat string var humanFormat string
id := e.ID id := e.ID
if truncate { if truncate {

View File

@ -48,8 +48,8 @@ func (e EventJournalD) Write(ee Event) error {
m["PODMAN_IMAGE"] = ee.Image m["PODMAN_IMAGE"] = ee.Image
m["PODMAN_NAME"] = ee.Name m["PODMAN_NAME"] = ee.Name
m["PODMAN_ID"] = ee.ID m["PODMAN_ID"] = ee.ID
if ee.ContainerExitCode != 0 { if ee.ContainerExitCode != nil {
m["PODMAN_EXIT_CODE"] = strconv.Itoa(ee.ContainerExitCode) m["PODMAN_EXIT_CODE"] = strconv.Itoa(*ee.ContainerExitCode)
} }
if ee.PodID != "" { if ee.PodID != "" {
m["PODMAN_POD_ID"] = ee.PodID m["PODMAN_POD_ID"] = ee.PodID
@ -206,7 +206,7 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) {
if err != nil { if err != nil {
logrus.Errorf("Parsing event exit code %s", code) logrus.Errorf("Parsing event exit code %s", code)
} else { } else {
newEvent.ContainerExitCode = intCode newEvent.ContainerExitCode = &intCode
} }
} }

View File

@ -934,8 +934,7 @@ func (s *SQLiteState) GetContainerExitCode(id string) (int32, error) {
} }
row := s.conn.QueryRow("SELECT ExitCode FROM ContainerExitCode WHERE ID=?;", id) row := s.conn.QueryRow("SELECT ExitCode FROM ContainerExitCode WHERE ID=?;", id)
var exitCode int32 = -1
var exitCode int32
if err := row.Scan(&exitCode); err != nil { if err := row.Scan(&exitCode); err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
return -1, fmt.Errorf("getting exit code of container %s from DB: %w", id, define.ErrNoSuchExitCode) return -1, fmt.Errorf("getting exit code of container %s from DB: %w", id, define.ErrNoSuchExitCode)

View File

@ -238,7 +238,10 @@ func waitNextExit(ctx context.Context, containerName string) (int32, error) {
evt, ok := <-eventChannel evt, ok := <-eventChannel
if ok { if ok {
return int32(evt.ContainerExitCode), nil if evt.ContainerExitCode != nil {
return int32(*evt.ContainerExitCode), nil
}
return -1, nil
} }
// if ok == false then containerEngine.Events() has exited // if ok == false then containerEngine.Events() has exited
// it may happen if request was canceled (e.g. client closed connection prematurely) or // it may happen if request was canceled (e.g. client closed connection prematurely) or

View File

@ -19,9 +19,13 @@ type Event struct {
// ConvertToLibpodEvent converts an entities event to a libpod one. // ConvertToLibpodEvent converts an entities event to a libpod one.
func ConvertToLibpodEvent(e Event) *libpodEvents.Event { func ConvertToLibpodEvent(e Event) *libpodEvents.Event {
exitCode, err := strconv.Atoi(e.Actor.Attributes["containerExitCode"]) var exitCode int
if err != nil { if ec, ok := e.Actor.Attributes["containerExitCode"]; ok {
return nil var err error
exitCode, err = strconv.Atoi(ec)
if err != nil {
return nil
}
} }
status, err := libpodEvents.StringToStatus(e.Action) status, err := libpodEvents.StringToStatus(e.Action)
if err != nil { if err != nil {
@ -39,7 +43,7 @@ func ConvertToLibpodEvent(e Event) *libpodEvents.Event {
delete(details, "name") delete(details, "name")
delete(details, "containerExitCode") delete(details, "containerExitCode")
return &libpodEvents.Event{ return &libpodEvents.Event{
ContainerExitCode: exitCode, ContainerExitCode: &exitCode,
ID: e.Actor.ID, ID: e.Actor.ID,
Image: image, Image: image,
Name: name, Name: name,
@ -62,7 +66,9 @@ func ConvertToEntitiesEvent(e libpodEvents.Event) *Event {
} }
attributes["image"] = e.Image attributes["image"] = e.Image
attributes["name"] = e.Name attributes["name"] = e.Name
attributes["containerExitCode"] = strconv.Itoa(e.ContainerExitCode) if e.ContainerExitCode != nil {
attributes["containerExitCode"] = strconv.Itoa(*e.ContainerExitCode)
}
attributes["podId"] = e.PodID attributes["podId"] = e.PodID
message := dockerEvents.Message{ message := dockerEvents.Message{
// Compatibility with clients that still look for deprecated API elements // Compatibility with clients that still look for deprecated API elements

View File

@ -1192,7 +1192,8 @@ func (ic *ContainerEngine) GetContainerExitCode(ctx context.Context, ctr *libpod
exitCode, err := ctr.Wait(ctx) exitCode, err := ctr.Wait(ctx)
if err != nil { if err != nil {
logrus.Errorf("Waiting for container %s: %v", ctr.ID(), err) logrus.Errorf("Waiting for container %s: %v", ctr.ID(), err)
return define.ExecErrorCodeNotFound intExitCode := int(define.ExecErrorCodeNotFound)
return intExitCode
} }
return int(exitCode) return int(exitCode)
} }

View File

@ -773,7 +773,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
logrus.Errorf("Cannot get exit code: %v", err) logrus.Errorf("Cannot get exit code: %v", err)
report.ExitCode = define.ExecErrorCodeNotFound report.ExitCode = define.ExecErrorCodeNotFound
} else { } else {
report.ExitCode = event.ContainerExitCode report.ExitCode = *event.ContainerExitCode
} }
} else { } else {
report.ExitCode = int(exitCode) report.ExitCode = int(exitCode)
@ -962,7 +962,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
return &report, nil //nolint: nilerr return &report, nil //nolint: nilerr
} }
report.ExitCode = lastEvent.ContainerExitCode report.ExitCode = *lastEvent.ContainerExitCode
return &report, err return &report, err
} }

View File

@ -10,7 +10,7 @@ podman rm -a -f &>/dev/null
START=$(date +%s) START=$(date +%s)
podman run $IMAGE false || true podman run --rm $IMAGE false || true
# libpod api # libpod api
t GET "libpod/events?stream=false&since=$START" 200 \ t GET "libpod/events?stream=false&since=$START" 200 \
@ -28,4 +28,8 @@ t GET "events?stream=false&since=$START" 200 \
'select(.status | contains("die")).Action=die' \ 'select(.status | contains("die")).Action=die' \
'select(.status | contains("die")).Actor.Attributes.exitCode=1' 'select(.status | contains("die")).Actor.Attributes.exitCode=1'
t GET "events?stream=false&since=$START&type=remove" 200 \
'select(.status| contains("remove")).Action=remove' \
'select(.status | contains("remove")).Actor.Attributes.containerExitCode=1'
# vim: filetype=sh # vim: filetype=sh