Merge pull request #561 from mrjana/integ
Introduce end to end overlay integration test
This commit is contained in:
commit
ffb13d6e8d
7 changed files with 207 additions and 47 deletions
|
@ -13,7 +13,7 @@ integration-tests: ./cmd/dnet/dnet
|
|||
@./test/integration/dnet/run-integration-tests.sh
|
||||
|
||||
./cmd/dnet/dnet:
|
||||
make build-local
|
||||
make build
|
||||
|
||||
clean:
|
||||
@if [ -e ./cmd/dnet/dnet ]; then \
|
||||
|
|
|
@ -236,21 +236,22 @@ func (cli *NetworkCli) CmdServiceLs(chain string, args ...string) error {
|
|||
wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
|
||||
// unless quiet (-q) is specified, print field titles
|
||||
if !*quiet {
|
||||
fmt.Fprintln(wr, "SERVICE ID\tNAME\tNETWORK\tCONTAINER")
|
||||
fmt.Fprintln(wr, "SERVICE ID\tNAME\tNETWORK\tCONTAINER\tSANDBOX")
|
||||
}
|
||||
|
||||
for _, sr := range serviceResources {
|
||||
ID := sr.ID
|
||||
bkID, err := getBackendID(cli, ID)
|
||||
bkID, sbID, err := getBackendID(cli, ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !*noTrunc {
|
||||
ID = stringid.TruncateID(ID)
|
||||
bkID = stringid.TruncateID(bkID)
|
||||
sbID = stringid.TruncateID(sbID)
|
||||
}
|
||||
if !*quiet {
|
||||
fmt.Fprintf(wr, "%s\t%s\t%s\t%s\n", ID, sr.Name, sr.Network, bkID)
|
||||
fmt.Fprintf(wr, "%s\t%s\t%s\t%s\t%s\n", ID, sr.Name, sr.Network, bkID, sbID)
|
||||
} else {
|
||||
fmt.Fprintln(wr, ID)
|
||||
}
|
||||
|
@ -260,24 +261,26 @@ func (cli *NetworkCli) CmdServiceLs(chain string, args ...string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getBackendID(cli *NetworkCli, servID string) (string, error) {
|
||||
func getBackendID(cli *NetworkCli, servID string) (string, string, error) {
|
||||
var (
|
||||
obj []byte
|
||||
err error
|
||||
bk string
|
||||
sb string
|
||||
)
|
||||
|
||||
if obj, _, err = readBody(cli.call("GET", "/services/"+servID+"/backend", nil, nil)); err == nil {
|
||||
var sr SandboxResource
|
||||
if err := json.NewDecoder(bytes.NewReader(obj)).Decode(&sr); err == nil {
|
||||
bk = sr.ContainerID
|
||||
sb = sr.ID
|
||||
} else {
|
||||
// Only print a message, don't make the caller cli fail for this
|
||||
fmt.Fprintf(cli.out, "Failed to retrieve backend list for service %s (%v)\n", servID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return bk, err
|
||||
return bk, sb, err
|
||||
}
|
||||
|
||||
// CmdServiceInfo handles service info UI
|
||||
|
|
|
@ -9,7 +9,9 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
|
@ -165,9 +167,24 @@ func (d *dnetConnection) dnetDaemon(cfgFile string) error {
|
|||
post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
|
||||
post = r.PathPrefix("/sandboxes").Subrouter()
|
||||
post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
|
||||
|
||||
handleSignals(controller)
|
||||
|
||||
return http.ListenAndServe(d.addr, r)
|
||||
}
|
||||
|
||||
func handleSignals(controller libnetwork.NetworkController) {
|
||||
c := make(chan os.Signal, 1)
|
||||
signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}
|
||||
signal.Notify(c, signals...)
|
||||
go func() {
|
||||
for _ = range c {
|
||||
controller.Stop()
|
||||
os.Exit(0)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func startTestDriver() error {
|
||||
mux := http.NewServeMux()
|
||||
server := httptest.NewServer(mux)
|
||||
|
|
|
@ -54,16 +54,15 @@ func (sb *sandbox) processOptions(options ...SandboxOption) {
|
|||
type epHeap []*endpoint
|
||||
|
||||
type sandbox struct {
|
||||
id string
|
||||
containerID string
|
||||
config containerConfig
|
||||
osSbox osl.Sandbox
|
||||
controller *controller
|
||||
refCnt int
|
||||
endpoints epHeap
|
||||
epPriority map[string]int
|
||||
//hostsPath string
|
||||
//resolvConfPath string
|
||||
id string
|
||||
containerID string
|
||||
config containerConfig
|
||||
osSbox osl.Sandbox
|
||||
controller *controller
|
||||
refCnt int
|
||||
hostsOnce sync.Once
|
||||
endpoints epHeap
|
||||
epPriority map[string]int
|
||||
joinLeaveDone chan struct{}
|
||||
sync.Mutex
|
||||
}
|
||||
|
@ -460,22 +459,47 @@ func (sb *sandbox) buildHostsFile() error {
|
|||
}
|
||||
|
||||
func (sb *sandbox) updateHostsFile(ifaceIP string, svcRecords []etchosts.Record) error {
|
||||
var err error
|
||||
|
||||
if sb.config.originHostsPath != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Rebuild the hosts file accounting for the passed interface IP and service records
|
||||
extraContent := make([]etchosts.Record, 0, len(sb.config.extraHosts)+len(svcRecords))
|
||||
max := func(a, b int) int {
|
||||
if a < b {
|
||||
return b
|
||||
}
|
||||
|
||||
for _, extraHost := range sb.config.extraHosts {
|
||||
extraContent = append(extraContent, etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP})
|
||||
return a
|
||||
}
|
||||
|
||||
extraContent := make([]etchosts.Record, 0,
|
||||
max(len(sb.config.extraHosts), len(svcRecords)))
|
||||
|
||||
sb.hostsOnce.Do(func() {
|
||||
// Rebuild the hosts file accounting for the passed
|
||||
// interface IP and service records
|
||||
|
||||
for _, extraHost := range sb.config.extraHosts {
|
||||
extraContent = append(extraContent,
|
||||
etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP})
|
||||
}
|
||||
|
||||
err = etchosts.Build(sb.config.hostsPath, ifaceIP,
|
||||
sb.config.hostName, sb.config.domainName, extraContent)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
extraContent = extraContent[:0]
|
||||
for _, svc := range svcRecords {
|
||||
extraContent = append(extraContent, svc)
|
||||
}
|
||||
|
||||
return etchosts.Build(sb.config.hostsPath, ifaceIP, sb.config.hostName, sb.config.domainName, extraContent)
|
||||
sb.addHostsEntries(extraContent)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sb *sandbox) addHostsEntries(recs []etchosts.Record) {
|
||||
|
|
|
@ -28,20 +28,40 @@ function stop_consul() {
|
|||
}
|
||||
|
||||
function start_dnet() {
|
||||
stop_dnet $1 $2
|
||||
name=$(dnet_container_name $1 $2)
|
||||
if [ -z "$3" ]
|
||||
then
|
||||
hport=$((41000+${1}-1))
|
||||
cport=2385
|
||||
hopt=""
|
||||
else
|
||||
hport=$3
|
||||
cport=$3
|
||||
hopt="-H tcp://0.0.0.0:${cport}"
|
||||
fi
|
||||
inst=$1
|
||||
shift
|
||||
suffix=$1
|
||||
shift
|
||||
|
||||
stop_dnet ${inst} ${suffix}
|
||||
name=$(dnet_container_name ${inst} ${suffix})
|
||||
|
||||
hport=$((41000+${inst}-1))
|
||||
cport=2385
|
||||
hopt=""
|
||||
isnum='^[0-9]+$'
|
||||
|
||||
while [ -n "$1" ]
|
||||
do
|
||||
if [[ "$1" =~ ^[0-9]+$ ]]
|
||||
then
|
||||
hport=$1
|
||||
cport=$1
|
||||
hopt="-H tcp://0.0.0.0:${cport}"
|
||||
else
|
||||
neighip=$1
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
bridge_ip=$(docker inspect --format '{{.NetworkSettings.Gateway}}' pr_consul)
|
||||
|
||||
if [ -z "$neighip" ]; then
|
||||
labels="\"com.docker.network.driver.overlay.bind_interface=eth0\""
|
||||
else
|
||||
labels="\"com.docker.network.driver.overlay.bind_interface=eth0\", \"com.docker.network.driver.overlay.neighbor_ip=${neighip}\""
|
||||
fi
|
||||
|
||||
mkdir -p /tmp/dnet/${name}
|
||||
tomlfile="/tmp/dnet/${name}/libnetwork.toml"
|
||||
cat > ${tomlfile} <<EOF
|
||||
|
@ -49,13 +69,14 @@ title = "LibNetwork Configuration file"
|
|||
|
||||
[daemon]
|
||||
debug = false
|
||||
labels = ["com.docker.network.driver.overlay.bind_interface=eth0"]
|
||||
labels = [${labels}]
|
||||
[globalstore]
|
||||
embedded = false
|
||||
[globalstore.client]
|
||||
provider = "consul"
|
||||
Address = "${bridge_ip}:8500"
|
||||
EOF
|
||||
echo "parsed values: " ${name} ${hport} ${cport} ${hopt}
|
||||
docker run \
|
||||
-d \
|
||||
--name=${name} \
|
||||
|
@ -63,6 +84,8 @@ EOF
|
|||
-p ${hport}:${cport} \
|
||||
-v $(pwd)/:/go/src/github.com/docker/libnetwork \
|
||||
-v /tmp:/tmp \
|
||||
-v $(pwd)/${TMPC_ROOT}:/scratch \
|
||||
-v /usr/local/bin/runc:/usr/local/bin/runc \
|
||||
-w /go/src/github.com/docker/libnetwork \
|
||||
golang:1.4 ./cmd/dnet/dnet -d -D ${hopt} -c ${tomlfile}
|
||||
sleep 2
|
||||
|
@ -89,3 +112,17 @@ function dnet_cmd() {
|
|||
shift
|
||||
./cmd/dnet/dnet -H tcp://127.0.0.1:${hport} $*
|
||||
}
|
||||
|
||||
function dnet_exec() {
|
||||
docker exec -it ${1} bash -c "$2"
|
||||
}
|
||||
|
||||
function runc() {
|
||||
dnet=${1}
|
||||
shift
|
||||
dnet_exec ${dnet} "cp /var/lib/docker/network/files/${1}*/* /scratch/rootfs/etc"
|
||||
dnet_exec ${dnet} "mkdir -p /var/run/netns"
|
||||
dnet_exec ${dnet} "touch /var/run/netns/c && mount -o bind /var/run/docker/netns/${1} /var/run/netns/c"
|
||||
dnet_exec ${dnet} "ip netns exec c unshare -fmuip --mount-proc chroot \"/scratch/rootfs\" /bin/sh -c \"/bin/mount -t proc proc /proc && ${2}\""
|
||||
dnet_exec ${dnet} "umount /var/run/netns/c && rm /var/run/netns/c"
|
||||
}
|
||||
|
|
49
libnetwork/test/integration/dnet/overlay.bats
Normal file
49
libnetwork/test/integration/dnet/overlay.bats
Normal file
|
@ -0,0 +1,49 @@
|
|||
# -*- mode: sh -*-
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
@test "Test overlay network" {
|
||||
skip_for_circleci
|
||||
|
||||
echo $(docker ps)
|
||||
|
||||
start=1
|
||||
end=3
|
||||
# Setup overlay network and connect containers ot it
|
||||
dnet_cmd $(inst_id2port 1) network create -d overlay multihost
|
||||
for i in `seq ${start} ${end}`;
|
||||
do
|
||||
osvc="svc$i"
|
||||
dnet_cmd $(inst_id2port $i) service publish ${osvc}.multihost
|
||||
dnet_cmd $(inst_id2port $i) container create container_${i}
|
||||
dnet_cmd $(inst_id2port $i) service attach container_${i} ${osvc}.multihost
|
||||
done
|
||||
|
||||
# Now test connectivity between all the containers using service names
|
||||
for i in `seq ${start} ${end}`;
|
||||
do
|
||||
src="svc$i"
|
||||
line=$(dnet_cmd $(inst_id2port $i) service ls | grep ${src})
|
||||
echo ${line}
|
||||
sbid=$(echo ${line} | cut -d" " -f5)
|
||||
for j in `seq ${start} ${end}`;
|
||||
do
|
||||
if [ "$i" -eq "$j" ]; then
|
||||
continue
|
||||
fi
|
||||
runc $(dnet_container_name $i overlay) ${sbid} "ping -c 1 svc$j"
|
||||
done
|
||||
done
|
||||
|
||||
# Teardown the container connections and the network
|
||||
for i in `seq ${start} ${end}`;
|
||||
do
|
||||
osvc="svc$i"
|
||||
dnet_cmd $(inst_id2port $i) service detach container_${i} ${osvc}.multihost
|
||||
dnet_cmd $(inst_id2port $i) container rm container_${i}
|
||||
dnet_cmd $(inst_id2port $i) service unpublish ${osvc}.multihost
|
||||
done
|
||||
|
||||
run dnet_cmd $(inst_id2port 2) network rm multihost
|
||||
}
|
|
@ -2,12 +2,23 @@
|
|||
|
||||
set -e
|
||||
|
||||
if [ ! -d ./integration-tmp ]; then
|
||||
mkdir -p ./integration-tmp
|
||||
git clone https://github.com/sstephenson/bats.git ./integration-tmp/bats
|
||||
export INTEGRATION_ROOT=./integration-tmp
|
||||
export TMPC_ROOT=./integration-tmp/tmpc
|
||||
|
||||
if [ ! -d ${INTEGRATION_ROOT} ]; then
|
||||
mkdir -p ${INTEGRATION_ROOT}
|
||||
git clone https://github.com/sstephenson/bats.git ${INTEGRATION_ROOT}/bats
|
||||
./integration-tmp/bats/install.sh ./integration-tmp
|
||||
fi
|
||||
|
||||
if [ ! -d ${TMPC_ROOT} ]; then
|
||||
mkdir -p ${TMPC_ROOT}
|
||||
docker pull busybox:ubuntu
|
||||
docker export $(docker create busybox:ubuntu) > ${TMPC_ROOT}/busybox.tar
|
||||
mkdir -p ${TMPC_ROOT}/rootfs
|
||||
tar -C ${TMPC_ROOT}/rootfs -xf ${TMPC_ROOT}/busybox.tar
|
||||
fi
|
||||
|
||||
declare -A cmap
|
||||
|
||||
trap "cleanup_containers" EXIT SIGINT
|
||||
|
@ -27,7 +38,7 @@ function cleanup_containers() {
|
|||
source ./test/integration/dnet/helpers.bash
|
||||
|
||||
# Suite setup
|
||||
start_consul 1>/dev/null 2>&1
|
||||
start_consul 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
cmap[pr_consul]=pr_consul
|
||||
|
||||
# Test dnet configuration options
|
||||
|
@ -36,37 +47,56 @@ cmap[pr_consul]=pr_consul
|
|||
# Test a single node configuration with a global scope test driver
|
||||
|
||||
## Setup
|
||||
start_dnet 1 simple 1>/dev/null 2>&1
|
||||
start_dnet 1 simple 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
cmap[dnet-1-simple]=dnet-1-simple
|
||||
|
||||
## Run the test cases
|
||||
./integration-tmp/bin/bats ./test/integration/dnet/simple.bats
|
||||
|
||||
## Teardown
|
||||
stop_dnet 1 simple 1>/dev/null 2>&1
|
||||
stop_dnet 1 simple 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
unset cmap[dnet-1-simple]
|
||||
|
||||
# Test multi node configuration with a global scope test driver
|
||||
|
||||
## Setup
|
||||
start_dnet 1 multi 1>/dev/null 2>&1
|
||||
start_dnet 1 multi 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
cmap[dnet-1-multi]=dnet-1-multi
|
||||
start_dnet 2 multi 1>/dev/null 2>&1
|
||||
start_dnet 2 multi 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
cmap[dnet-2-multi]=dnet-2-multi
|
||||
start_dnet 3 multi 1>/dev/null 2>&1
|
||||
start_dnet 3 multi 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
cmap[dnet-3-multi]=dnet-3-multi
|
||||
|
||||
## Run the test cases
|
||||
./integration-tmp/bin/bats ./test/integration/dnet/multi.bats
|
||||
|
||||
## Teardown
|
||||
stop_dnet 1 multi 1>/dev/null 2>&1
|
||||
stop_dnet 1 multi 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
unset cmap[dnet-1-multi]
|
||||
stop_dnet 2 multi 1>/dev/null 2>&1
|
||||
stop_dnet 2 multi 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
unset cmap[dnet-2-multi]
|
||||
stop_dnet 3 multi 1>/dev/null 2>&1
|
||||
stop_dnet 3 multi 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
unset cmap[dnet-3-multi]
|
||||
|
||||
## Setup
|
||||
start_dnet 1 overlay 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
cmap[dnet-1-overlay]=dnet-1-overlay
|
||||
start_dnet 2 overlay $(docker inspect --format '{{.NetworkSettings.IPAddress}}' dnet-1-overlay) 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
cmap[dnet-2-overlay]=dnet-2-overlay
|
||||
start_dnet 3 overlay $(docker inspect --format '{{.NetworkSettings.IPAddress}}' dnet-2-overlay) 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
cmap[dnet-3-overlay]=dnet-3-overlay
|
||||
|
||||
## Run the test cases
|
||||
./integration-tmp/bin/bats ./test/integration/dnet/overlay.bats
|
||||
|
||||
## Teardown
|
||||
stop_dnet 1 overlay 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
unset cmap[dnet-1-overlay]
|
||||
stop_dnet 2 overlay 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
unset cmap[dnet-2-overlay]
|
||||
stop_dnet 3 overlay 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
unset cmap[dnet-3-overlay]
|
||||
|
||||
# Suite teardowm
|
||||
stop_consul 1>/dev/null 2>&1
|
||||
stop_consul 1>>${INTEGRATION_ROOT}/test.log 2>&1
|
||||
unset cmap[pr_consul]
|
||||
|
|
Loading…
Add table
Reference in a new issue