mirror of
https://github.com/moby/moby.git
synced 2026-01-11 10:41:43 +00:00
The format for filters changed in93d1dd8036(docker v1.10 / API v1.22). As part of that implementation, the daemon would parse the new format, and fall back to parsing the old format if this failed. This fallback was not based on API version, so any version of the API released since would continue to accept both the legacy and curent format. For the client, the change in format caused a regression when connecting to an older daemon; a `ToParamWithVersion` utility was introduced in [docker/engine-api@81388f0] to produce the old format when the client was connected to a docker v1.9 or older daemon, using an old API version. Given that any version of docker 1.10 or above would support both formats, regardless of the API version used, and API v1.22 is no longer supported, it should be safe to assume we can drop the version-specific format in the client. Even if the client would be using API v1.22 (or older), the format would only be necessary for an actual docker v1.9 daemon, which would be very unlikely, and a daemon that's 9 Years old. [docker/engine-api@81388f0]:81388f00ddSigned-off-by: Sebastiaan van Stijn <github@gone.nl>
107 lines
2.2 KiB
Go
107 lines
2.2 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/moby/moby/api/types/events"
|
|
"github.com/moby/moby/api/types/filters"
|
|
"github.com/moby/moby/client/internal/timestamp"
|
|
)
|
|
|
|
// EventsListOptions holds parameters to filter events with.
|
|
type EventsListOptions struct {
|
|
Since string
|
|
Until string
|
|
Filters filters.Args
|
|
}
|
|
|
|
// Events returns a stream of events in the daemon. It's up to the caller to close the stream
|
|
// by cancelling the context. Once the stream has been completely read an [io.EOF] error is
|
|
// sent over the error channel. If an error is sent, all processing is stopped. It's up
|
|
// to the caller to reopen the stream in the event of an error by reinvoking this method.
|
|
func (cli *Client) Events(ctx context.Context, options EventsListOptions) (<-chan events.Message, <-chan error) {
|
|
messages := make(chan events.Message)
|
|
errs := make(chan error, 1)
|
|
|
|
started := make(chan struct{})
|
|
go func() {
|
|
defer close(errs)
|
|
|
|
query, err := buildEventsQueryParams(options)
|
|
if err != nil {
|
|
close(started)
|
|
errs <- err
|
|
return
|
|
}
|
|
|
|
resp, err := cli.get(ctx, "/events", query, nil)
|
|
if err != nil {
|
|
close(started)
|
|
errs <- err
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
decoder := json.NewDecoder(resp.Body)
|
|
|
|
close(started)
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
errs <- ctx.Err()
|
|
return
|
|
default:
|
|
var event events.Message
|
|
if err := decoder.Decode(&event); err != nil {
|
|
errs <- err
|
|
return
|
|
}
|
|
|
|
select {
|
|
case messages <- event:
|
|
case <-ctx.Done():
|
|
errs <- ctx.Err()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
<-started
|
|
|
|
return messages, errs
|
|
}
|
|
|
|
func buildEventsQueryParams(options EventsListOptions) (url.Values, error) {
|
|
query := url.Values{}
|
|
ref := time.Now()
|
|
|
|
if options.Since != "" {
|
|
ts, err := timestamp.GetTimestamp(options.Since, ref)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
query.Set("since", ts)
|
|
}
|
|
|
|
if options.Until != "" {
|
|
ts, err := timestamp.GetTimestamp(options.Until, ref)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
query.Set("until", ts)
|
|
}
|
|
|
|
if options.Filters.Len() > 0 {
|
|
filterJSON, err := filters.ToJSON(options.Filters)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
query.Set("filters", filterJSON)
|
|
}
|
|
|
|
return query, nil
|
|
}
|