mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add negotiation process for driver scope
Add one capability negotiation interaction after plugin handshake, use this to determine plugin's capability instead of default "global" scope. Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
This commit is contained in:
parent
17f56bac82
commit
304bfd6261
4 changed files with 149 additions and 12 deletions
|
@ -49,6 +49,16 @@ When loaded, a remote driver process receives an HTTP POST on the URL `/Plugin.A
|
|||
|
||||
Other entries in the list value are allowed; `"NetworkDriver"` indicates that the plugin should be registered with LibNetwork as a driver.
|
||||
|
||||
### Set capability
|
||||
|
||||
After Handshake, the remote driver will receive another POST message to the URL `/NetworkDriver.GetCapabilities` with no payload. The driver's response should have the form:
|
||||
|
||||
{
|
||||
"Scope": "local"
|
||||
}
|
||||
|
||||
Value of "Scope" should be either "local" or "global" which indicates the capability of remote driver, values beyond these will fail driver's registration and return an error to the caller.
|
||||
|
||||
### Create network
|
||||
|
||||
When the proxy is asked to create a network, the remote process shall receive a POST to the URL `/NetworkDriver.CreateNetwork` of the form
|
||||
|
|
|
@ -16,6 +16,12 @@ func (r *Response) GetError() string {
|
|||
return r.Err
|
||||
}
|
||||
|
||||
// GetCapabilityResponse is the response of GetCapability request
|
||||
type GetCapabilityResponse struct {
|
||||
Response
|
||||
Scope string
|
||||
}
|
||||
|
||||
// CreateNetworkRequest requests a new network.
|
||||
type CreateNetworkRequest struct {
|
||||
// A network ID that remote plugins are expected to store for future
|
||||
|
|
|
@ -28,16 +28,40 @@ func newDriver(name string, client *plugins.Client) driverapi.Driver {
|
|||
// plugin is activated.
|
||||
func Init(dc driverapi.DriverCallback) error {
|
||||
plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
|
||||
c := driverapi.Capability{
|
||||
Scope: driverapi.GlobalScope,
|
||||
// negotiate driver capability with client
|
||||
d := newDriver(name, client)
|
||||
c, err := d.(*driver).getCapabilities()
|
||||
if err != nil {
|
||||
log.Errorf("error getting capability for %s due to %v", name, err)
|
||||
return
|
||||
}
|
||||
if err := dc.RegisterDriver(name, newDriver(name, client), c); err != nil {
|
||||
if err = dc.RegisterDriver(name, d, *c); err != nil {
|
||||
log.Errorf("error registering driver for %s due to %v", name, err)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get capability from client
|
||||
func (d *driver) getCapabilities() (*driverapi.Capability, error) {
|
||||
var capResp api.GetCapabilityResponse
|
||||
if err := d.call("GetCapabilities", nil, &capResp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &driverapi.Capability{}
|
||||
switch capResp.Scope {
|
||||
case "global":
|
||||
c.Scope = driverapi.GlobalScope
|
||||
case "local":
|
||||
c.Scope = driverapi.LocalScope
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid capability: expecting 'local' or 'global', got %s", capResp.Scope)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Config is not implemented for remote drivers, since it is assumed
|
||||
// to be supplied to the remote process out-of-band (e.g., as command
|
||||
// line arguments).
|
||||
|
|
|
@ -153,6 +153,91 @@ func (test *testEndpoint) AddStaticRoute(destination *net.IPNet, routeType int,
|
|||
return nil
|
||||
}
|
||||
|
||||
func TestGetEmptyCapabilities(t *testing.T) {
|
||||
var plugin = "test-net-driver-empty-cap"
|
||||
|
||||
mux := http.NewServeMux()
|
||||
defer setupPlugin(t, plugin, mux)()
|
||||
|
||||
handle(t, mux, "GetCapabilities", func(msg map[string]interface{}) interface{} {
|
||||
return map[string]interface{}{}
|
||||
})
|
||||
|
||||
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
d := newDriver(plugin, p.Client)
|
||||
if d.Type() != plugin {
|
||||
t.Fatal("Driver type does not match that given")
|
||||
}
|
||||
|
||||
_, err = d.(*driver).getCapabilities()
|
||||
if err == nil {
|
||||
t.Fatal("There should be error reported when get empty capability")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExtraCapabilities(t *testing.T) {
|
||||
var plugin = "test-net-driver-extra-cap"
|
||||
|
||||
mux := http.NewServeMux()
|
||||
defer setupPlugin(t, plugin, mux)()
|
||||
|
||||
handle(t, mux, "GetCapabilities", func(msg map[string]interface{}) interface{} {
|
||||
return map[string]interface{}{
|
||||
"Scope": "local",
|
||||
"foo": "bar",
|
||||
}
|
||||
})
|
||||
|
||||
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
d := newDriver(plugin, p.Client)
|
||||
if d.Type() != plugin {
|
||||
t.Fatal("Driver type does not match that given")
|
||||
}
|
||||
|
||||
c, err := d.(*driver).getCapabilities()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if c.Scope != driverapi.LocalScope {
|
||||
t.Fatalf("get capability '%s', expecting 'local'", c.Scope)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInvalidCapabilities(t *testing.T) {
|
||||
var plugin = "test-net-driver-invalid-cap"
|
||||
|
||||
mux := http.NewServeMux()
|
||||
defer setupPlugin(t, plugin, mux)()
|
||||
|
||||
handle(t, mux, "GetCapabilities", func(msg map[string]interface{}) interface{} {
|
||||
return map[string]interface{}{
|
||||
"Scope": "fake",
|
||||
}
|
||||
})
|
||||
|
||||
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
d := newDriver(plugin, p.Client)
|
||||
if d.Type() != plugin {
|
||||
t.Fatal("Driver type does not match that given")
|
||||
}
|
||||
|
||||
_, err = d.(*driver).getCapabilities()
|
||||
if err == nil {
|
||||
t.Fatal("There should be error reported when get invalid capability")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoteDriver(t *testing.T) {
|
||||
var plugin = "test-net-driver"
|
||||
|
||||
|
@ -177,6 +262,11 @@ func TestRemoteDriver(t *testing.T) {
|
|||
|
||||
var networkID string
|
||||
|
||||
handle(t, mux, "GetCapabilities", func(msg map[string]interface{}) interface{} {
|
||||
return map[string]interface{}{
|
||||
"Scope": "global",
|
||||
}
|
||||
})
|
||||
handle(t, mux, "CreateNetwork", func(msg map[string]interface{}) interface{} {
|
||||
nid := msg["NetworkID"]
|
||||
var ok bool
|
||||
|
@ -245,38 +335,45 @@ func TestRemoteDriver(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
driver := newDriver(plugin, p.Client)
|
||||
if driver.Type() != plugin {
|
||||
d := newDriver(plugin, p.Client)
|
||||
if d.Type() != plugin {
|
||||
t.Fatal("Driver type does not match that given")
|
||||
}
|
||||
|
||||
c, err := d.(*driver).getCapabilities()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if c.Scope != driverapi.GlobalScope {
|
||||
t.Fatalf("get capability '%s', expecting 'global'", c.Scope)
|
||||
}
|
||||
|
||||
netID := "dummy-network"
|
||||
err = driver.CreateNetwork(netID, map[string]interface{}{})
|
||||
err = d.CreateNetwork(netID, map[string]interface{}{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
endID := "dummy-endpoint"
|
||||
err = driver.CreateEndpoint(netID, endID, ep, map[string]interface{}{})
|
||||
err = d.CreateEndpoint(netID, endID, ep, map[string]interface{}{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
joinOpts := map[string]interface{}{"foo": "fooValue"}
|
||||
err = driver.Join(netID, endID, "sandbox-key", ep, joinOpts)
|
||||
err = d.Join(netID, endID, "sandbox-key", ep, joinOpts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = driver.EndpointOperInfo(netID, endID); err != nil {
|
||||
if _, err = d.EndpointOperInfo(netID, endID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = driver.Leave(netID, endID); err != nil {
|
||||
if err = d.Leave(netID, endID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = driver.DeleteEndpoint(netID, endID); err != nil {
|
||||
if err = d.DeleteEndpoint(netID, endID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = driver.DeleteNetwork(netID); err != nil {
|
||||
if err = d.DeleteNetwork(netID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue