Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
package remote
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2015-09-30 11:16:58 -04:00
|
|
|
"io/ioutil"
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
"net"
|
|
|
|
"net/http"
|
2015-09-30 11:16:58 -04:00
|
|
|
"net/http/httptest"
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/docker/docker/pkg/plugins"
|
2015-09-16 07:42:35 -04:00
|
|
|
"github.com/docker/libnetwork/datastore"
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
"github.com/docker/libnetwork/driverapi"
|
2015-09-07 13:33:28 -04:00
|
|
|
_ "github.com/docker/libnetwork/testutils"
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
"github.com/docker/libnetwork/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
func decodeToMap(r *http.Request) (res map[string]interface{}, err error) {
|
|
|
|
err = json.NewDecoder(r.Body).Decode(&res)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func handle(t *testing.T, mux *http.ServeMux, method string, h func(map[string]interface{}) interface{}) {
|
|
|
|
mux.HandleFunc(fmt.Sprintf("/%s.%s", driverapi.NetworkPluginEndpointType, method), func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
ask, err := decodeToMap(r)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
answer := h(ask)
|
|
|
|
err = json.NewEncoder(w).Encode(&answer)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupPlugin(t *testing.T, name string, mux *http.ServeMux) func() {
|
2015-09-30 11:16:58 -04:00
|
|
|
if err := os.MkdirAll("/etc/docker/plugins", 0755); err != nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-09-30 11:16:58 -04:00
|
|
|
server := httptest.NewServer(mux)
|
|
|
|
if server == nil {
|
|
|
|
t.Fatal("Failed to start a HTTP Server")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := ioutil.WriteFile(fmt.Sprintf("/etc/docker/plugins/%s.spec", name), []byte(server.URL), 0644); err != nil {
|
|
|
|
t.Fatal(err)
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
|
2015-09-30 11:16:58 -04:00
|
|
|
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
fmt.Fprintf(w, `{"Implements": ["%s"]}`, driverapi.NetworkPluginEndpointType)
|
|
|
|
})
|
|
|
|
|
|
|
|
return func() {
|
2015-09-30 11:16:58 -04:00
|
|
|
if err := os.RemoveAll("/etc/docker/plugins"); err != nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-09-30 11:16:58 -04:00
|
|
|
server.Close()
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type testEndpoint struct {
|
|
|
|
t *testing.T
|
|
|
|
src string
|
|
|
|
dst string
|
|
|
|
address string
|
|
|
|
addressIPv6 string
|
|
|
|
macAddress string
|
|
|
|
gateway string
|
|
|
|
gatewayIPv6 string
|
|
|
|
resolvConfPath string
|
|
|
|
hostsPath string
|
2015-05-27 21:39:46 -04:00
|
|
|
nextHop string
|
|
|
|
destination string
|
|
|
|
routeType int
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
|
2015-09-09 19:06:35 -04:00
|
|
|
func (test *testEndpoint) Interface() driverapi.InterfaceInfo {
|
|
|
|
return nil
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
|
2015-09-09 19:06:35 -04:00
|
|
|
func (test *testEndpoint) AddInterface(mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
ip4, net4, _ := net.ParseCIDR(test.address)
|
|
|
|
ip6, net6, _ := net.ParseCIDR(test.addressIPv6)
|
|
|
|
if ip4 != nil {
|
|
|
|
net4.IP = ip4
|
|
|
|
if !types.CompareIPNet(net4, &ipv4) {
|
|
|
|
test.t.Fatalf("Wrong address given %+v", ipv4)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ip6 != nil {
|
|
|
|
net6.IP = ip6
|
|
|
|
if !types.CompareIPNet(net6, &ipv6) {
|
|
|
|
test.t.Fatalf("Wrong address (IPv6) given %+v", ipv6)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if test.macAddress != "" && mac.String() != test.macAddress {
|
|
|
|
test.t.Fatalf("Wrong MAC address given %v", mac)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-09-09 19:06:35 -04:00
|
|
|
func (test *testEndpoint) InterfaceName() driverapi.InterfaceNameInfo {
|
|
|
|
return test
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func compareIPs(t *testing.T, kind string, shouldBe string, supplied net.IP) {
|
|
|
|
ip := net.ParseIP(shouldBe)
|
|
|
|
if ip == nil {
|
|
|
|
t.Fatalf(`Invalid IP to test against: "%s"`, shouldBe)
|
|
|
|
}
|
|
|
|
if !ip.Equal(supplied) {
|
|
|
|
t.Fatalf(`%s IPs are not equal: expected "%s", got %v`, kind, shouldBe, supplied)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-27 21:39:46 -04:00
|
|
|
func compareIPNets(t *testing.T, kind string, shouldBe string, supplied net.IPNet) {
|
|
|
|
_, net, _ := net.ParseCIDR(shouldBe)
|
|
|
|
if net == nil {
|
|
|
|
t.Fatalf(`Invalid IP network to test against: "%s"`, shouldBe)
|
|
|
|
}
|
|
|
|
if !types.CompareIPNet(net, &supplied) {
|
|
|
|
t.Fatalf(`%s IP networks are not equal: expected "%s", got %v`, kind, shouldBe, supplied)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
func (test *testEndpoint) SetGateway(ipv4 net.IP) error {
|
|
|
|
compareIPs(test.t, "Gateway", test.gateway, ipv4)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (test *testEndpoint) SetGatewayIPv6(ipv6 net.IP) error {
|
|
|
|
compareIPs(test.t, "GatewayIPv6", test.gatewayIPv6, ipv6)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (test *testEndpoint) SetNames(src string, dst string) error {
|
|
|
|
if test.src != src {
|
|
|
|
test.t.Fatalf(`Wrong SrcName; expected "%s", got "%s"`, test.src, src)
|
|
|
|
}
|
|
|
|
if test.dst != dst {
|
2015-06-01 18:35:57 -04:00
|
|
|
test.t.Fatalf(`Wrong DstPrefix; expected "%s", got "%s"`, test.dst, dst)
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-09-09 19:06:35 -04:00
|
|
|
func (test *testEndpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error {
|
2015-05-27 21:39:46 -04:00
|
|
|
compareIPNets(test.t, "Destination", test.destination, *destination)
|
|
|
|
compareIPs(test.t, "NextHop", test.nextHop, nextHop)
|
|
|
|
|
|
|
|
if test.routeType != routeType {
|
|
|
|
test.t.Fatalf(`Wrong RouteType; expected "%d", got "%d"`, test.routeType, routeType)
|
|
|
|
}
|
|
|
|
|
2015-05-19 20:08:56 -04:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-09-13 08:00:05 -04:00
|
|
|
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)
|
2015-09-16 07:42:35 -04:00
|
|
|
} else if c.DataScope != datastore.LocalScope {
|
|
|
|
t.Fatalf("get capability '%s', expecting 'local'", c.DataScope)
|
2015-09-13 08:00:05 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
func TestRemoteDriver(t *testing.T) {
|
|
|
|
var plugin = "test-net-driver"
|
|
|
|
|
|
|
|
ep := &testEndpoint{
|
|
|
|
t: t,
|
|
|
|
src: "vethsrc",
|
|
|
|
dst: "vethdst",
|
|
|
|
address: "192.168.5.7/16",
|
|
|
|
addressIPv6: "2001:DB8::5:7/48",
|
|
|
|
macAddress: "7a:56:78:34:12:da",
|
|
|
|
gateway: "192.168.0.1",
|
|
|
|
gatewayIPv6: "2001:DB8::1",
|
|
|
|
hostsPath: "/here/comes/the/host/path",
|
|
|
|
resolvConfPath: "/there/goes/the/resolv/conf",
|
2015-05-27 21:39:46 -04:00
|
|
|
destination: "10.0.0.0/8",
|
|
|
|
nextHop: "10.0.0.1",
|
|
|
|
routeType: 1,
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
defer setupPlugin(t, plugin, mux)()
|
|
|
|
|
|
|
|
var networkID string
|
|
|
|
|
2015-09-13 08:00:05 -04:00
|
|
|
handle(t, mux, "GetCapabilities", func(msg map[string]interface{}) interface{} {
|
|
|
|
return map[string]interface{}{
|
|
|
|
"Scope": "global",
|
|
|
|
}
|
|
|
|
})
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
handle(t, mux, "CreateNetwork", func(msg map[string]interface{}) interface{} {
|
|
|
|
nid := msg["NetworkID"]
|
|
|
|
var ok bool
|
|
|
|
if networkID, ok = nid.(string); !ok {
|
|
|
|
t.Fatal("RPC did not include network ID string")
|
|
|
|
}
|
|
|
|
return map[string]interface{}{}
|
|
|
|
})
|
|
|
|
handle(t, mux, "DeleteNetwork", func(msg map[string]interface{}) interface{} {
|
|
|
|
if nid, ok := msg["NetworkID"]; !ok || nid != networkID {
|
|
|
|
t.Fatal("Network ID missing or does not match that created")
|
|
|
|
}
|
|
|
|
return map[string]interface{}{}
|
|
|
|
})
|
|
|
|
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
|
|
|
iface := map[string]interface{}{
|
|
|
|
"Address": ep.address,
|
|
|
|
"AddressIPv6": ep.addressIPv6,
|
|
|
|
"MacAddress": ep.macAddress,
|
|
|
|
}
|
|
|
|
return map[string]interface{}{
|
2015-09-09 19:06:35 -04:00
|
|
|
"Interface": iface,
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
handle(t, mux, "Join", func(msg map[string]interface{}) interface{} {
|
|
|
|
options := msg["Options"].(map[string]interface{})
|
|
|
|
foo, ok := options["foo"].(string)
|
|
|
|
if !ok || foo != "fooValue" {
|
|
|
|
t.Fatalf("Did not receive expected foo string in request options: %+v", msg)
|
|
|
|
}
|
|
|
|
return map[string]interface{}{
|
|
|
|
"Gateway": ep.gateway,
|
|
|
|
"GatewayIPv6": ep.gatewayIPv6,
|
|
|
|
"HostsPath": ep.hostsPath,
|
|
|
|
"ResolvConfPath": ep.resolvConfPath,
|
2015-09-09 19:06:35 -04:00
|
|
|
"InterfaceName": map[string]interface{}{
|
|
|
|
"SrcName": ep.src,
|
|
|
|
"DstPrefix": ep.dst,
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
},
|
2015-05-27 21:39:46 -04:00
|
|
|
"StaticRoutes": []map[string]interface{}{
|
|
|
|
map[string]interface{}{
|
|
|
|
"Destination": ep.destination,
|
|
|
|
"RouteType": ep.routeType,
|
|
|
|
"NextHop": ep.nextHop,
|
|
|
|
},
|
|
|
|
},
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
handle(t, mux, "Leave", func(msg map[string]interface{}) interface{} {
|
|
|
|
return map[string]string{}
|
|
|
|
})
|
|
|
|
handle(t, mux, "DeleteEndpoint", func(msg map[string]interface{}) interface{} {
|
|
|
|
return map[string]interface{}{}
|
|
|
|
})
|
|
|
|
handle(t, mux, "EndpointOperInfo", func(msg map[string]interface{}) interface{} {
|
|
|
|
return map[string]interface{}{
|
|
|
|
"Value": map[string]string{
|
|
|
|
"Arbitrary": "key",
|
|
|
|
"Value": "pairs?",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-09-13 08:00:05 -04:00
|
|
|
d := newDriver(plugin, p.Client)
|
|
|
|
if d.Type() != plugin {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatal("Driver type does not match that given")
|
|
|
|
}
|
|
|
|
|
2015-09-13 08:00:05 -04:00
|
|
|
c, err := d.(*driver).getCapabilities()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2015-09-16 07:42:35 -04:00
|
|
|
} else if c.DataScope != datastore.GlobalScope {
|
|
|
|
t.Fatalf("get capability '%s', expecting 'global'", c.DataScope)
|
2015-09-13 08:00:05 -04:00
|
|
|
}
|
|
|
|
|
2015-07-02 01:00:48 -04:00
|
|
|
netID := "dummy-network"
|
2015-09-13 08:00:05 -04:00
|
|
|
err = d.CreateNetwork(netID, map[string]interface{}{})
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-02 01:00:48 -04:00
|
|
|
endID := "dummy-endpoint"
|
2015-09-13 08:00:05 -04:00
|
|
|
err = d.CreateEndpoint(netID, endID, ep, map[string]interface{}{})
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
joinOpts := map[string]interface{}{"foo": "fooValue"}
|
2015-09-13 08:00:05 -04:00
|
|
|
err = d.Join(netID, endID, "sandbox-key", ep, joinOpts)
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-09-13 08:00:05 -04:00
|
|
|
if _, err = d.EndpointOperInfo(netID, endID); err != nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-09-13 08:00:05 -04:00
|
|
|
if err = d.Leave(netID, endID); err != nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-09-13 08:00:05 -04:00
|
|
|
if err = d.DeleteEndpoint(netID, endID); err != nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-09-13 08:00:05 -04:00
|
|
|
if err = d.DeleteNetwork(netID); err != nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type failEndpoint struct {
|
|
|
|
t *testing.T
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *failEndpoint) Interfaces() []*driverapi.InterfaceInfo {
|
|
|
|
f.t.Fatal("Unexpected call of Interfaces")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func (f *failEndpoint) AddInterface(int, net.HardwareAddr, net.IPNet, net.IPNet) error {
|
|
|
|
f.t.Fatal("Unexpected call of AddInterface")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDriverError(t *testing.T) {
|
|
|
|
var plugin = "test-net-driver-error"
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
defer setupPlugin(t, plugin, mux)()
|
|
|
|
|
|
|
|
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
|
|
|
return map[string]interface{}{
|
|
|
|
"Err": "this should get raised as an error",
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
driver := newDriver(plugin, p.Client)
|
|
|
|
|
2015-07-02 01:00:48 -04:00
|
|
|
if err := driver.CreateEndpoint("dummy", "dummy", &testEndpoint{t: t}, map[string]interface{}{}); err == nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatalf("Expected error from driver")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMissingValues(t *testing.T) {
|
|
|
|
var plugin = "test-net-driver-missing"
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
defer setupPlugin(t, plugin, mux)()
|
|
|
|
|
|
|
|
ep := &testEndpoint{
|
2015-09-09 19:06:35 -04:00
|
|
|
t: t,
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
|
|
|
iface := map[string]interface{}{
|
|
|
|
"Address": ep.address,
|
|
|
|
"AddressIPv6": ep.addressIPv6,
|
|
|
|
"MacAddress": ep.macAddress,
|
|
|
|
}
|
|
|
|
return map[string]interface{}{
|
|
|
|
"Interfaces": []interface{}{iface},
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
driver := newDriver(plugin, p.Client)
|
|
|
|
|
2015-07-02 01:00:48 -04:00
|
|
|
if err := driver.CreateEndpoint("dummy", "dummy", ep, map[string]interface{}{}); err != nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type rollbackEndpoint struct {
|
|
|
|
}
|
|
|
|
|
2015-09-09 19:06:35 -04:00
|
|
|
func (r *rollbackEndpoint) Interface() driverapi.InterfaceInfo {
|
|
|
|
return nil
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
|
2015-09-09 19:06:35 -04:00
|
|
|
func (r *rollbackEndpoint) AddInterface(_ net.HardwareAddr, _ net.IPNet, _ net.IPNet) error {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
return fmt.Errorf("fail this to trigger a rollback")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRollback(t *testing.T) {
|
|
|
|
var plugin = "test-net-driver-rollback"
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
defer setupPlugin(t, plugin, mux)()
|
|
|
|
|
|
|
|
rolledback := false
|
|
|
|
|
|
|
|
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
|
|
|
iface := map[string]interface{}{
|
|
|
|
"Address": "192.168.4.5/16",
|
|
|
|
"AddressIPv6": "",
|
|
|
|
"MacAddress": "7a:12:34:56:78:90",
|
|
|
|
}
|
|
|
|
return map[string]interface{}{
|
2015-09-09 19:06:35 -04:00
|
|
|
"Interface": interface{}(iface),
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
handle(t, mux, "DeleteEndpoint", func(msg map[string]interface{}) interface{} {
|
|
|
|
rolledback = true
|
|
|
|
return map[string]interface{}{}
|
|
|
|
})
|
|
|
|
|
|
|
|
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
driver := newDriver(plugin, p.Client)
|
|
|
|
|
|
|
|
ep := &rollbackEndpoint{}
|
|
|
|
|
2015-07-02 01:00:48 -04:00
|
|
|
if err := driver.CreateEndpoint("dummy", "dummy", ep, map[string]interface{}{}); err == nil {
|
Remote driver implementation
In essense, this just involves marshalling structs back and forth to a
remote process, via the plugin client. There are a couple of types
that don't JSONify well, notably `net.IPNet`, so there is some
translation to be done.
To conform to the driverapi interface, we must give the list of
endpoint interfaces to the remote process, and let it puzzle out what
it's supposed to do; including the possibility of returning an error.
The constraints on EndpointInfo are enforced by the remote driver
implementation; namely:
* It can't be nil
* If it's got non-empty Interfaces(), the remote process can't put
more in
In the latter case, or if we fail to add an interface for some
(future) reason, we try to roll the endpoint creation back. Likewise
for join -- if we fail to set the fields of the JoinInfo, we roll the
join back by leaving.
Signed-off-by: Michael Bridgen <mikeb@squaremobius.net>
2015-05-16 12:27:21 -04:00
|
|
|
t.Fatalf("Expected error from driver")
|
|
|
|
}
|
|
|
|
if !rolledback {
|
|
|
|
t.Fatalf("Expected to have had DeleteEndpoint called")
|
|
|
|
}
|
|
|
|
}
|