apiv2 stream events

the events endpoint should be stream-based.  it also needed to be registered to answer and not produce 404s.

Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
Brent Baude
2020-02-11 15:00:41 -06:00
parent 86b5a89d1a
commit 5b830cca90
4 changed files with 34 additions and 16 deletions

View File

@ -1,19 +1,24 @@
package handlers
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
func GetEvents(w http.ResponseWriter, r *http.Request) {
var (
fromStart bool
eventsError error
)
query := struct {
Since time.Time `schema:"since"`
Until time.Time `schema:"until"`
Since string `schema:"since"`
Until string `schema:"until"`
Filters map[string][]string `schema:"filters"`
}{}
if err := decodeQuery(r, &query); err != nil {
@ -27,15 +32,30 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
}
}
libpodEvents, err := getRuntime(r).GetEvents(libpodFilters)
if err != nil {
utils.BadRequest(w, "filters", strings.Join(r.URL.Query()["filters"], ", "), err)
if len(query.Since) > 0 || len(query.Until) > 0 {
fromStart = true
}
eventChannel := make(chan *events.Event)
go func() {
readOpts := events.ReadOptions{FromStart: fromStart, Stream: true, Filters: libpodFilters, EventChannel: eventChannel, Since: query.Since, Until: query.Until}
eventsError = getRuntime(r).Events(readOpts)
}()
if eventsError != nil {
utils.InternalServerError(w, eventsError)
return
}
var apiEvents = make([]*Event, len(libpodEvents))
for _, v := range libpodEvents {
apiEvents = append(apiEvents, EventToApiEvent(v))
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
for event := range eventChannel {
e := EventToApiEvent(event)
//utils.WriteJSON(w, http.StatusOK, e)
coder := json.NewEncoder(w)
coder.SetEscapeHTML(true)
if err := coder.Encode(e); err != nil {
logrus.Errorf("unable to write json: %q", err)
}
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
}
}
utils.WriteJSON(w, http.StatusOK, apiEvents)
}

View File

@ -19,9 +19,6 @@ import (
const DefaultStatsPeriod = 5 * time.Second
func StatsContainer(w http.ResponseWriter, r *http.Request) {
// 200 no error
// 404 no such
// 500 internal
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)

View File

@ -29,7 +29,7 @@ func (s *APIServer) RegisterEventsHandlers(r *mux.Router) error {
// description: JSON encoded map[string][]string of constraints
// responses:
// 200:
// $ref: "#/responses/ok"
// description: returns a string of json data describing an event
// 500:
// "$ref": "#/responses/InternalError"
r.Handle(VersionedPath("/events"), APIHandler(s.Context, handlers.GetEvents))

View File

@ -106,6 +106,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
server.RegisterContainersHandlers,
server.RegisterDistributionHandlers,
server.registerExecHandlers,
server.RegisterEventsHandlers,
server.registerHealthCheckHandlers,
server.registerImagesHandlers,
server.registerInfoHandlers,