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  }