plugin/events.go
4f0d95fa
 package plugin // import "github.com/docker/docker/plugin"
72c3bcf2
 
 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
 }