diff --git a/oci/oci.go b/oci/oci.go index 476a61a6..e6033865 100644 --- a/oci/oci.go +++ b/oci/oci.go @@ -4,9 +4,11 @@ import ( "bytes" "encoding/json" "fmt" + "io/ioutil" "os" "os/exec" "path/filepath" + "strconv" "strings" "sync" "syscall" @@ -150,6 +152,27 @@ func (r *Runtime) UpdateStatus(c *Container) error { if err := json.NewDecoder(stateReader).Decode(&c.state); err != nil { return fmt.Errorf("failed to decode container status for %s: %s", c.name, err) } + + if c.state.Status == "stopped" { + exitFilePath := filepath.Join(c.bundlePath, "exit") + fi, err := os.Stat(exitFilePath) + if err != nil { + return fmt.Errorf("failed to find container exit file: %v", err) + } + st := fi.Sys().(*syscall.Stat_t) + c.state.Finished = time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec)) + + statusCodeStr, err := ioutil.ReadFile(exitFilePath) + if err != nil { + return fmt.Errorf("failed to read exit file: %v", err) + } + statusCode, err := strconv.Atoi(string(statusCodeStr)) + if err != nil { + return fmt.Errorf("status code conversion failed: %v", err) + } + c.state.ExitCode = int32(statusCode) + } + return nil } @@ -175,8 +198,10 @@ type Container struct { // ContainerStatus represents the status of a container. type ContainerState struct { specs.State - Created time.Time `json:"created"` - Started time.Time `json:"started"` + Created time.Time `json:"created"` + Started time.Time `json:"started"` + Finished time.Time `json:"finished"` + ExitCode int32 `json:"exitCode"` } // NewContainer creates a container object. diff --git a/server/runtime.go b/server/runtime.go index fd827392..a18d99a7 100644 --- a/server/runtime.go +++ b/server/runtime.go @@ -248,6 +248,10 @@ func int64Ptr(i int64) *int64 { return &i } +func int32Ptr(i int32) *int32 { + return &i +} + func sPtr(s string) *string { return &s } @@ -668,12 +672,14 @@ func (s *Server) ContainerStatus(ctx context.Context, req *pb.ContainerStatusReq started := cState.Started.Unix() csr.Status.StartedAt = int64Ptr(started) case "stopped": - // TODO: Get the exit time rStatus = pb.ContainerState_EXITED created := cState.Created.Unix() csr.Status.CreatedAt = int64Ptr(created) started := cState.Started.Unix() csr.Status.StartedAt = int64Ptr(started) + finished := cState.Finished.Unix() + csr.Status.FinishedAt = int64Ptr(finished) + csr.Status.ExitCode = int32Ptr(cState.ExitCode) } csr.Status.State = &rStatus