mirror of
https://github.com/containers/podman.git
synced 2025-08-06 19:44:14 +08:00

Fix a bug in remote events where only one event would be sent if when streaming is turned off. The source of the bug was that the handler attempted to implement the streaming logic and did it wrong. The fix is rather simple by removing this logic from the handler and let the events backend handle streaming. Fixes: #10529 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
105 lines
2.7 KiB
Go
105 lines
2.7 KiB
Go
package compat
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/containers/podman/v3/libpod"
|
|
"github.com/containers/podman/v3/libpod/events"
|
|
"github.com/containers/podman/v3/pkg/api/handlers/utils"
|
|
"github.com/containers/podman/v3/pkg/domain/entities"
|
|
"github.com/containers/podman/v3/pkg/util"
|
|
"github.com/gorilla/schema"
|
|
jsoniter "github.com/json-iterator/go"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// NOTE: this endpoint serves both the docker-compatible one and the new libpod
|
|
// one.
|
|
func GetEvents(w http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
fromStart bool
|
|
decoder = r.Context().Value("decoder").(*schema.Decoder)
|
|
runtime = r.Context().Value("runtime").(*libpod.Runtime)
|
|
json = jsoniter.ConfigCompatibleWithStandardLibrary // FIXME: this should happen on the package level
|
|
)
|
|
|
|
// NOTE: the "filters" parameter is extracted separately for backwards
|
|
// compat via `filterFromRequest()`.
|
|
query := struct {
|
|
Since string `schema:"since"`
|
|
Until string `schema:"until"`
|
|
Stream bool `schema:"stream"`
|
|
}{
|
|
Stream: true,
|
|
}
|
|
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
|
|
utils.Error(w, "failed to parse parameters", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
|
|
return
|
|
}
|
|
|
|
if len(query.Since) > 0 || len(query.Until) > 0 {
|
|
fromStart = true
|
|
}
|
|
|
|
libpodFilters, err := util.FiltersFromRequest(r)
|
|
if err != nil {
|
|
utils.Error(w, "failed to parse parameters", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
|
|
return
|
|
}
|
|
eventChannel := make(chan *events.Event)
|
|
errorChannel := make(chan error)
|
|
|
|
// Start reading events.
|
|
go func() {
|
|
readOpts := events.ReadOptions{
|
|
FromStart: fromStart,
|
|
Stream: query.Stream,
|
|
Filters: libpodFilters,
|
|
EventChannel: eventChannel,
|
|
Since: query.Since,
|
|
Until: query.Until,
|
|
}
|
|
errorChannel <- runtime.Events(r.Context(), readOpts)
|
|
}()
|
|
|
|
var flush = func() {}
|
|
if flusher, ok := w.(http.Flusher); ok {
|
|
flush = flusher.Flush
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
flush()
|
|
|
|
coder := json.NewEncoder(w)
|
|
coder.SetEscapeHTML(true)
|
|
|
|
for {
|
|
select {
|
|
case err := <-errorChannel:
|
|
if err != nil {
|
|
// FIXME StatusOK already sent above cannot send 500 here
|
|
utils.InternalServerError(w, err)
|
|
}
|
|
return
|
|
case evt := <-eventChannel:
|
|
if evt == nil {
|
|
continue
|
|
}
|
|
|
|
e := entities.ConvertToEntitiesEvent(*evt)
|
|
if !utils.IsLibpodRequest(r) && e.Status == "died" {
|
|
e.Status = "die"
|
|
}
|
|
|
|
if err := coder.Encode(e); err != nil {
|
|
logrus.Errorf("unable to write json: %q", err)
|
|
}
|
|
flush()
|
|
case <-r.Context().Done():
|
|
return
|
|
}
|
|
}
|
|
}
|