Merge pull request #561 from mrjana/integ

Introduce end to end overlay integration test
This commit is contained in:
Madhu Venugopal 2015-09-24 02:55:21 -07:00
commit ffb13d6e8d
7 changed files with 207 additions and 47 deletions

View file

@ -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 \

View file

@ -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

View file

@ -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)

View file

@ -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) {

View file

@ -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"
}

View 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
}

View file

@ -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]