moby/libnetwork/drvregistry/ipams.go
Cory Snider 5595311209 libnetwork/drvregistry: split up the registries
There is no benefit to having a single registry for both IPAM drivers
and network drivers. IPAM drivers are registered in a separate namespace
from network drivers, have separate registration methods, separate
accessor methods and do not interact with network drivers within a
DrvRegistry in any way. The only point of commonality is

    interface { GetPluginGetter() plugingetter.PluginGetter }

which is only used by the respective remote drivers and therefore should
be outside of the scope of a driver registry.

Create new, separate registry types for network drivers and IPAM
drivers, respectively. These types are "legacy-free". Neither type has
GetPluginGetter methods. The IPAMs registry does not have an
IPAMDefaultAddressSpaces method as that information can be queried
directly from the driver using its GetDefaultAddressSpaces method.
The Networks registry does not have an AddDriver method as that method
is a trivial wrapper around calling one of its arguments with its other
arguments.

Refactor DrvRegistry in terms of the new IPAMs and Networks registries
so that existing code in libnetwork and Swarmkit will continue to work.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2023-01-27 11:47:42 -05:00

84 lines
2.2 KiB
Go

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
}
}
}