github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/client/events.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "context" 5 "encoding/json" 6 "net/url" 7 "time" 8 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/api/types/events" 11 "github.com/docker/docker/api/types/filters" 12 timetypes "github.com/docker/docker/api/types/time" 13 ) 14 15 // Events returns a stream of events in the daemon. It's up to the caller to close the stream 16 // by cancelling the context. Once the stream has been completely read an io.EOF error will 17 // be sent over the error channel. If an error is sent all processing will be stopped. It's up 18 // to the caller to reopen the stream in the event of an error by reinvoking this method. 19 func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) { 20 21 messages := make(chan events.Message) 22 errs := make(chan error, 1) 23 24 started := make(chan struct{}) 25 go func() { 26 defer close(errs) 27 28 query, err := buildEventsQueryParams(cli.version, options) 29 if err != nil { 30 close(started) 31 errs <- err 32 return 33 } 34 35 resp, err := cli.get(ctx, "/events", query, nil) 36 if err != nil { 37 close(started) 38 errs <- err 39 return 40 } 41 defer resp.body.Close() 42 43 decoder := json.NewDecoder(resp.body) 44 45 close(started) 46 for { 47 select { 48 case <-ctx.Done(): 49 errs <- ctx.Err() 50 return 51 default: 52 var event events.Message 53 if err := decoder.Decode(&event); err != nil { 54 errs <- err 55 return 56 } 57 58 select { 59 case messages <- event: 60 case <-ctx.Done(): 61 errs <- ctx.Err() 62 return 63 } 64 } 65 } 66 }() 67 <-started 68 69 return messages, errs 70 } 71 72 func buildEventsQueryParams(cliVersion string, options types.EventsOptions) (url.Values, error) { 73 query := url.Values{} 74 ref := time.Now() 75 76 if options.Since != "" { 77 ts, err := timetypes.GetTimestamp(options.Since, ref) 78 if err != nil { 79 return nil, err 80 } 81 query.Set("since", ts) 82 } 83 84 if options.Until != "" { 85 ts, err := timetypes.GetTimestamp(options.Until, ref) 86 if err != nil { 87 return nil, err 88 } 89 query.Set("until", ts) 90 } 91 92 if options.Filters.Len() > 0 { 93 //nolint:staticcheck // ignore SA1019 for old code 94 filterJSON, err := filters.ToParamWithVersion(cliVersion, options.Filters) 95 if err != nil { 96 return nil, err 97 } 98 query.Set("filters", filterJSON) 99 } 100 101 return query, nil 102 }