github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/api/handlers/compat/containers_top.go (about) 1 package compat 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "strings" 8 "time" 9 10 "github.com/hanks177/podman/v4/libpod" 11 "github.com/hanks177/podman/v4/pkg/api/handlers" 12 "github.com/hanks177/podman/v4/pkg/api/handlers/utils" 13 api "github.com/hanks177/podman/v4/pkg/api/types" 14 "github.com/gorilla/schema" 15 "github.com/pkg/errors" 16 "github.com/sirupsen/logrus" 17 ) 18 19 func TopContainer(w http.ResponseWriter, r *http.Request) { 20 runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) 21 decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) 22 23 psArgs := "-ef" 24 if utils.IsLibpodRequest(r) { 25 psArgs = "" 26 } 27 query := struct { 28 Delay int `schema:"delay"` 29 PsArgs string `schema:"ps_args"` 30 Stream bool `schema:"stream"` 31 }{ 32 Delay: 5, 33 PsArgs: psArgs, 34 } 35 if err := decoder.Decode(&query, r.URL.Query()); err != nil { 36 utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) 37 return 38 } 39 40 if query.Delay < 1 { 41 utils.Error(w, http.StatusBadRequest, fmt.Errorf("\"delay\" parameter of value %d < 1", query.Delay)) 42 return 43 } 44 45 name := utils.GetName(r) 46 c, err := runtime.LookupContainer(name) 47 if err != nil { 48 utils.ContainerNotFound(w, name, err) 49 return 50 } 51 52 // We are committed now - all errors logged but not reported to client, ship has sailed 53 w.WriteHeader(http.StatusOK) 54 w.Header().Set("Content-Type", "application/json") 55 if f, ok := w.(http.Flusher); ok { 56 f.Flush() 57 } 58 59 encoder := json.NewEncoder(w) 60 61 loop: // break out of for/select infinite` loop 62 for { 63 select { 64 case <-r.Context().Done(): 65 break loop 66 default: 67 output, err := c.Top([]string{query.PsArgs}) 68 if err != nil { 69 logrus.Infof("Error from %s %q : %v", r.Method, r.URL, err) 70 break loop 71 } 72 73 if len(output) > 0 { 74 body := handlers.ContainerTopOKBody{} 75 body.Titles = strings.Split(output[0], "\t") 76 for i := range body.Titles { 77 body.Titles[i] = strings.TrimSpace(body.Titles[i]) 78 } 79 80 for _, line := range output[1:] { 81 process := strings.Split(line, "\t") 82 for i := range process { 83 process[i] = strings.TrimSpace(process[i]) 84 } 85 body.Processes = append(body.Processes, process) 86 } 87 88 if err := encoder.Encode(body); err != nil { 89 logrus.Infof("Error from %s %q : %v", r.Method, r.URL, err) 90 break loop 91 } 92 if f, ok := w.(http.Flusher); ok { 93 f.Flush() 94 } 95 } 96 97 if query.Stream { 98 time.Sleep(time.Duration(query.Delay) * time.Second) 99 } else { 100 break loop 101 } 102 } 103 } 104 }