github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/drvregistry/drvregistry.go (about)

     1  package drvregistry
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  	"sync"
     8  
     9  	"github.com/docker/docker/pkg/plugingetter"
    10  	"github.com/docker/libnetwork/driverapi"
    11  	"github.com/docker/libnetwork/ipamapi"
    12  	"github.com/docker/libnetwork/types"
    13  )
    14  
    15  type driverData struct {
    16  	driver     driverapi.Driver
    17  	capability driverapi.Capability
    18  }
    19  
    20  type ipamData struct {
    21  	driver     ipamapi.Ipam
    22  	capability *ipamapi.Capability
    23  	// default address spaces are provided by ipam driver at registration time
    24  	defaultLocalAddressSpace, defaultGlobalAddressSpace string
    25  }
    26  
    27  type driverTable map[string]*driverData
    28  type ipamTable map[string]*ipamData
    29  
    30  // DrvRegistry holds the registry of all network drivers and IPAM drivers that it knows about.
    31  type DrvRegistry struct {
    32  	sync.Mutex
    33  	drivers      driverTable
    34  	ipamDrivers  ipamTable
    35  	dfn          DriverNotifyFunc
    36  	ifn          IPAMNotifyFunc
    37  	pluginGetter plugingetter.PluginGetter
    38  }
    39  
    40  // Functors definition
    41  
    42  // InitFunc defines the driver initialization function signature.
    43  type InitFunc func(driverapi.DriverCallback, map[string]interface{}) error
    44  
    45  // IPAMWalkFunc defines the IPAM driver table walker function signature.
    46  type IPAMWalkFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool
    47  
    48  // DriverWalkFunc defines the network driver table walker function signature.
    49  type DriverWalkFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) bool
    50  
    51  // IPAMNotifyFunc defines the notify function signature when a new IPAM driver gets registered.
    52  type IPAMNotifyFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) error
    53  
    54  // DriverNotifyFunc defines the notify function signature when a new network driver gets registered.
    55  type DriverNotifyFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) error
    56  
    57  // New returns a new driver registry handle.
    58  func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc, pg plugingetter.PluginGetter) (*DrvRegistry, error) {
    59  	r := &DrvRegistry{
    60  		drivers:      make(driverTable),
    61  		ipamDrivers:  make(ipamTable),
    62  		dfn:          dfn,
    63  		ifn:          ifn,
    64  		pluginGetter: pg,
    65  	}
    66  
    67  	return r, nil
    68  }
    69  
    70  // AddDriver adds a network driver to the registry.
    71  func (r *DrvRegistry) AddDriver(ntype string, fn InitFunc, config map[string]interface{}) error {
    72  	return fn(r, config)
    73  }
    74  
    75  // WalkIPAMs walks the IPAM drivers registered in the registry and invokes the passed walk function and each one of them.
    76  func (r *DrvRegistry) WalkIPAMs(ifn IPAMWalkFunc) {
    77  	type ipamVal struct {
    78  		name string
    79  		data *ipamData
    80  	}
    81  
    82  	r.Lock()
    83  	ivl := make([]ipamVal, 0, len(r.ipamDrivers))
    84  	for k, v := range r.ipamDrivers {
    85  		ivl = append(ivl, ipamVal{name: k, data: v})
    86  	}
    87  	r.Unlock()
    88  
    89  	for _, iv := range ivl {
    90  		if ifn(iv.name, iv.data.driver, iv.data.capability) {
    91  			break
    92  		}
    93  	}
    94  }
    95  
    96  // WalkDrivers walks the network drivers registered in the registry and invokes the passed walk function and each one of them.
    97  func (r *DrvRegistry) WalkDrivers(dfn DriverWalkFunc) {
    98  	type driverVal struct {
    99  		name string
   100  		data *driverData
   101  	}
   102  
   103  	r.Lock()
   104  	dvl := make([]driverVal, 0, len(r.drivers))
   105  	for k, v := range r.drivers {
   106  		dvl = append(dvl, driverVal{name: k, data: v})
   107  	}
   108  	r.Unlock()
   109  
   110  	for _, dv := range dvl {
   111  		if dfn(dv.name, dv.data.driver, dv.data.capability) {
   112  			break
   113  		}
   114  	}
   115  }
   116  
   117  // Driver returns the actual network driver instance and its capability  which registered with the passed name.
   118  func (r *DrvRegistry) Driver(name string) (driverapi.Driver, *driverapi.Capability) {
   119  	r.Lock()
   120  	defer r.Unlock()
   121  
   122  	d, ok := r.drivers[name]
   123  	if !ok {
   124  		return nil, nil
   125  	}
   126  
   127  	return d.driver, &d.capability
   128  }
   129  
   130  // IPAM returns the actual IPAM driver instance and its capability which registered with the passed name.
   131  func (r *DrvRegistry) IPAM(name string) (ipamapi.Ipam, *ipamapi.Capability) {
   132  	r.Lock()
   133  	defer r.Unlock()
   134  
   135  	i, ok := r.ipamDrivers[name]
   136  	if !ok {
   137  		return nil, nil
   138  	}
   139  
   140  	return i.driver, i.capability
   141  }
   142  
   143  // IPAMDefaultAddressSpaces returns the default address space strings for the passed IPAM driver name.
   144  func (r *DrvRegistry) IPAMDefaultAddressSpaces(name string) (string, string, error) {
   145  	r.Lock()
   146  	defer r.Unlock()
   147  
   148  	i, ok := r.ipamDrivers[name]
   149  	if !ok {
   150  		return "", "", fmt.Errorf("ipam %s not found", name)
   151  	}
   152  
   153  	return i.defaultLocalAddressSpace, i.defaultGlobalAddressSpace, nil
   154  }
   155  
   156  // GetPluginGetter returns the plugingetter
   157  func (r *DrvRegistry) GetPluginGetter() plugingetter.PluginGetter {
   158  	return r.pluginGetter
   159  }
   160  
   161  // RegisterDriver registers the network driver when it gets discovered.
   162  func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capability driverapi.Capability) error {
   163  	if strings.TrimSpace(ntype) == "" {
   164  		return errors.New("network type string cannot be empty")
   165  	}
   166  
   167  	r.Lock()
   168  	dd, ok := r.drivers[ntype]
   169  	r.Unlock()
   170  
   171  	if ok && dd.driver.IsBuiltIn() {
   172  		return driverapi.ErrActiveRegistration(ntype)
   173  	}
   174  
   175  	if r.dfn != nil {
   176  		if err := r.dfn(ntype, driver, capability); err != nil {
   177  			return err
   178  		}
   179  	}
   180  
   181  	dData := &driverData{driver, capability}
   182  
   183  	r.Lock()
   184  	r.drivers[ntype] = dData
   185  	r.Unlock()
   186  
   187  	return nil
   188  }
   189  
   190  func (r *DrvRegistry) registerIpamDriver(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error {
   191  	if strings.TrimSpace(name) == "" {
   192  		return errors.New("ipam driver name string cannot be empty")
   193  	}
   194  
   195  	r.Lock()
   196  	dd, ok := r.ipamDrivers[name]
   197  	r.Unlock()
   198  	if ok && dd.driver.IsBuiltIn() {
   199  		return types.ForbiddenErrorf("ipam driver %q already registered", name)
   200  	}
   201  
   202  	locAS, glbAS, err := driver.GetDefaultAddressSpaces()
   203  	if err != nil {
   204  		return types.InternalErrorf("ipam driver %q failed to return default address spaces: %v", name, err)
   205  	}
   206  
   207  	if r.ifn != nil {
   208  		if err := r.ifn(name, driver, caps); err != nil {
   209  			return err
   210  		}
   211  	}
   212  
   213  	r.Lock()
   214  	r.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS, capability: caps}
   215  	r.Unlock()
   216  
   217  	return nil
   218  }
   219  
   220  // RegisterIpamDriver registers the IPAM driver discovered with default capabilities.
   221  func (r *DrvRegistry) RegisterIpamDriver(name string, driver ipamapi.Ipam) error {
   222  	return r.registerIpamDriver(name, driver, &ipamapi.Capability{})
   223  }
   224  
   225  // RegisterIpamDriverWithCapabilities registers the IPAM driver discovered with specified capabilities.
   226  func (r *DrvRegistry) RegisterIpamDriverWithCapabilities(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error {
   227  	return r.registerIpamDriver(name, driver, caps)
   228  }