| package plugin // import "github.com/docker/docker/plugin" |
| |
| import ( |
| "fmt" |
| "reflect" |
| |
| "github.com/docker/docker/api/types" |
| ) |
| |
| // Event is emitted for actions performed on the plugin manager |
| type Event interface { |
| matches(Event) bool |
| } |
| |
| // EventCreate is an event which is emitted when a plugin is created |
| // This is either by pull or create from context. |
| // |
| // Use the `Interfaces` field to match only plugins that implement a specific |
| // interface. |
| // These are matched against using "or" logic. |
| // If no interfaces are listed, all are matched. |
| type EventCreate struct { |
| Interfaces map[string]bool |
| Plugin types.Plugin |
| } |
| |
| func (e EventCreate) matches(observed Event) bool { |
| oe, ok := observed.(EventCreate) |
| if !ok { |
| return false |
| } |
| if len(e.Interfaces) == 0 { |
| return true |
| } |
| |
| var ifaceMatch bool |
| for _, in := range oe.Plugin.Config.Interface.Types { |
| if e.Interfaces[in.Capability] { |
| ifaceMatch = true |
| break |
| } |
| } |
| return ifaceMatch |
| } |
| |
| // EventRemove is an event which is emitted when a plugin is removed |
| // It maches on the passed in plugin's ID only. |
| type EventRemove struct { |
| Plugin types.Plugin |
| } |
| |
| func (e EventRemove) matches(observed Event) bool { |
| oe, ok := observed.(EventRemove) |
| if !ok { |
| return false |
| } |
| return e.Plugin.ID == oe.Plugin.ID |
| } |
| |
| // EventDisable is an event that is emitted when a plugin is disabled |
| // It maches on the passed in plugin's ID only. |
| type EventDisable struct { |
| Plugin types.Plugin |
| } |
| |
| func (e EventDisable) matches(observed Event) bool { |
| oe, ok := observed.(EventDisable) |
| if !ok { |
| return false |
| } |
| return e.Plugin.ID == oe.Plugin.ID |
| } |
| |
| // EventEnable is an event that is emitted when a plugin is disabled |
| // It maches on the passed in plugin's ID only. |
| type EventEnable struct { |
| Plugin types.Plugin |
| } |
| |
| func (e EventEnable) matches(observed Event) bool { |
| oe, ok := observed.(EventEnable) |
| if !ok { |
| return false |
| } |
| return e.Plugin.ID == oe.Plugin.ID |
| } |
| |
| // SubscribeEvents provides an event channel to listen for structured events from |
| // the plugin manager actions, CRUD operations. |
| // The caller must call the returned `cancel()` function once done with the channel |
| // or this will leak resources. |
| func (pm *Manager) SubscribeEvents(buffer int, watchEvents ...Event) (eventCh <-chan interface{}, cancel func()) { |
| topic := func(i interface{}) bool { |
| observed, ok := i.(Event) |
| if !ok { |
| panic(fmt.Sprintf("unexpected type passed to event channel: %v", reflect.TypeOf(i))) |
| } |
| for _, e := range watchEvents { |
| if e.matches(observed) { |
| return true |
| } |
| } |
| // If no specific events are specified always assume a matched event |
| // If some events were specified and none matched above, then the event |
| // doesn't match |
| return watchEvents == nil |
| } |
| ch := pm.publisher.SubscribeTopicWithBuffer(topic, buffer) |
| cancelFunc := func() { pm.publisher.Evict(ch) } |
| return ch, cancelFunc |
| } |