package drvregistry import ( "errors" "strings" "sync" "github.com/docker/docker/libnetwork/ipamapi" "github.com/docker/docker/libnetwork/types" ) type ipamDriver struct { driver ipamapi.Ipam capability *ipamapi.Capability } // IPAMs is a registry of IPAM drivers. The zero value is an empty IPAM driver // registry, ready to use. type IPAMs struct { mu sync.Mutex drivers map[string]ipamDriver } var _ ipamapi.Registerer = (*IPAMs)(nil) // IPAM returns the actual IPAM driver instance and its capability which registered with the passed name. func (ir *IPAMs) IPAM(name string) (ipamapi.Ipam, *ipamapi.Capability) { ir.mu.Lock() defer ir.mu.Unlock() d := ir.drivers[name] return d.driver, d.capability } // RegisterIpamDriverWithCapabilities registers the IPAM driver discovered with specified capabilities. func (ir *IPAMs) RegisterIpamDriverWithCapabilities(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error { if strings.TrimSpace(name) == "" { return errors.New("ipam driver name string cannot be empty") } ir.mu.Lock() defer ir.mu.Unlock() dd, ok := ir.drivers[name] if ok && dd.driver.IsBuiltIn() { return types.ForbiddenErrorf("ipam driver %q already registered", name) } if ir.drivers == nil { ir.drivers = make(map[string]ipamDriver) } ir.drivers[name] = ipamDriver{driver: driver, capability: caps} return nil } // RegisterIpamDriver registers the IPAM driver discovered with default capabilities. func (ir *IPAMs) RegisterIpamDriver(name string, driver ipamapi.Ipam) error { return ir.RegisterIpamDriverWithCapabilities(name, driver, &ipamapi.Capability{}) } // IPAMWalkFunc defines the IPAM driver table walker function signature. type IPAMWalkFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool // WalkIPAMs walks the IPAM drivers registered in the registry and invokes the passed walk function and each one of them. func (ir *IPAMs) WalkIPAMs(ifn IPAMWalkFunc) { type ipamVal struct { name string data ipamDriver } ir.mu.Lock() ivl := make([]ipamVal, 0, len(ir.drivers)) for k, v := range ir.drivers { ivl = append(ivl, ipamVal{name: k, data: v}) } ir.mu.Unlock() for _, iv := range ivl { if ifn(iv.name, iv.data.driver, iv.data.capability) { break } } }