diff --git a/README.md b/README.md
index 453f3ccf..2e1adff8 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ it locally to control a weave network on a remote host.
## Quick Start Screencast
-
+
diff --git a/circle.yml b/circle.yml
index 7b23b9f1..4bc4d29b 100644
--- a/circle.yml
+++ b/circle.yml
@@ -41,9 +41,9 @@ test:
parallel: true
- cd $SRCDIR/test; ./gce.sh setup:
parallel: true
- - cd $SRCDIR/test; . ./gce.sh hosts; ./setup.sh:
+ - cd $SRCDIR/test; eval $(./gce.sh hosts); ./setup.sh:
parallel: true
- - cd $SRCDIR/test; . ./gce.sh hosts; export COVERAGE=true; ./run_all.sh:
+ - cd $SRCDIR/test; eval $(./gce.sh hosts); export COVERAGE=true; ./run_all.sh:
parallel: true
timeout: 300
post:
diff --git a/docs/hello-screencast.png b/docs/hello-screencast.png
index 70ac6ed3..1833429e 100644
Binary files a/docs/hello-screencast.png and b/docs/hello-screencast.png differ
diff --git a/nameserver/nameserver.go b/nameserver/nameserver.go
index 5a2e7cb0..c6822bec 100644
--- a/nameserver/nameserver.go
+++ b/nameserver/nameserver.go
@@ -137,6 +137,7 @@ func (n *Nameserver) ContainerDied(ident string) error {
}
func (n *Nameserver) PeerGone(peer *router.Peer) {
+ n.infof("peer gone %s", peer.String())
n.Lock()
defer n.Unlock()
n.entries.filter(func(e *Entry) bool {
diff --git a/proxy/create_container_interceptor.go b/proxy/create_container_interceptor.go
index 9381d983..6fa255f8 100644
--- a/proxy/create_container_interceptor.go
+++ b/proxy/create_container_interceptor.go
@@ -25,9 +25,9 @@ type createContainerRequestBody struct {
MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
}
-// Replacement for docker.NoSuchImage, which does not contain the
-// image name, which in turn breaks docker clients post 1.7.0 since
-// they expect the image name to be present in errors.
+// ErrNoSuchImage replaces docker.NoSuchImage, which does not contain the image
+// name, which in turn breaks docker clients post 1.7.0 since they expect the
+// image name to be present in errors.
type ErrNoSuchImage struct {
Name string
}
@@ -48,7 +48,9 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error {
return err
}
- if cidrs, ok := i.proxy.weaveCIDRsFromConfig(container.Config); ok {
+ if cidrs, err := i.proxy.weaveCIDRsFromConfig(container.Config, container.HostConfig); err != nil {
+ Log.Infof("Ignoring container due to %s", err)
+ } else {
Log.Infof("Creating container with WEAVE_CIDR \"%s\"", strings.Join(cidrs, " "))
if container.HostConfig == nil {
container.HostConfig = &docker.HostConfig{}
diff --git a/proxy/create_exec_interceptor.go b/proxy/create_exec_interceptor.go
index 3a1af205..8b89a53a 100644
--- a/proxy/create_exec_interceptor.go
+++ b/proxy/create_exec_interceptor.go
@@ -30,8 +30,10 @@ func (i *createExecInterceptor) InterceptRequest(r *http.Request) error {
}
_, hasWeaveWait := container.Volumes["/w"]
- cidrs, hasCIDRs := i.proxy.weaveCIDRsFromConfig(container.Config)
- if hasCIDRs && hasWeaveWait {
+ cidrs, err := i.proxy.weaveCIDRsFromConfig(container.Config, container.HostConfig)
+ if err != nil {
+ Log.Infof("Ignoring container %s due to %s", container.ID, err)
+ } else if hasWeaveWait {
Log.Infof("Exec in container %s with WEAVE_CIDR \"%s\"", container.ID, strings.Join(cidrs, " "))
cmd := append(weaveWaitEntrypoint, "-s")
options.Cmd = append(cmd, options.Cmd...)
diff --git a/proxy/proxy.go b/proxy/proxy.go
index 214bff22..5f1bbb06 100644
--- a/proxy/proxy.go
+++ b/proxy/proxy.go
@@ -2,6 +2,7 @@ package proxy
import (
"crypto/tls"
+ "errors"
"fmt"
"net"
"net/http"
@@ -26,6 +27,10 @@ var (
containerCreateRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/create$")
containerStartRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/[^/]*/(re)?start$")
execCreateRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/[^/]*/exec$")
+
+ ErrInvalidNetworkMode = errors.New("--net option")
+ ErrWeaveCIDRNone = errors.New("WEAVE_CIDR=none")
+ ErrNoDefaultIPAM = errors.New("--no-default-ipam option")
)
type Config struct {
@@ -191,14 +196,22 @@ func (proxy *Proxy) listen(protoAndAddr string) (net.Listener, string, error) {
return listener, fmt.Sprintf("%s://%s", proto, addr), nil
}
-func (proxy *Proxy) weaveCIDRsFromConfig(config *docker.Config) ([]string, bool) {
+func (proxy *Proxy) weaveCIDRsFromConfig(config *docker.Config, hostConfig *docker.HostConfig) ([]string, error) {
+ if hostConfig != nil &&
+ hostConfig.NetworkMode != "" &&
+ hostConfig.NetworkMode != "bridge" {
+ return nil, ErrInvalidNetworkMode
+ }
for _, e := range config.Env {
if strings.HasPrefix(e, "WEAVE_CIDR=") {
if e[11:] == "none" {
- return nil, false
+ return nil, ErrWeaveCIDRNone
}
- return strings.Fields(e[11:]), true
+ return strings.Fields(e[11:]), nil
}
}
- return nil, !proxy.NoDefaultIPAM
+ if proxy.NoDefaultIPAM {
+ return nil, ErrNoDefaultIPAM
+ }
+ return nil, nil
}
diff --git a/proxy/start_container_interceptor.go b/proxy/start_container_interceptor.go
index 1a4de456..7353c07e 100644
--- a/proxy/start_container_interceptor.go
+++ b/proxy/start_container_interceptor.go
@@ -21,9 +21,9 @@ func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
return err
}
- cidrs, ok := i.proxy.weaveCIDRsFromConfig(container.Config)
- if !ok {
- Log.Debug("No Weave CIDR, ignoring")
+ cidrs, err := i.proxy.weaveCIDRsFromConfig(container.Config, container.HostConfig)
+ if err != nil {
+ Log.Infof("Ignoring container %s due to %s", container.ID, err)
return nil
}
Log.Infof("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " "))
diff --git a/test/210_dns_cross_hosts_test.sh b/test/210_dns_cross_hosts_test.sh
index 1d936e3e..7f134654 100755
--- a/test/210_dns_cross_hosts_test.sh
+++ b/test/210_dns_cross_hosts_test.sh
@@ -36,6 +36,31 @@ start_container_with_dns $HOST1 --name=baz
assert_dns_record $HOST1 baz foo.weave.local $FOO_IPS
assert_dns_record $HOST1 baz bar.weave.local $BAR_IPS
+# now stop and start the containers a bunch of times
+# this tests gossip dns tombstone behaviour
+for i in $(seq 5); do
+ for host in $HOSTS; do
+ proxy docker_on $host kill foo 1>/dev/null
+ proxy docker_on $host kill bar 1>/dev/null
+ done
+
+ assert_no_dns_record $HOST1 baz foo.weave.local
+ assert_no_dns_record $HOST1 baz bar.weave.local
+
+ FOO_IPS=
+ BAR_IPS=
+ for host in $HOSTS; do
+ proxy docker_on $host start foo 1>/dev/null
+ proxy docker_on $host start bar 1>/dev/null
+
+ FOO_IPS="$FOO_IPS $(container_ip $host foo)"
+ BAR_IPS="$BAR_IPS $(container_ip $host bar)"
+ done
+
+ assert_dns_record $HOST1 baz foo.weave.local $FOO_IPS
+ assert_dns_record $HOST1 baz bar.weave.local $BAR_IPS
+done
+
# resolution for names mapped to multiple addresses
weave_on $HOST2 dns-add $C2a c2 -h $NAME2
weave_on $HOST2 dns-add $C2b c2 -h $NAME2
diff --git a/test/660_proxy_ipam_test.sh b/test/660_proxy_ipam_test.sh
index 0e27b5ec..24c37679 100755
--- a/test/660_proxy_ipam_test.sh
+++ b/test/660_proxy_ipam_test.sh
@@ -26,13 +26,21 @@ start $HOST1 --name=auto
start $HOST1 --name=none -e WEAVE_CIDR=none
start $HOST2 --name=zero -e WEAVE_CIDR=
start $HOST2 --name=no-default
+start $HOST1 --name=bridge --net=bridge
+start $HOST1 --name=host --net=host
+start $HOST1 --name=other --net=container:auto
AUTO=$(container_ip $HOST1 auto)
ZERO=$(container_ip $HOST2 zero)
+BRIDGE=$(container_ip $HOST1 bridge)
+OTHER=$(container_ip $HOST1 other)
assert_raises "proxy exec_on $HOST1 auto $PING $ZERO"
assert_raises "proxy exec_on $HOST2 zero $PING $AUTO"
+assert_raises "proxy exec_on $HOST2 zero $PING $BRIDGE"
+assert_raises "proxy exec_on $HOST2 zero $PING $OTHER"
assert_no_ethwe $HOST1 none
assert_no_ethwe $HOST2 no-default
+assert_no_ethwe $HOST1 host
end_suite
diff --git a/test/gce.sh b/test/gce.sh
index 192af733..dd1cb63b 100755
--- a/test/gce.sh
+++ b/test/gce.sh
@@ -5,7 +5,7 @@
# ./gce.sh destroy - tear down the VMs
# ./gce.sh make_template - make a fresh VM template; update TEMPLATE_NAME first!
-set -ex
+set -e
KEY_FILE=/tmp/gce_private_key.json
SSH_KEY_FILE=$HOME/.ssh/gce_ssh_key
@@ -20,7 +20,7 @@ if [ -n "$CIRCLECI" ]; then
fi
# Setup authentication
-gcloud auth activate-service-account --key-file $KEY_FILE
+gcloud auth activate-service-account --key-file $KEY_FILE 1>/dev/null
gcloud config set project $PROJECT
function vm_names {
@@ -120,9 +120,9 @@ function hosts {
hosts="$hostname $hosts"
args="--add-host=$hostname:$(internal_ip $name) $args"
done
- export SSH=ssh
- export HOSTS="$hosts"
- export WEAVE_DOCKER_ARGS="$args"
+ echo export SSH=ssh
+ echo export HOSTS=\"$hosts\"
+ echo export WEAVE_DOCKER_ARGS=\"$args\"
}
case "$1" in