浏览代码

libnet: un-plumb datastores from IPAM inits

The datastore arguments to the IPAM driver Init() functions are always
nil, even in Swarmkit. The only IPAM driver which consumed the
datastores was builtin; all others (null, remote, windowsipam) simply
ignored it. As the signatures of the IPAM driver init functions cannot
be changed without breaking the Swarmkit build, they have to be left
with the same signatures for the time being. Assert that nil datastores
are always passed into the builtin IPAM driver's init function so that
there is no ambiguity the datastores are no longer respected.

Add new Register functions for the IPAM drivers which are free from the
legacy baggage of the Init functions. (The legacy Init functions can be
removed once Swarmkit is migrated to using the Register functions.) As
the remote IPAM driver is the only one which depends on a PluginGetter,
pass it in explicitly as an argument to Register. The other IPAM drivers
should not be forced to depend on a GetPluginGetter() method they do not
use (Interface Segregation Principle).

Signed-off-by: Cory Snider <csnider@mirantis.com>
Cory Snider 2 年之前
父节点
当前提交
d478e13639

+ 1 - 1
libnetwork/controller.go

@@ -149,7 +149,7 @@ func New(cfgOptions ...config.Option) (*Controller, error) {
 		}
 		}
 	}
 	}
 
 
-	if err = initIPAMDrivers(drvRegistry, nil, nil, c.cfg.DefaultAddressPool); err != nil {
+	if err = initIPAMDrivers(drvRegistry, c.cfg.PluginGetter, c.cfg.DefaultAddressPool); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 

+ 8 - 8
libnetwork/drivers_ipam.go

@@ -1,30 +1,30 @@
 package libnetwork
 package libnetwork
 
 
 import (
 import (
-	"github.com/docker/docker/libnetwork/drvregistry"
 	"github.com/docker/docker/libnetwork/ipamapi"
 	"github.com/docker/docker/libnetwork/ipamapi"
 	builtinIpam "github.com/docker/docker/libnetwork/ipams/builtin"
 	builtinIpam "github.com/docker/docker/libnetwork/ipams/builtin"
 	nullIpam "github.com/docker/docker/libnetwork/ipams/null"
 	nullIpam "github.com/docker/docker/libnetwork/ipams/null"
 	remoteIpam "github.com/docker/docker/libnetwork/ipams/remote"
 	remoteIpam "github.com/docker/docker/libnetwork/ipams/remote"
 	"github.com/docker/docker/libnetwork/ipamutils"
 	"github.com/docker/docker/libnetwork/ipamutils"
+	"github.com/docker/docker/pkg/plugingetter"
 )
 )
 
 
-func initIPAMDrivers(r *drvregistry.DrvRegistry, lDs, gDs interface{}, addressPool []*ipamutils.NetworkToSplit) error {
+func initIPAMDrivers(r ipamapi.Registerer, pg plugingetter.PluginGetter, addressPool []*ipamutils.NetworkToSplit) error {
 	// TODO: pass address pools as arguments to builtinIpam.Init instead of
 	// TODO: pass address pools as arguments to builtinIpam.Init instead of
 	// indirectly through global mutable state. Swarmkit references that
 	// indirectly through global mutable state. Swarmkit references that
 	// function so changing its signature breaks the build.
 	// function so changing its signature breaks the build.
 	if err := builtinIpam.SetDefaultIPAddressPool(addressPool); err != nil {
 	if err := builtinIpam.SetDefaultIPAddressPool(addressPool); err != nil {
 		return err
 		return err
 	}
 	}
-	for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){
-		builtinIpam.Init,
-		remoteIpam.Init,
-		nullIpam.Init,
+
+	for _, fn := range [](func(ipamapi.Registerer) error){
+		builtinIpam.Register,
+		nullIpam.Register,
 	} {
 	} {
-		if err := fn(r, lDs, gDs); err != nil {
+		if err := fn(r); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
 
 
-	return nil
+	return remoteIpam.Register(r, pg)
 }
 }

+ 6 - 6
libnetwork/drvregistry/drvregistry_test.go

@@ -99,20 +99,20 @@ func getNew(t *testing.T) *DrvRegistry {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	err = initIPAMDrivers(reg, nil, nil)
+	err = initIPAMDrivers(reg)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 	return reg
 	return reg
 }
 }
 
 
-func initIPAMDrivers(r *DrvRegistry, lDs, gDs interface{}) error {
+func initIPAMDrivers(r *DrvRegistry) error {
 	for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){
 	for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){
-		builtinIpam.Init,
-		remoteIpam.Init,
-		nullIpam.Init,
+		builtinIpam.Init, //nolint:staticcheck
+		remoteIpam.Init,  //nolint:staticcheck
+		nullIpam.Init,    //nolint:staticcheck
 	} {
 	} {
-		if err := fn(r, lDs, gDs); err != nil {
+		if err := fn(r, nil, nil); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}

+ 12 - 5
libnetwork/ipamapi/contract.go

@@ -21,14 +21,21 @@ const (
 	RequestAddressType = "RequestAddressType"
 	RequestAddressType = "RequestAddressType"
 )
 )
 
 
-// Callback provides a Callback interface for registering an IPAM instance into LibNetwork
+// Registerer provides a callback interface for registering IPAM instances into libnetwork.
+type Registerer interface {
+	// RegisterIpamDriver provides a way for drivers to dynamically register with libnetwork
+	RegisterIpamDriver(name string, driver Ipam) error
+	// RegisterIpamDriverWithCapabilities provides a way for drivers to dynamically register with libnetwork and specify capabilities
+	RegisterIpamDriverWithCapabilities(name string, driver Ipam, capability *Capability) error
+}
+
+// Callback is a legacy interface for registering an IPAM instance into LibNetwork.
+//
+// The narrower [Registerer] interface is preferred for new code.
 type Callback interface {
 type Callback interface {
+	Registerer
 	// GetPluginGetter returns the pluginv2 getter.
 	// GetPluginGetter returns the pluginv2 getter.
 	GetPluginGetter() plugingetter.PluginGetter
 	GetPluginGetter() plugingetter.PluginGetter
-	// RegisterIpamDriver provides a way for Remote drivers to dynamically register with libnetwork
-	RegisterIpamDriver(name string, driver Ipam) error
-	// RegisterIpamDriverWithCapabilities provides a way for Remote drivers to dynamically register with libnetwork and specify capabilities
-	RegisterIpamDriverWithCapabilities(name string, driver Ipam, capability *Capability) error
 }
 }
 
 
 // Well-known errors returned by IPAM
 // Well-known errors returned by IPAM

+ 3 - 22
libnetwork/ipams/builtin/builtin.go

@@ -1,10 +1,8 @@
 package builtin
 package builtin
 
 
 import (
 import (
-	"errors"
 	"net"
 	"net"
 
 
-	"github.com/docker/docker/libnetwork/datastore"
 	"github.com/docker/docker/libnetwork/ipam"
 	"github.com/docker/docker/libnetwork/ipam"
 	"github.com/docker/docker/libnetwork/ipamapi"
 	"github.com/docker/docker/libnetwork/ipamapi"
 	"github.com/docker/docker/libnetwork/ipamutils"
 	"github.com/docker/docker/libnetwork/ipamutils"
@@ -15,25 +13,8 @@ var (
 	defaultAddressPool []*net.IPNet
 	defaultAddressPool []*net.IPNet
 )
 )
 
 
-// initBuiltin registers the built-in ipam service with libnetwork
-func initBuiltin(ic ipamapi.Callback, l, g interface{}) error {
-	var (
-		ok                bool
-		localDs, globalDs datastore.DataStore
-	)
-
-	if l != nil {
-		if localDs, ok = l.(datastore.DataStore); !ok {
-			return errors.New("incorrect local datastore passed to built-in ipam init")
-		}
-	}
-
-	if g != nil {
-		if globalDs, ok = g.(datastore.DataStore); !ok {
-			return errors.New("incorrect global datastore passed to built-in ipam init")
-		}
-	}
-
+// registerBuiltin registers the built-in ipam driver with libnetwork.
+func registerBuiltin(ic ipamapi.Registerer) error {
 	var localAddressPool []*net.IPNet
 	var localAddressPool []*net.IPNet
 	if len(defaultAddressPool) > 0 {
 	if len(defaultAddressPool) > 0 {
 		localAddressPool = append([]*net.IPNet(nil), defaultAddressPool...)
 		localAddressPool = append([]*net.IPNet(nil), defaultAddressPool...)
@@ -41,7 +22,7 @@ func initBuiltin(ic ipamapi.Callback, l, g interface{}) error {
 		localAddressPool = ipamutils.GetLocalScopeDefaultNetworks()
 		localAddressPool = ipamutils.GetLocalScopeDefaultNetworks()
 	}
 	}
 
 
-	a, err := ipam.NewAllocator(localDs, globalDs, localAddressPool, ipamutils.GetGlobalScopeDefaultNetworks())
+	a, err := ipam.NewAllocator(nil, nil, localAddressPool, ipamutils.GetGlobalScopeDefaultNetworks())
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 21 - 2
libnetwork/ipams/builtin/builtin_unix.go

@@ -3,9 +3,28 @@
 
 
 package builtin
 package builtin
 
 
-import "github.com/docker/docker/libnetwork/ipamapi"
+import (
+	"errors"
+
+	"github.com/docker/docker/libnetwork/ipamapi"
+)
 
 
 // Init registers the built-in ipam service with libnetwork
 // Init registers the built-in ipam service with libnetwork
+//
+// Deprecated: use [Register].
 func Init(ic ipamapi.Callback, l, g interface{}) error {
 func Init(ic ipamapi.Callback, l, g interface{}) error {
-	return initBuiltin(ic, l, g)
+	if l != nil {
+		return errors.New("non-nil local datastore passed to built-in ipam init")
+	}
+
+	if g != nil {
+		return errors.New("non-nil global datastore passed to built-in ipam init")
+	}
+
+	return Register(ic)
+}
+
+// Register registers the built-in ipam service with libnetwork.
+func Register(r ipamapi.Registerer) error {
+	return registerBuiltin(r)
 }
 }

+ 19 - 5
libnetwork/ipams/builtin/builtin_windows.go

@@ -4,18 +4,32 @@
 package builtin
 package builtin
 
 
 import (
 import (
+	"errors"
+
 	"github.com/docker/docker/libnetwork/ipamapi"
 	"github.com/docker/docker/libnetwork/ipamapi"
 	"github.com/docker/docker/libnetwork/ipams/windowsipam"
 	"github.com/docker/docker/libnetwork/ipams/windowsipam"
 )
 )
 
 
-// Init registers the built-in ipam service with libnetwork
+// Init registers the built-in ipam services with libnetwork.
+//
+// Deprecated: use [Register].
 func Init(ic ipamapi.Callback, l, g interface{}) error {
 func Init(ic ipamapi.Callback, l, g interface{}) error {
-	initFunc := windowsipam.GetInit(windowsipam.DefaultIPAM)
+	if l != nil {
+		return errors.New("non-nil local datastore passed to built-in ipam init")
+	}
+
+	if g != nil {
+		return errors.New("non-nil global datastore passed to built-in ipam init")
+	}
+
+	return Register(ic)
+}
 
 
-	err := initBuiltin(ic, l, g)
-	if err != nil {
+// Register registers the built-in ipam services with libnetwork.
+func Register(r ipamapi.Registerer) error {
+	if err := registerBuiltin(r); err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	return initFunc(ic, l, g)
+	return windowsipam.Register(windowsipam.DefaultIPAM, r)
 }
 }

+ 9 - 2
libnetwork/ipams/null/null.go

@@ -69,7 +69,14 @@ func (a *allocator) IsBuiltIn() bool {
 	return true
 	return true
 }
 }
 
 
-// Init registers a remote ipam when its plugin is activated
+// Init registers the null ipam driver with ic.
+//
+// Deprecated: use [Register].
 func Init(ic ipamapi.Callback, l, g interface{}) error {
 func Init(ic ipamapi.Callback, l, g interface{}) error {
-	return ic.RegisterIpamDriver(ipamapi.NullIPAM, &allocator{})
+	return Register(ic)
+}
+
+// Register registers the null ipam driver with r.
+func Register(r ipamapi.Registerer) error {
+	return r.RegisterIpamDriver(ipamapi.NullIPAM, &allocator{})
 }
 }

+ 8 - 2
libnetwork/ipams/remote/remote.go

@@ -30,9 +30,15 @@ func newAllocator(name string, client *plugins.Client) ipamapi.Ipam {
 	return a
 	return a
 }
 }
 
 
-// Init registers a remote ipam when its plugin is activated
+// Init registers a remote ipam when its plugin is activated.
+//
+// Deprecated: use [Register].
 func Init(cb ipamapi.Callback, l, g interface{}) error {
 func Init(cb ipamapi.Callback, l, g interface{}) error {
+	return Register(cb, cb.GetPluginGetter())
+}
 
 
+// Register registers a remote ipam when its plugin is activated.
+func Register(cb ipamapi.Registerer, pg plugingetter.PluginGetter) error {
 	newPluginHandler := func(name string, client *plugins.Client) {
 	newPluginHandler := func(name string, client *plugins.Client) {
 		a := newAllocator(name, client)
 		a := newAllocator(name, client)
 		if cps, err := a.(*allocator).getCapabilities(); err == nil {
 		if cps, err := a.(*allocator).getCapabilities(); err == nil {
@@ -50,7 +56,7 @@ func Init(cb ipamapi.Callback, l, g interface{}) error {
 
 
 	// Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
 	// Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
 	handleFunc := plugins.Handle
 	handleFunc := plugins.Handle
-	if pg := cb.GetPluginGetter(); pg != nil {
+	if pg != nil {
 		handleFunc = pg.Handle
 		handleFunc = pg.Handle
 		activePlugins := pg.GetAllManagedPluginsByCap(ipamapi.PluginEndpointType)
 		activePlugins := pg.GetAllManagedPluginsByCap(ipamapi.PluginEndpointType)
 		for _, ap := range activePlugins {
 		for _, ap := range activePlugins {

+ 3 - 5
libnetwork/ipams/windowsipam/windowsipam.go

@@ -24,11 +24,9 @@ var (
 type allocator struct {
 type allocator struct {
 }
 }
 
 
-// GetInit registers the built-in ipam service with libnetwork
-func GetInit(ipamName string) func(ic ipamapi.Callback, l, g interface{}) error {
-	return func(ic ipamapi.Callback, l, g interface{}) error {
-		return ic.RegisterIpamDriver(ipamName, &allocator{})
-	}
+// Register registers the built-in ipam service with libnetwork
+func Register(ipamName string, r ipamapi.Registerer) error {
+	return r.RegisterIpamDriver(ipamName, &allocator{})
 }
 }
 
 
 func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
 func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {