diff --git a/prog/weaveproxy/main.go b/prog/weaveproxy/main.go index 7a86bccd..815b1ef5 100644 --- a/prog/weaveproxy/main.go +++ b/prog/weaveproxy/main.go @@ -52,6 +52,7 @@ func main() { mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)") ListVar(&c.ListenAddrs, []string{"H"}, defaultListenAddrs, "addresses on which to listen") mflag.BoolVar(&c.NoDefaultIPAM, []string{"#-no-default-ipam", "-no-default-ipalloc"}, false, "do not automatically allocate addresses for containers without a WEAVE_CIDR") + mflag.BoolVar(&c.NoRewriteHosts, []string{"no-rewrite-hosts"}, false, "do not automatically rewrite /etc/hosts. Use if you need the docker IP to remain in /etc/hosts") mflag.StringVar(&c.TLSConfig.CACert, []string{"#tlscacert", "-tlscacert"}, "", "Trust certs signed only by this CA") mflag.StringVar(&c.TLSConfig.Cert, []string{"#tlscert", "-tlscert"}, "", "Path to TLS certificate file") mflag.BoolVar(&c.TLSConfig.Enabled, []string{"#tls", "-tls"}, false, "Use TLS; implied by --tls-verify") diff --git a/prog/weavewait/main.go b/prog/weavewait/main.go index 9b1151bf..24904f2b 100644 --- a/prog/weavewait/main.go +++ b/prog/weavewait/main.go @@ -1,32 +1,56 @@ package main import ( + "bufio" + "bytes" "fmt" + "io/ioutil" + "net" "os" "os/exec" "os/signal" + "sort" + "strings" "syscall" - "github.com/weaveworks/weave/net" + weavenet "github.com/weaveworks/weave/net" ) func main() { if len(os.Args) <= 1 { os.Exit(0) } - args := os.Args[1:] + + var ( + args = os.Args[1:] + notInExec = true + rewriteHosts = true + ) if args[0] == "-s" { + notInExec = false + rewriteHosts = false args = args[1:] - } else { + } + + if args[0] == "-h" { + rewriteHosts = false + args = args[1:] + } + + if notInExec { usr2 := make(chan os.Signal) signal.Notify(usr2, syscall.SIGUSR2) <-usr2 } - _, err := net.EnsureInterface("ethwe", -1) + iface, err := weavenet.EnsureInterface("ethwe", -1) checkErr(err) + if rewriteHosts { + updateHosts(iface) + } + binary, err := exec.LookPath(args[0]) checkErr(err) @@ -39,3 +63,92 @@ func checkErr(err error) { os.Exit(1) } } + +func updateHosts(iface *net.Interface) { + addrs, err := iface.Addrs() + checkErr(err) + if len(addrs) == 0 { + return + } + hostname, err := os.Hostname() + checkErr(err) + + hosts := parseHosts() + + // Remove existing ips pointing to our hostname + toRemove := []string{} + for ip, addrs := range hosts { + for _, addr := range addrs { + if addr == hostname { + toRemove = append(toRemove, ip) + break + } + } + } + for _, ip := range toRemove { + delete(hosts, ip) + } + + // Add the weave ip(s) + for _, addr := range addrs { + if addr, ok := addr.(*net.IPNet); ok { + ip := addr.IP.String() + hosts[ip] = append(hosts[ip], hostname) + } + } + + writeHosts(hosts) +} + +func parseHosts() map[string][]string { + f, err := os.Open("/etc/hosts") + checkErr(err) + defer f.Close() + ips := map[string][]string{} + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + + // Remove any comments + if i := strings.IndexByte(line, '#'); i != -1 { + line = line[:i] + } + + fields := strings.Fields(line) + if len(fields) > 0 { + ips[fields[0]] = append(ips[fields[0]], fields[1:]...) + } + } + checkErr(scanner.Err()) + return ips +} + +func writeHosts(contents map[string][]string) { + ips := []string{} + for ip := range contents { + ips = append(ips, ip) + } + sort.Strings(ips) + + buf := &bytes.Buffer{} + fmt.Fprintln(buf, "# modified by weave") + for _, ip := range ips { + if addrs := contents[ip]; len(addrs) > 0 { + fmt.Fprintf(buf, "%s\t%s\n", ip, strings.Join(uniqueStrs(addrs), " ")) + } + } + checkErr(ioutil.WriteFile("/etc/hosts", buf.Bytes(), 644)) +} + +func uniqueStrs(s []string) []string { + m := map[string]struct{}{} + result := []string{} + for _, str := range s { + if _, ok := m[str]; !ok { + m[str] = struct{}{} + result = append(result, str) + } + } + sort.Strings(result) + return result +} diff --git a/proxy/create_container_interceptor.go b/proxy/create_container_interceptor.go index 723a3d0b..8e3cca04 100644 --- a/proxy/create_container_interceptor.go +++ b/proxy/create_container_interceptor.go @@ -92,7 +92,11 @@ func (i *createContainerInterceptor) setWeaveWaitEntrypoint(container *docker.Co } if len(container.Entrypoint) == 0 || container.Entrypoint[0] != weaveWaitEntrypoint[0] { - container.Entrypoint = append(weaveWaitEntrypoint, container.Entrypoint...) + entrypoint := weaveWaitEntrypoint + if i.proxy.NoRewriteHosts { + entrypoint = append(entrypoint, "-h") + } + container.Entrypoint = append(entrypoint, container.Entrypoint...) } return nil diff --git a/proxy/proxy.go b/proxy/proxy.go index 2993d00d..0e1969f2 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -29,12 +29,13 @@ var ( ) type Config struct { - ListenAddrs []string - NoDefaultIPAM bool - TLSConfig TLSConfig - Version string - WithDNS bool - WithoutDNS bool + ListenAddrs []string + NoDefaultIPAM bool + NoRewriteHosts bool + TLSConfig TLSConfig + Version string + WithDNS bool + WithoutDNS bool } type Proxy struct { diff --git a/test/610_proxy_wait_for_weave_test.sh b/test/610_proxy_wait_for_weave_test.sh index acb748d5..7376a70d 100755 --- a/test/610_proxy_wait_for_weave_test.sh +++ b/test/610_proxy_wait_for_weave_test.sh @@ -19,4 +19,7 @@ COMMITTED_IMAGE=$(proxy docker_on $HOST1 commit c1) assert_raises "proxy docker_on $HOST1 run --name c2 $COMMITTED_IMAGE" assert "entrypoint c2" "$(entrypoint $COMMITTED_IMAGE)" +# Check weave IP is first ip returned, so java (etc) prefer weave. +assert "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.1/24' $BASE_IMAGE hostname -i | cut -d' ' -f1" "10.2.1.1" + end_suite diff --git a/weave b/weave index f69bcb9a..c7983f68 100755 --- a/weave +++ b/weave @@ -36,7 +36,7 @@ weave launch-router [--password ] [--nickname ] [--no-discovery] [--init-peer-count ] ... weave launch-dns [] weave launch-proxy [-H ] [--with-dns | --without-dns] - [--no-default-ipalloc] + [--no-default-ipalloc] [--no-rewrite-hosts] weave connect [--replace] [ ...] weave forget ... weave run [--with-dns | --without-dns] [ ...]