Преглед изворни кода

Introduce test remote plugin in dnet

There are multiple goals of introducing test driver plugin
  - Need a driver which can be configured to simulate
    different driver behaviors
  - For pure libnetwork multi-host integration testing
    a test driver configured for global scope can be used
    without trying to use a real driver like overlay
    which comes with it's own dependencies which can't
    be satisfied all enviroments(I am looking at you
    circleci)

This PR also makes all test cases that we have so far to be run
in circleci without any skipping needed.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan пре 9 година
родитељ
комит
2479562e72

+ 64 - 0
libnetwork/cmd/dnet/dnet.go

@@ -7,6 +7,7 @@ import (
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
 	"net/http"
 	"net/http"
+	"net/http/httptest"
 	"os"
 	"os"
 	"strings"
 	"strings"
 
 
@@ -19,6 +20,7 @@ import (
 	"github.com/docker/libnetwork"
 	"github.com/docker/libnetwork"
 	"github.com/docker/libnetwork/api"
 	"github.com/docker/libnetwork/api"
 	"github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/config"
+	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/options"
 	"github.com/gorilla/mux"
 	"github.com/gorilla/mux"
@@ -134,6 +136,10 @@ type dnetConnection struct {
 }
 }
 
 
 func (d *dnetConnection) dnetDaemon(cfgFile string) error {
 func (d *dnetConnection) dnetDaemon(cfgFile string) error {
+	if err := startTestDriver(); err != nil {
+		return fmt.Errorf("failed to start test driver: %v\n", err)
+	}
+
 	cfg, err := parseConfig(cfgFile)
 	cfg, err := parseConfig(cfgFile)
 	var cOptions []config.Option
 	var cOptions []config.Option
 	if err == nil {
 	if err == nil {
@@ -162,6 +168,64 @@ func (d *dnetConnection) dnetDaemon(cfgFile string) error {
 	return http.ListenAndServe(d.addr, r)
 	return http.ListenAndServe(d.addr, r)
 }
 }
 
 
+func startTestDriver() error {
+	mux := http.NewServeMux()
+	server := httptest.NewServer(mux)
+	if server == nil {
+		return fmt.Errorf("Failed to start a HTTP Server")
+	}
+
+	mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
+		fmt.Fprintf(w, `{"Implements": ["%s"]}`, driverapi.NetworkPluginEndpointType)
+	})
+
+	mux.HandleFunc(fmt.Sprintf("/%s.GetCapabilities", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
+		fmt.Fprintf(w, `{"Scope":"global"}`)
+	})
+
+	mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
+		fmt.Fprintf(w, "null")
+	})
+
+	mux.HandleFunc(fmt.Sprintf("/%s.DeleteNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
+		fmt.Fprintf(w, "null")
+	})
+
+	mux.HandleFunc(fmt.Sprintf("/%s.CreateEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
+		fmt.Fprintf(w, "null")
+	})
+
+	mux.HandleFunc(fmt.Sprintf("/%s.DeleteEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
+		fmt.Fprintf(w, "null")
+	})
+
+	mux.HandleFunc(fmt.Sprintf("/%s.Join", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
+		fmt.Fprintf(w, "null")
+	})
+
+	mux.HandleFunc(fmt.Sprintf("/%s.Leave", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
+		fmt.Fprintf(w, "null")
+	})
+
+	if err := os.MkdirAll("/usr/share/docker/plugins", 0755); err != nil {
+		return err
+	}
+
+	if err := ioutil.WriteFile("/usr/share/docker/plugins/test.spec", []byte(server.URL), 0644); err != nil {
+		return err
+	}
+
+	return nil
+}
+
 func newDnetConnection(val string) (*dnetConnection, error) {
 func newDnetConnection(val string) (*dnetConnection, error) {
 	url, err := parsers.ParseHost(DefaultHTTPHost, DefaultUnixSocket, val)
 	url, err := parsers.ParseHost(DefaultHTTPHost, DefaultUnixSocket, val)
 	if err != nil {
 	if err != nil {

+ 2 - 2
libnetwork/drivers/remote/driver.go

@@ -192,8 +192,8 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
 	}
 	}
 
 
 	ifaceName := res.InterfaceName
 	ifaceName := res.InterfaceName
-	if ifaceName == nil {
-		return fmt.Errorf("no interface name information received")
+	if jinfo.InterfaceName() != nil && ifaceName == nil {
+		return fmt.Errorf("no interface name information received while one is expected")
 	}
 	}
 
 
 	if iface := jinfo.InterfaceName(); iface != nil {
 	if iface := jinfo.InterfaceName(); iface != nil {

+ 6 - 6
libnetwork/test/integration/dnet/simple.bats

@@ -5,7 +5,7 @@ load helpers
 function setup() {
 function setup() {
     if [ "${BATS_TEST_NUMBER}" -eq 1 ]; then
     if [ "${BATS_TEST_NUMBER}" -eq 1 ]; then
 	start_consul
 	start_consul
-	start_dnet 1 simple multihost overlay
+	start_dnet 1 simple multihost test
     fi
     fi
 }
 }
 
 
@@ -26,12 +26,13 @@ function teardown() {
     driver=$(echo ${lines[1]} | cut -d" " -f3)
     driver=$(echo ${lines[1]} | cut -d" " -f3)
     echo ${name} ${driver}
     echo ${name} ${driver}
     [ "$name" = "multihost" ]
     [ "$name" = "multihost" ]
-    [ "$driver" = "overlay" ]
+    [ "$driver" = "test" ]
 }
 }
 
 
 @test "Test network create" {
 @test "Test network create" {
     echo $(docker ps)
     echo $(docker ps)
-    run dnet_cmd $(inst_id2port 1) network create -d overlay mh1
+    run dnet_cmd $(inst_id2port 1) network create -d test mh1
+    echo ${output}
     [ "$status" -eq 0 ]
     [ "$status" -eq 0 ]
     line=$(dnet_cmd $(inst_id2port 1) network ls | grep mh1)
     line=$(dnet_cmd $(inst_id2port 1) network ls | grep mh1)
     echo ${line}
     echo ${line}
@@ -39,13 +40,13 @@ function teardown() {
     driver=$(echo ${line} | cut -d" " -f3)
     driver=$(echo ${line} | cut -d" " -f3)
     echo ${name} ${driver}
     echo ${name} ${driver}
     [ "$name" = "mh1" ]
     [ "$name" = "mh1" ]
-    [ "$driver" = "overlay" ]
+    [ "$driver" = "test" ]
     dnet_cmd $(inst_id2port 1) network rm mh1
     dnet_cmd $(inst_id2port 1) network rm mh1
 }
 }
 
 
 @test "Test network delete with id" {
 @test "Test network delete with id" {
     echo $(docker ps)
     echo $(docker ps)
-    run dnet_cmd $(inst_id2port 1) network create -d overlay mh1
+    run dnet_cmd $(inst_id2port 1) network create -d test mh1
     [ "$status" -eq 0 ]
     [ "$status" -eq 0 ]
     echo ${output}
     echo ${output}
     dnet_cmd $(inst_id2port 1) network rm ${output}
     dnet_cmd $(inst_id2port 1) network rm ${output}
@@ -82,7 +83,6 @@ function teardown() {
 }
 }
 
 
 @test "Test service attach" {
 @test "Test service attach" {
-    skip_for_circleci
     echo $(docker ps)
     echo $(docker ps)
     dnet_cmd $(inst_id2port 1) service publish svc1.multihost
     dnet_cmd $(inst_id2port 1) service publish svc1.multihost
     dnet_cmd $(inst_id2port 1) container create container_1
     dnet_cmd $(inst_id2port 1) container create container_1