github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/plugin/events.go (about)

     1  package plugin // import "github.com/docker/docker/plugin"
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/docker/docker/api/types"
     8  )
     9  
    10  // Event is emitted for actions performed on the plugin manager
    11  type Event interface {
    12  	matches(Event) bool
    13  }
    14  
    15  // EventCreate is an event which is emitted when a plugin is created
    16  // This is either by pull or create from context.
    17  //
    18  // Use the `Interfaces` field to match only plugins that implement a specific
    19  // interface.
    20  // These are matched against using "or" logic.
    21  // If no interfaces are listed, all are matched.
    22  type EventCreate struct {
    23  	Interfaces map[string]bool
    24  	Plugin     types.Plugin
    25  }
    26  
    27  func (e EventCreate) matches(observed Event) bool {
    28  	oe, ok := observed.(EventCreate)
    29  	if !ok {
    30  		return false
    31  	}
    32  	if len(e.Interfaces) == 0 {
    33  		return true
    34  	}
    35  
    36  	var ifaceMatch bool
    37  	for _, in := range oe.Plugin.Config.Interface.Types {
    38  		if e.Interfaces[in.Capability] {
    39  			ifaceMatch = true
    40  			break
    41  		}
    42  	}
    43  	return ifaceMatch
    44  }
    45  
    46  // EventRemove is an event which is emitted when a plugin is removed
    47  // It maches on the passed in plugin's ID only.
    48  type EventRemove struct {
    49  	Plugin types.Plugin
    50  }
    51  
    52  func (e EventRemove) matches(observed Event) bool {
    53  	oe, ok := observed.(EventRemove)
    54  	if !ok {
    55  		return false
    56  	}
    57  	return e.Plugin.ID == oe.Plugin.ID
    58  }
    59  
    60  // EventDisable is an event that is emitted when a plugin is disabled
    61  // It maches on the passed in plugin's ID only.
    62  type EventDisable struct {
    63  	Plugin types.Plugin
    64  }
    65  
    66  func (e EventDisable) matches(observed Event) bool {
    67  	oe, ok := observed.(EventDisable)
    68  	if !ok {
    69  		return false
    70  	}
    71  	return e.Plugin.ID == oe.Plugin.ID
    72  }
    73  
    74  // EventEnable is an event that is emitted when a plugin is disabled
    75  // It maches on the passed in plugin's ID only.
    76  type EventEnable struct {
    77  	Plugin types.Plugin
    78  }
    79  
    80  func (e EventEnable) matches(observed Event) bool {
    81  	oe, ok := observed.(EventEnable)
    82  	if !ok {
    83  		return false
    84  	}
    85  	return e.Plugin.ID == oe.Plugin.ID
    86  }
    87  
    88  // SubscribeEvents provides an event channel to listen for structured events from
    89  // the plugin manager actions, CRUD operations.
    90  // The caller must call the returned `cancel()` function once done with the channel
    91  // or this will leak resources.
    92  func (pm *Manager) SubscribeEvents(buffer int, watchEvents ...Event) (eventCh <-chan interface{}, cancel func()) {
    93  	topic := func(i interface{}) bool {
    94  		observed, ok := i.(Event)
    95  		if !ok {
    96  			panic(fmt.Sprintf("unexpected type passed to event channel: %v", reflect.TypeOf(i)))
    97  		}
    98  		for _, e := range watchEvents {
    99  			if e.matches(observed) {
   100  				return true
   101  			}
   102  		}
   103  		// If no specific events are specified always assume a matched event
   104  		// If some events were specified and none matched above, then the event
   105  		// doesn't match
   106  		return watchEvents == nil
   107  	}
   108  	ch := pm.publisher.SubscribeTopicWithBuffer(topic, buffer)
   109  	cancelFunc := func() { pm.publisher.Evict(ch) }
   110  	return ch, cancelFunc
   111  }