diff --git a/.gitignore b/.gitignore index a47a726b71..2cefdfb76a 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ prog/weavehosts/weavehosts prog/weaveproxy/weaveproxy prog/sigproxy/sigproxy prog/weavewait/weavewait +prog/weavewait/weavewait_noop prog/netcheck/netcheck prog/docker_tls_args/docker_tls_args testing/cover/cover @@ -52,6 +53,7 @@ prog/weaveexec/weave prog/weaveexec/weavehosts prog/weaveexec/weaveproxy prog/weaveexec/weavewait +prog/weaveexec/weavewait_noop prog/weaveexec/sigproxy prog/weaveexec/netcheck prog/weaveexec/docker_tls_args diff --git a/Makefile b/Makefile index e1ff21565d..a8e6e6f3df 100644 --- a/Makefile +++ b/Makefile @@ -13,11 +13,12 @@ WEAVER_EXE=prog/weaver/weaver WEAVEPROXY_EXE=prog/weaveproxy/weaveproxy SIGPROXY_EXE=prog/sigproxy/sigproxy WEAVEWAIT_EXE=prog/weavewait/weavewait +WEAVEWAIT_NOOP_EXE=prog/weavewait/weavewait_noop NETCHECK_EXE=prog/netcheck/netcheck DOCKERTLSARGS_EXE=prog/docker_tls_args/docker_tls_args RUNNER_EXE=testing/runner/runner -EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE) $(RUNNER_EXE) +EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE) $(RUNNER_EXE) WEAVER_UPTODATE=.weaver.uptodate WEAVEEXEC_UPTODATE=.weaveexec.uptodate @@ -76,7 +77,7 @@ $(NETCHECK_EXE): prog/netcheck/netcheck.go # Sigproxy and weavewait need separate rules as they fail the netgo check in # the main build stanza due to not importing net package $(SIGPROXY_EXE): prog/sigproxy/main.go -$(WEAVEWAIT_EXE): prog/weavewait/main.go net/*.go +$(WEAVEWAIT_EXE): prog/weavewait/*.go net/*.go $(RUNNER_EXE): testing/runner/runner.go $(DOCKERTLSARGS_EXE): prog/docker_tls_args/*.go @@ -84,15 +85,20 @@ $(WEAVEWAIT_EXE) $(SIGPROXY_EXE) $(RUNNER_EXE) $(DOCKERTLSARGS_EXE): go get -tags netgo ./$(@D) go build $(BUILD_FLAGS) -o $@ ./$(@D) +$(WEAVEWAIT_NOOP_EXE): prog/weavewait/*.go + go get -tags netgo ./$(@D) + go build $(BUILD_FLAGS) -tags noop -o $@ ./$(@D) + $(WEAVER_UPTODATE): prog/weaver/Dockerfile $(WEAVER_EXE) $(SUDO) docker build -t $(WEAVER_IMAGE) prog/weaver touch $@ -$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE) +$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE) cp weave prog/weaveexec/weave cp $(SIGPROXY_EXE) prog/weaveexec/sigproxy cp $(WEAVEPROXY_EXE) prog/weaveexec/weaveproxy cp $(WEAVEWAIT_EXE) prog/weaveexec/weavewait + cp $(WEAVEWAIT_NOOP_EXE) prog/weaveexec/weavewait_noop cp $(NETCHECK_EXE) prog/weaveexec/netcheck cp $(DOCKERTLSARGS_EXE) prog/weaveexec/docker_tls_args cp $(DOCKER_DISTRIB) prog/weaveexec/docker.tgz diff --git a/prog/weaveexec/Dockerfile b/prog/weaveexec/Dockerfile index 3cd1972d9a..3003d03eb6 100644 --- a/prog/weaveexec/Dockerfile +++ b/prog/weaveexec/Dockerfile @@ -5,6 +5,7 @@ LABEL works.weave.role=system WORKDIR /home/weave VOLUME /w +VOLUME /w-noop ENTRYPOINT ["/home/weave/sigproxy", "/home/weave/weave"] RUN apk add --update \ @@ -20,4 +21,5 @@ RUN apk add --update \ ADD ./weave ./sigproxy ./weaveproxy /home/weave/ ADD ./netcheck ./docker_tls_args /usr/bin/ ADD ./weavewait /w/w +ADD ./weavewait_noop /w-noop/w ADD ./docker.tgz / diff --git a/prog/weavewait/check_network.go b/prog/weavewait/check_network.go new file mode 100644 index 0000000000..9c17bf8e9f --- /dev/null +++ b/prog/weavewait/check_network.go @@ -0,0 +1,12 @@ +// +build !noop + +package main + +import ( + weavenet "github.com/weaveworks/weave/net" +) + +func checkNetwork() error { + _, err := weavenet.EnsureInterfaceAndMcastRoute("ethwe") + return err +} diff --git a/prog/weavewait/main.go b/prog/weavewait/main.go index 43158e9356..199073f5a5 100644 --- a/prog/weavewait/main.go +++ b/prog/weavewait/main.go @@ -6,8 +6,6 @@ import ( "os" "os/exec" "syscall" - - weavenet "github.com/weaveworks/weave/net" ) var ( @@ -19,8 +17,7 @@ func main() { args = os.Args[1:] ) - _, err := weavenet.EnsureInterfaceAndMcastRoute("ethwe") - checkErr(err) + checkErr(checkNetwork()) if len(args) == 0 { checkErr(ErrNoCommandSpecified) diff --git a/prog/weavewait/noop.go b/prog/weavewait/noop.go new file mode 100644 index 0000000000..2342311d2a --- /dev/null +++ b/prog/weavewait/noop.go @@ -0,0 +1,7 @@ +// +build noop + +package main + +func checkNetwork() error { + return nil +} diff --git a/proxy/common.go b/proxy/common.go index 29db23efad..9a927cca70 100644 --- a/proxy/common.go +++ b/proxy/common.go @@ -155,3 +155,25 @@ func weaveContainerIPs(containerID string) (mac string, ips []net.IP, nets []*ne } return } + +func addVolume(hostConfig jsonObject, source, target, mode string) error { + configBinds, err := hostConfig.StringArray("Binds") + if err != nil { + return err + } + + var binds []string + for _, bind := range configBinds { + s := strings.Split(bind, ":") + if len(s) >= 2 && s[1] == target { + continue + } + binds = append(binds, bind) + } + bind := source + ":" + target + if mode != "" { + bind += ":" + mode + } + hostConfig["Binds"] = append(binds, bind) + return nil +} diff --git a/proxy/create_container_interceptor.go b/proxy/create_container_interceptor.go index 381c3bf2b9..7f4bc84edd 100644 --- a/proxy/create_container_interceptor.go +++ b/proxy/create_container_interceptor.go @@ -53,7 +53,7 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error { Log.Infof("Leaving container alone because %s", err) } else { Log.Infof("Creating container with WEAVE_CIDR \"%s\"", strings.Join(cidrs, " ")) - if err := i.proxy.addWeaveWaitVolume(hostConfig); err != nil { + if err := addVolume(hostConfig, i.proxy.weaveWaitVolume, "/w", "ro"); err != nil { return err } if err := i.setWeaveWaitEntrypoint(container); err != nil { diff --git a/proxy/proxy.go b/proxy/proxy.go index e90c7f57a9..6618fe51ba 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -70,6 +70,7 @@ type Proxy struct { dockerBridgeIP string hostnameMatchRegexp *regexp.Regexp weaveWaitVolume string + weaveWaitNoopVolume string normalisedAddrs []string waiters map[*http.Request]*wait } @@ -106,7 +107,7 @@ func NewProxy(c Config) (*Proxy, error) { return nil, err } - if err = p.findWeaveWaitVolume(); err != nil { + if err = p.findWeaveWaitVolumes(); err != nil { return nil, err } @@ -135,23 +136,31 @@ func (proxy *Proxy) Dial() (net.Conn, error) { return net.Dial("unix", dockerSock) } -func (proxy *Proxy) findWeaveWaitVolume() error { +func (proxy *Proxy) findWeaveWaitVolumes() error { + var err error + if proxy.weaveWaitVolume, err = proxy.findVolume("/w"); err != nil { + return err + } + proxy.weaveWaitNoopVolume, err = proxy.findVolume("/w-noop") + return err +} + +func (proxy *Proxy) findVolume(v string) (string, error) { container, err := proxy.client.InspectContainer("weaveproxy") if err != nil { - return fmt.Errorf("Could not find the weavewait volume: %s", err) + return "", fmt.Errorf("Could not find the weavewait volume: %s", err) } if container.Volumes == nil { - return fmt.Errorf("Could not find the weavewait volume") + return "", fmt.Errorf("Could not find the weavewait volume") } - volume, ok := container.Volumes["/w"] + volume, ok := container.Volumes[v] if !ok { - return fmt.Errorf("Could not find the weavewait volume") + return "", fmt.Errorf("Could not find the weavewait volume") } - proxy.weaveWaitVolume = volume - return nil + return volume, nil } func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -425,7 +434,7 @@ func (proxy *Proxy) attachRouter(container *docker.Container) error { func (proxy *Proxy) weaveCIDRs(networkMode string, env []string) ([]string, error) { if networkMode == "host" || strings.HasPrefix(networkMode, "container:") { - return nil, fmt.Errorf("the container was created with the '--net=%s'", networkMode) + return nil, fmt.Errorf("the container has '--net=%s'", networkMode) } for _, e := range env { if strings.HasPrefix(e, "WEAVE_CIDR=") { @@ -441,24 +450,6 @@ func (proxy *Proxy) weaveCIDRs(networkMode string, env []string) ([]string, erro return nil, nil } -func (proxy *Proxy) addWeaveWaitVolume(hostConfig jsonObject) error { - configBinds, err := hostConfig.StringArray("Binds") - if err != nil { - return err - } - - var binds []string - for _, bind := range configBinds { - s := strings.Split(bind, ":") - if len(s) >= 2 && s[1] == "/w" { - continue - } - binds = append(binds, bind) - } - hostConfig["Binds"] = append(binds, fmt.Sprintf("%s:/w:ro", proxy.weaveWaitVolume)) - return nil -} - func (proxy *Proxy) setWeaveDNS(hostConfig jsonObject, hostname, dnsDomain string) error { dns, err := hostConfig.StringArray("Dns") if err != nil { diff --git a/proxy/start_container_interceptor.go b/proxy/start_container_interceptor.go index e182a62985..6e68059ea7 100644 --- a/proxy/start_container_interceptor.go +++ b/proxy/start_container_interceptor.go @@ -2,6 +2,7 @@ package proxy import ( "net/http" + "strings" ) type startContainerInterceptor struct{ proxy *Proxy } @@ -31,11 +32,23 @@ func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error { hostConfig = params } if hostConfig != nil { - i.proxy.addWeaveWaitVolume(hostConfig) - if dnsDomain := i.proxy.getDNSDomain(); dnsDomain != "" { - if err := i.proxy.setWeaveDNS(hostConfig, container.Config.Hostname, dnsDomain); err != nil { + networkMode, err := jsonObject(hostConfig).String("NetworkMode") + if err != nil { + return err + } + if strings.HasPrefix(networkMode, "container:") || networkMode == "host" { + if err := addVolume(hostConfig, i.proxy.weaveWaitNoopVolume, "/w", "ro"); err != nil { return err } + } else { + if err := addVolume(hostConfig, i.proxy.weaveWaitVolume, "/w", "ro"); err != nil { + return err + } + if dnsDomain := i.proxy.getDNSDomain(); dnsDomain != "" { + if err := i.proxy.setWeaveDNS(hostConfig, container.Config.Hostname, dnsDomain); err != nil { + return err + } + } } // Note we marshal the original top-level dictionary to avoid disturbing anything else diff --git a/test/666_abuse_of_start_test.sh b/test/666_abuse_of_start_test.sh index 36722081f6..2f666bc08e 100755 --- a/test/666_abuse_of_start_test.sh +++ b/test/666_abuse_of_start_test.sh @@ -9,8 +9,8 @@ docker_bridge_ip=$(weave_on $HOST1 docker-bridge-ip) proxy_start_container $HOST1 --name=c1 check_hostconfig() { - docker_on $HOST1 attach c2 >/dev/null 2>&1 || true # Wait for container to exit - assert "docker_on $HOST1 inspect -f '{{.HostConfig.Dns}} {{.HostConfig.NetworkMode}} {{.State.Running}} {{.State.ExitCode}}' $1" "[$docker_bridge_ip] $2 false 0" + docker_on $HOST1 attach $1 >/dev/null 2>&1 || true # Wait for container to exit + assert "docker_on $HOST1 inspect -f '{{.HostConfig.Dns}} {{.HostConfig.NetworkMode}} {{.State.Running}} {{.State.ExitCode}}' $1" "[$3] $2 false 0" } # Start c2 with a sneaky HostConfig @@ -26,7 +26,7 @@ check_hostconfig c5 container:c1 # Start c3 with HostConfig having empty binds and null dns/networking settings proxy docker_on $HOST1 create --name=c3 -v /tmp:/hosttmp $SMALL_IMAGE $CHECK_ETHWE_UP proxy docker_api_on $HOST1 POST /containers/c3/start '{"Binds":[],"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,"Devices":null,"NetworkMode":""}' -check_hostconfig c3 default +check_hostconfig c3 default $docker_bridge_ip # Start c4 with an 'null' HostConfig and check this doesn't remove previous parameters proxy docker_on $HOST1 create --name=c4 --memory-swap -1 $SMALL_IMAGE echo foo @@ -42,6 +42,17 @@ check_hostconfig c6 container:c1 proxy docker_on $HOST1 create --name=c7 --memory-swap -1 $SMALL_IMAGE $CHECK_ETHWE_UP proxy docker_api_on $HOST1 POST /containers/c7/start '{"HostConfig":{}}' assert "docker_on $HOST1 inspect -f '{{.HostConfig.MemorySwap}}' c7" "0" -check_hostconfig c7 default +check_hostconfig c7 default $docker_bridge_ip + +# Start c8 in host network mode +proxy docker_on $HOST1 create --name=c8 $SMALL_IMAGE $CHECK_ETHWE_MISSING +proxy docker_api_on $HOST1 POST /containers/c8/start '{"HostConfig": {"NetworkMode": "host"}}' +check_hostconfig c8 host + +# Start c10 in network of host container +proxy_start_container $HOST1 --name=c9 --net=host +proxy docker_on $HOST1 create --name=c10 $SMALL_IMAGE $CHECK_ETHWE_MISSING +proxy docker_api_on $HOST1 POST /containers/c10/start '{"HostConfig": {"NetworkMode": "container:c9"}}' +check_hostconfig c10 container:c9 end_suite diff --git a/test/config.sh b/test/config.sh index d6471b2f00..f50e03b556 100644 --- a/test/config.sh +++ b/test/config.sh @@ -40,6 +40,7 @@ TEST_IMAGES="$SMALL_IMAGE $DNS_IMAGE" PING="ping -nq -W 1 -c 1" CHECK_ETHWE_UP="grep ^1$ /sys/class/net/ethwe/carrier" +CHECK_ETHWE_MISSING="test ! -d /sys/class/net/ethwe" DOCKER_PORT=2375