github.com/containerd/Containerd@v1.4.13/events.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package containerd 18 19 import ( 20 "context" 21 22 eventsapi "github.com/containerd/containerd/api/services/events/v1" 23 "github.com/containerd/containerd/errdefs" 24 "github.com/containerd/containerd/events" 25 "github.com/containerd/typeurl" 26 ) 27 28 // EventService handles the publish, forward and subscribe of events. 29 type EventService interface { 30 events.Publisher 31 events.Forwarder 32 events.Subscriber 33 } 34 35 // NewEventServiceFromClient returns a new event service which communicates 36 // over a GRPC connection. 37 func NewEventServiceFromClient(client eventsapi.EventsClient) EventService { 38 return &eventRemote{ 39 client: client, 40 } 41 } 42 43 type eventRemote struct { 44 client eventsapi.EventsClient 45 } 46 47 func (e *eventRemote) Publish(ctx context.Context, topic string, event events.Event) error { 48 any, err := typeurl.MarshalAny(event) 49 if err != nil { 50 return err 51 } 52 req := &eventsapi.PublishRequest{ 53 Topic: topic, 54 Event: any, 55 } 56 if _, err := e.client.Publish(ctx, req); err != nil { 57 return errdefs.FromGRPC(err) 58 } 59 return nil 60 } 61 62 func (e *eventRemote) Forward(ctx context.Context, envelope *events.Envelope) error { 63 req := &eventsapi.ForwardRequest{ 64 Envelope: &eventsapi.Envelope{ 65 Timestamp: envelope.Timestamp, 66 Namespace: envelope.Namespace, 67 Topic: envelope.Topic, 68 Event: envelope.Event, 69 }, 70 } 71 if _, err := e.client.Forward(ctx, req); err != nil { 72 return errdefs.FromGRPC(err) 73 } 74 return nil 75 } 76 77 func (e *eventRemote) Subscribe(ctx context.Context, filters ...string) (ch <-chan *events.Envelope, errs <-chan error) { 78 var ( 79 evq = make(chan *events.Envelope) 80 errq = make(chan error, 1) 81 ) 82 83 errs = errq 84 ch = evq 85 86 session, err := e.client.Subscribe(ctx, &eventsapi.SubscribeRequest{ 87 Filters: filters, 88 }) 89 if err != nil { 90 errq <- err 91 close(errq) 92 return 93 } 94 95 go func() { 96 defer close(errq) 97 98 for { 99 ev, err := session.Recv() 100 if err != nil { 101 errq <- err 102 return 103 } 104 105 select { 106 case evq <- &events.Envelope{ 107 Timestamp: ev.Timestamp, 108 Namespace: ev.Namespace, 109 Topic: ev.Topic, 110 Event: ev.Event, 111 }: 112 case <-ctx.Done(): 113 if cerr := ctx.Err(); cerr != context.Canceled { 114 errq <- cerr 115 } 116 return 117 } 118 } 119 }() 120 121 return ch, errs 122 }