libnet: convert to new-style driver registration

Per the Interface Segregation Principle, network drivers should not have
to depend on GetPluginGetter methods they do not use. The remote network
driver is the only one which needs a PluginGetter, and it is already
special-cased in Controller so there is no sense warping the interfaces
to achieve a foolish consistency. Replace all other network drivers' Init
functions with Register functions which take a driverapi.Registerer
argument instead of a driverapi.DriverCallback. Add back in Init wrapper
functions for only the drivers which Swarmkit references so that
Swarmkit can continue to build.

Refactor the libnetwork Controller to use the new drvregistry.Networks
and drvregistry.IPAMs driver registries in place of the legacy ones.

Signed-off-by: Cory Snider <csnider@mirantis.com>
This commit is contained in:
Cory Snider 2023-01-24 18:19:26 -05:00
parent 5595311209
commit 28edc8e2d6
23 changed files with 124 additions and 104 deletions

View file

@ -13,7 +13,6 @@ import (
"github.com/docker/docker/libnetwork/drivers/overlay"
"github.com/docker/docker/libnetwork/netlabel"
"github.com/docker/docker/libnetwork/types"
"github.com/docker/docker/pkg/plugingetter"
"github.com/docker/docker/pkg/reexec"
"github.com/vishvananda/netlink"
)
@ -28,10 +27,6 @@ type endpoint struct {
name string
}
func (r *router) GetPluginGetter() plugingetter.PluginGetter {
return nil
}
func (r *router) RegisterDriver(name string, driver driverapi.Driver, c driverapi.Capability) error {
r.d = driver
return nil
@ -126,7 +121,7 @@ func main() {
}
r := &router{}
if err := overlay.Init(r, opt); err != nil {
if err := overlay.Register(r, opt); err != nil {
fmt.Printf("Failed to initialize overlay driver: %v\n", err)
os.Exit(1)
}

View file

@ -58,6 +58,7 @@ import (
"github.com/docker/docker/libnetwork/diagnostic"
"github.com/docker/docker/libnetwork/discoverapi"
"github.com/docker/docker/libnetwork/driverapi"
remotedriver "github.com/docker/docker/libnetwork/drivers/remote"
"github.com/docker/docker/libnetwork/drvregistry"
"github.com/docker/docker/libnetwork/ipamapi"
"github.com/docker/docker/libnetwork/netlabel"
@ -85,7 +86,8 @@ type sandboxTable map[string]*Sandbox
// Controller manages networks.
type Controller struct {
id string
drvRegistry *drvregistry.DrvRegistry
drvRegistry drvregistry.Networks
ipamRegistry drvregistry.IPAMs
sandboxes sandboxTable
cfg *config.Config
store datastore.DataStore
@ -108,7 +110,7 @@ type Controller struct {
}
type initializer struct {
fn drvregistry.InitFunc
fn func(driverapi.Registerer, map[string]interface{}) error
ntype string
}
@ -130,31 +132,24 @@ func New(cfgOptions ...config.Option) (*Controller, error) {
return nil, err
}
drvRegistry, err := drvregistry.New(nil, nil, c.RegisterDriver, nil, c.cfg.PluginGetter)
if err != nil {
c.drvRegistry.Notify = c.RegisterDriver
// External plugins don't need config passed through daemon. They can
// bootstrap themselves.
if err := remotedriver.Register(&c.drvRegistry, c.cfg.PluginGetter); err != nil {
return nil, err
}
for _, i := range getInitializers() {
var dcfg map[string]interface{}
// External plugins don't need config passed through daemon. They can
// bootstrap themselves
if i.ntype != "remote" {
dcfg = c.makeDriverConfig(i.ntype)
}
if err := drvRegistry.AddDriver(i.ntype, i.fn, dcfg); err != nil {
if err := i.fn(&c.drvRegistry, c.makeDriverConfig(i.ntype)); err != nil {
return nil, err
}
}
if err = initIPAMDrivers(drvRegistry, c.cfg.PluginGetter, c.cfg.DefaultAddressPool); err != nil {
if err := initIPAMDrivers(&c.ipamRegistry, c.cfg.PluginGetter, c.cfg.DefaultAddressPool); err != nil {
return nil, err
}
c.drvRegistry = drvRegistry
c.WalkNetworks(populateSpecial)
// Reserve pools first before doing cleanup. Otherwise the
@ -387,7 +382,7 @@ func (c *Controller) BuiltinDrivers() []string {
// BuiltinIPAMDrivers returns the list of builtin ipam drivers.
func (c *Controller) BuiltinIPAMDrivers() []string {
drivers := []string{}
c.drvRegistry.WalkIPAMs(func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool {
c.ipamRegistry.WalkIPAMs(func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool {
if driver.IsBuiltIn() {
drivers = append(drivers, name)
}
@ -461,7 +456,7 @@ func (c *Controller) isDistributedControl() bool {
}
func (c *Controller) GetPluginGetter() plugingetter.PluginGetter {
return c.drvRegistry.GetPluginGetter()
return c.cfg.PluginGetter
}
func (c *Controller) RegisterDriver(networkType string, driver driverapi.Driver, capability driverapi.Capability) error {
@ -476,7 +471,7 @@ const overlayDSROptionString = "dsr"
// are network specific and modeled in a generic way.
func (c *Controller) NewNetwork(networkType, name string, id string, options ...NetworkOption) (Network, error) {
var (
caps *driverapi.Capability
caps driverapi.Capability
err error
t *network
skipCfgEpCount bool
@ -1101,7 +1096,7 @@ func (c *Controller) loadIPAMDriver(name string) error {
}
func (c *Controller) getIPAMDriver(name string) (ipamapi.Ipam, *ipamapi.Capability, error) {
id, cap := c.drvRegistry.IPAM(name)
id, cap := c.ipamRegistry.IPAM(name)
if id == nil {
// Might be a plugin name. Try loading it
if err := c.loadIPAMDriver(name); err != nil {
@ -1109,7 +1104,7 @@ func (c *Controller) getIPAMDriver(name string) (ipamapi.Ipam, *ipamapi.Capabili
}
// Now that we resolved the plugin, try again looking up the registry
id, cap = c.drvRegistry.IPAM(name)
id, cap = c.ipamRegistry.IPAM(name)
if id == nil {
return nil, nil, types.BadRequestErrorf("invalid ipam driver: %q", name)
}

View file

@ -166,8 +166,8 @@ func newDriver() *driver {
}
}
// Init registers a new instance of bridge driver
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
// Register registers a new instance of bridge driver.
func Register(r driverapi.Registerer, config map[string]interface{}) error {
d := newDriver()
if err := d.configure(config); err != nil {
return err
@ -177,7 +177,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
DataScope: datastore.LocalScope,
ConnectivityScope: datastore.LocalScope,
}
return dc.RegisterDriver(networkType, d, c)
return r.RegisterDriver(networkType, d, c)
}
// Validate performs a static validation on the network configuration parameters.

View file

@ -11,13 +11,20 @@ const networkType = "bridge"
type driver struct{}
// Init registers a new instance of bridge manager driver
// Init registers a new instance of bridge manager driver.
//
// Deprecated: use [Register].
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return Register(dc, config)
}
// Register registers a new instance of the bridge manager driver with r.
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.LocalScope,
ConnectivityScope: datastore.LocalScope,
}
return dc.RegisterDriver(networkType, &driver{}, c)
return r.RegisterDriver(networkType, &driver{}, c)
}
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {

View file

@ -16,13 +16,19 @@ type driver struct {
sync.Mutex
}
// Init registers a new instance of host driver
// Init registers a new instance of host driver.
//
// Deprecated: use [Register].
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return Register(dc, config)
}
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.LocalScope,
ConnectivityScope: datastore.LocalScope,
}
return dc.RegisterDriver(networkType, &driver{}, c)
return r.RegisterDriver(networkType, &driver{}, c)
}
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {

View file

@ -62,8 +62,8 @@ type network struct {
sync.Mutex
}
// Init initializes and registers the libnetwork ipvlan driver
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
// Register initializes and registers the libnetwork ipvlan driver.
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.LocalScope,
ConnectivityScope: datastore.GlobalScope,
@ -75,7 +75,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return err
}
return dc.RegisterDriver(driverName, d, c)
return r.RegisterDriver(driverName, d, c)
}
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {

View file

@ -7,7 +7,6 @@ import (
"testing"
"github.com/docker/docker/libnetwork/driverapi"
"github.com/docker/docker/pkg/plugingetter"
)
const testNetworkType = "ipvlan"
@ -17,10 +16,6 @@ type driverTester struct {
d *driver
}
func (dt *driverTester) GetPluginGetter() plugingetter.PluginGetter {
return nil
}
func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
cap driverapi.Capability) error {
if name != testNetworkType {
@ -37,15 +32,15 @@ func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
return nil
}
func TestIpvlanInit(t *testing.T) {
if err := Init(&driverTester{t: t}, nil); err != nil {
func TestIpvlanRegister(t *testing.T) {
if err := Register(&driverTester{t: t}, nil); err != nil {
t.Fatal(err)
}
}
func TestIpvlanNilConfig(t *testing.T) {
dt := &driverTester{t: t}
if err := Init(dt, nil); err != nil {
if err := Register(dt, nil); err != nil {
t.Fatal(err)
}
@ -56,7 +51,7 @@ func TestIpvlanNilConfig(t *testing.T) {
func TestIpvlanType(t *testing.T) {
dt := &driverTester{t: t}
if err := Init(dt, nil); err != nil {
if err := Register(dt, nil); err != nil {
t.Fatal(err)
}

View file

@ -11,13 +11,20 @@ const networkType = "ipvlan"
type driver struct{}
// Init registers a new instance of ipvlan manager driver
// Init registers a new instance of the ipvlan manager driver.
//
// Deprecated: use [Register].
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return Register(dc, config)
}
// Register registers a new instance of the ipvlan manager driver.
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.LocalScope,
ConnectivityScope: datastore.GlobalScope,
}
return dc.RegisterDriver(networkType, &driver{}, c)
return r.RegisterDriver(networkType, &driver{}, c)
}
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {

View file

@ -56,8 +56,8 @@ type network struct {
sync.Mutex
}
// Init initializes and registers the libnetwork macvlan driver
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
// Register initializes and registers the libnetwork macvlan driver
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.LocalScope,
ConnectivityScope: datastore.GlobalScope,
@ -69,7 +69,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return err
}
return dc.RegisterDriver(driverName, d, c)
return r.RegisterDriver(driverName, d, c)
}
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {

View file

@ -7,7 +7,6 @@ import (
"testing"
"github.com/docker/docker/libnetwork/driverapi"
"github.com/docker/docker/pkg/plugingetter"
)
const testNetworkType = "macvlan"
@ -17,10 +16,6 @@ type driverTester struct {
d *driver
}
func (dt *driverTester) GetPluginGetter() plugingetter.PluginGetter {
return nil
}
func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
cap driverapi.Capability) error {
if name != testNetworkType {
@ -37,15 +32,15 @@ func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
return nil
}
func TestMacvlanInit(t *testing.T) {
if err := Init(&driverTester{t: t}, nil); err != nil {
func TestMacvlanRegister(t *testing.T) {
if err := Register(&driverTester{t: t}, nil); err != nil {
t.Fatal(err)
}
}
func TestMacvlanNilConfig(t *testing.T) {
dt := &driverTester{t: t}
if err := Init(dt, nil); err != nil {
if err := Register(dt, nil); err != nil {
t.Fatal(err)
}
@ -56,7 +51,7 @@ func TestMacvlanNilConfig(t *testing.T) {
func TestMacvlanType(t *testing.T) {
dt := &driverTester{t: t}
if err := Init(dt, nil); err != nil {
if err := Register(dt, nil); err != nil {
t.Fatal(err)
}

View file

@ -11,13 +11,20 @@ const networkType = "macvlan"
type driver struct{}
// Init registers a new instance of macvlan manager driver
// Init registers a new instance of the macvlan manager driver.
//
// Deprecated: use [Register].
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return Register(dc, config)
}
// Register registers a new instance of the macvlan manager driver.
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.LocalScope,
ConnectivityScope: datastore.GlobalScope,
}
return dc.RegisterDriver(networkType, &driver{}, c)
return r.RegisterDriver(networkType, &driver{}, c)
}
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {

View file

@ -16,12 +16,12 @@ type driver struct {
sync.Mutex
}
// Init registers a new instance of null driver
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
// Register registers a new instance of the null driver.
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.LocalScope,
}
return dc.RegisterDriver(networkType, &driver{}, c)
return r.RegisterDriver(networkType, &driver{}, c)
}
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {

View file

@ -58,8 +58,8 @@ type driver struct {
sync.Mutex
}
// Init registers a new instance of overlay driver
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
// Register registers a new instance of the overlay driver.
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.GlobalScope,
ConnectivityScope: datastore.GlobalScope,
@ -107,7 +107,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
logrus.Warnf("Failure during overlay endpoints restore: %v", err)
}
return dc.RegisterDriver(networkType, d, c)
return r.RegisterDriver(networkType, d, c)
}
// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox

View file

@ -59,7 +59,7 @@ func setupDriver(t *testing.T) *driverTester {
},
}
if err := Init(dt, config); err != nil {
if err := Register(dt, config); err != nil {
t.Fatal(err)
}
@ -114,14 +114,14 @@ func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver,
}
func TestOverlayInit(t *testing.T) {
if err := Init(&driverTester{t: t}, nil); err != nil {
if err := Register(&driverTester{t: t}, nil); err != nil {
t.Fatal(err)
}
}
func TestOverlayFiniWithoutConfig(t *testing.T) {
dt := &driverTester{t: t}
if err := Init(dt, nil); err != nil {
if err := Register(dt, nil); err != nil {
t.Fatal(err)
}
@ -151,7 +151,7 @@ func TestOverlayConfig(t *testing.T) {
func TestOverlayType(t *testing.T) {
dt := &driverTester{t: t}
if err := Init(dt, nil); err != nil {
if err := Register(dt, nil); err != nil {
t.Fatal(err)
}

View file

@ -44,8 +44,15 @@ type network struct {
sync.Mutex
}
// Init registers a new instance of overlay driver
// Init registers a new instance of the overlay driver.
//
// Deprecated: use [Register].
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return Register(dc, config)
}
// Register registers a new instance of the overlay driver.
func Register(r driverapi.DriverCallback, config map[string]interface{}) error {
var err error
c := driverapi.Capability{
DataScope: datastore.GlobalScope,
@ -62,7 +69,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
}
return dc.RegisterDriver(networkType, d, c)
return r.RegisterDriver(networkType, d, c)
}
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {

View file

@ -30,7 +30,15 @@ func newDriver(name string, client *plugins.Client) driverapi.Driver {
// Init makes sure a remote driver is registered when a network driver
// plugin is activated.
//
// Deprecated: use [Register].
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
return Register(dc, dc.GetPluginGetter())
}
// Register makes sure a remote driver is registered with r when a network
// driver plugin is activated.
func Register(r driverapi.Registerer, pg plugingetter.PluginGetter) error {
newPluginHandler := func(name string, client *plugins.Client) {
// negotiate driver capability with client
d := newDriver(name, client)
@ -39,14 +47,14 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
logrus.Errorf("error getting capability for %s due to %v", name, err)
return
}
if err = dc.RegisterDriver(name, d, *c); err != nil {
if err = r.RegisterDriver(name, d, *c); err != nil {
logrus.Errorf("error registering driver for %s due to %v", name, err)
}
}
// Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
handleFunc := plugins.Handle
if pg := dc.GetPluginGetter(); pg != nil {
if pg != nil {
handleFunc = pg.Handle
activePlugins := pg.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType)
for _, ap := range activePlugins {

View file

@ -30,8 +30,8 @@ type driver struct {
sync.Mutex
}
// Init registers a new instance of overlay driver
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
// Register registers a new instance of the overlay driver.
func Register(r driverapi.Registerer, config map[string]interface{}) error {
c := driverapi.Capability{
DataScope: datastore.GlobalScope,
ConnectivityScope: datastore.GlobalScope,
@ -68,7 +68,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
d.restoreHNSNetworks()
return dc.RegisterDriver(networkType, d, c)
return r.RegisterDriver(networkType, d, c)
}
func (d *driver) restoreHNSNetworks() error {

View file

@ -127,8 +127,8 @@ func newDriver(networkType string) *driver {
}
// GetInit returns an initializer for the given network type
func GetInit(networkType string) func(dc driverapi.DriverCallback, config map[string]interface{}) error {
return func(dc driverapi.DriverCallback, config map[string]interface{}) error {
func GetInit(networkType string) func(dc driverapi.Registerer, config map[string]interface{}) error {
return func(dc driverapi.Registerer, config map[string]interface{}) error {
if !IsBuiltinLocalDriver(networkType) {
return types.BadRequestErrorf("Network type not supported: %s", networkType)
}

View file

@ -2,12 +2,10 @@ package libnetwork
import (
"github.com/docker/docker/libnetwork/drivers/null"
"github.com/docker/docker/libnetwork/drivers/remote"
)
func getInitializers() []initializer {
return []initializer{
{null.Init, "null"},
{remote.Init, "remote"},
{null.Register, "null"},
}
}

View file

@ -7,18 +7,16 @@ import (
"github.com/docker/docker/libnetwork/drivers/macvlan"
"github.com/docker/docker/libnetwork/drivers/null"
"github.com/docker/docker/libnetwork/drivers/overlay"
"github.com/docker/docker/libnetwork/drivers/remote"
)
func getInitializers() []initializer {
in := []initializer{
{bridge.Init, "bridge"},
{host.Init, "host"},
{ipvlan.Init, "ipvlan"},
{macvlan.Init, "macvlan"},
{null.Init, "null"},
{overlay.Init, "overlay"},
{remote.Init, "remote"},
{bridge.Register, "bridge"},
{host.Register, "host"},
{ipvlan.Register, "ipvlan"},
{macvlan.Register, "macvlan"},
{null.Register, "null"},
{overlay.Register, "overlay"},
}
return in
}

View file

@ -2,16 +2,14 @@ package libnetwork
import (
"github.com/docker/docker/libnetwork/drivers/null"
"github.com/docker/docker/libnetwork/drivers/remote"
"github.com/docker/docker/libnetwork/drivers/windows"
"github.com/docker/docker/libnetwork/drivers/windows/overlay"
)
func getInitializers() []initializer {
return []initializer{
{null.Init, "null"},
{overlay.Init, "overlay"},
{remote.Init, "remote"},
{null.Register, "null"},
{overlay.Register, "overlay"},
{windows.GetInit("transparent"), "transparent"},
{windows.GetInit("l2bridge"), "l2bridge"},
{windows.GetInit("l2tunnel"), "l2tunnel"},

View file

@ -576,7 +576,7 @@ func TestIpamReleaseOnNetDriverFailures(t *testing.T) {
}
defer c.Stop()
if err := c.drvRegistry.AddDriver(badDriverName, badDriverInit, nil); err != nil {
if err := badDriverRegister(&c.drvRegistry); err != nil {
t.Fatal(err)
}
@ -643,7 +643,7 @@ type badDriver struct {
var bd = badDriver{failNetworkCreation: true}
func badDriverInit(reg driverapi.DriverCallback, opt map[string]interface{}) error {
func badDriverRegister(reg driverapi.Registerer) error {
return reg.RegisterDriver(badDriverName, &bd, driverapi.Capability{DataScope: datastore.LocalScope})
}

View file

@ -916,7 +916,7 @@ func NetworkDeleteOptionRemoveLB(p *networkDeleteParams) {
p.rmLBEndpoint = true
}
func (n *network) resolveDriver(name string, load bool) (driverapi.Driver, *driverapi.Capability, error) {
func (n *network) resolveDriver(name string, load bool) (driverapi.Driver, driverapi.Capability, error) {
c := n.getController()
// Check if a driver for the specified network type is available
@ -925,16 +925,16 @@ func (n *network) resolveDriver(name string, load bool) (driverapi.Driver, *driv
if load {
err := c.loadDriver(name)
if err != nil {
return nil, nil, err
return nil, driverapi.Capability{}, err
}
d, cap = c.drvRegistry.Driver(name)
if d == nil {
return nil, nil, fmt.Errorf("could not resolve driver %s in registry", name)
return nil, driverapi.Capability{}, fmt.Errorf("could not resolve driver %s in registry", name)
}
} else {
// don't fail if driver loading is not required
return nil, nil, nil
return nil, driverapi.Capability{}, nil
}
}
@ -957,7 +957,7 @@ func (n *network) driver(load bool) (driverapi.Driver, error) {
n.mu.Lock()
// If load is not required, driver, cap and err may all be nil
if n.scope == "" && cap != nil {
if n.scope == "" {
n.scope = cap.DataScope
}
if n.dynamic {
@ -1772,7 +1772,11 @@ func (n *network) getIPData(ipVer int) []driverapi.IPAMData {
}
func (n *network) deriveAddressSpace() (string, error) {
local, global, err := n.getController().drvRegistry.IPAMDefaultAddressSpaces(n.ipamType)
ipam, _ := n.getController().ipamRegistry.IPAM(n.ipamType)
if ipam == nil {
return "", types.NotFoundErrorf("failed to get default address space: unknown ipam type %q", n.ipamType)
}
local, global, err := ipam.GetDefaultAddressSpaces()
if err != nil {
return "", types.NotFoundErrorf("failed to get default address space: %v", err)
}