In proxy, rewrite /etc/hosts from 'weave attach', via new utility weavehosts

This commit is contained in:
Bryan Boreham committed 2015-08-27 15:03:41 +01:00
1 parent 6e89b036e2
commit 3d25620d13
7 files changed
+151 -142

No files matched your search

+2
View File
@@ -35,6 +35,7 @@ coverage.html
# Project specific
prog/weaver/weaver
prog/weavedns/weavedns
prog/weavehosts/weavehosts
prog/weaveproxy/weaveproxy
prog/sigproxy/sigproxy
prog/weavewait/weavewait
@@ -49,6 +50,7 @@ releases
.weaveexec.uptodate
weave.tar
prog/weaveexec/weave
prog/weaveexec/weavehosts
prog/weaveexec/weaveproxy
prog/weaveexec/weavewait
prog/weaveexec/sigproxy
+5 -3
View File
@@ -13,11 +13,12 @@ WEAVER_EXE=prog/weaver/weaver
WEAVEPROXY_EXE=prog/weaveproxy/weaveproxy
SIGPROXY_EXE=prog/sigproxy/sigproxy
WEAVEWAIT_EXE=prog/weavewait/weavewait
WEAVEHOSTS_EXE=prog/weavehosts/weavehosts
NETCHECK_EXE=prog/netcheck/netcheck
COVER_EXE=testing/cover/cover
RUNNER_EXE=testing/runner/runner
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(NETCHECK_EXE) $(COVER_EXE) $(RUNNER_EXE)
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEHOSTS_EXE) $(NETCHECK_EXE) $(COVER_EXE) $(RUNNER_EXE)
WEAVER_UPTODATE=.weaver.uptodate
WEAVEEXEC_UPTODATE=.weaveexec.uptodate
@@ -79,7 +80,7 @@ $(WEAVEHOSTS_EXE): prog/weavehosts/weavehosts.go
$(COVER_EXE): testing/cover/cover.go
$(RUNNER_EXE): testing/runner/runner.go
$(WEAVEWAIT_EXE) $(SIGPROXY_EXE) $(COVER_EXE) $(RUNNER_EXE):
$(WEAVEWAIT_EXE) $(SIGPROXY_EXE) $(WEAVEHOSTS_EXE) $(COVER_EXE) $(RUNNER_EXE):
go get ./$(@D)
go build -o $@ ./$(@D)
@@ -87,11 +88,12 @@ $(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)
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEHOSTS_EXE) $(NETCHECK_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 $(WEAVEHOSTS_EXE) prog/weaveexec/weavehosts
cp $(NETCHECK_EXE) prog/weaveexec/netcheck
cp $(DOCKER_DISTRIB) prog/weaveexec/docker.tgz
$(SUDO) docker build -t $(WEAVEEXEC_IMAGE) prog/weaveexec
+1 -1
View File
@@ -17,6 +17,6 @@ RUN apk add --update \
&& rm -rf /var/cache/apk/*
ADD ./weave ./sigproxy ./weaveproxy /home/weave/
ADD ./netcheck /usr/bin/
ADD ./netcheck ./weavehosts /usr/bin/
ADD ./weavewait /w/w
ADD ./docker.tgz /
+120
View File
@@ -0,0 +1,120 @@
/* weavehosts: rewrite /etc/hosts as necessary to put the weave address(es) at the top */
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"net"
"os"
"sort"
"strings"
)
func main() {
args := os.Args
if len(args) < 4 {
fmt.Fprintln(os.Stderr, "usage: weavehosts hostpath hostname cidr [cidr ...]")
os.Exit(1)
}
checkErr(updateHosts(args[1], args[2], args[3:]))
os.Exit(0)
}
func checkErr(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func updateHosts(path, hostname string, cidrs []string) error {
hosts, err := parseHosts(path)
if err != nil {
return err
}
// 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 _, cidr := range cidrs {
ip, _, err := net.ParseCIDR(cidr)
checkErr(err)
ipStr := ip.String()
hosts[ipStr] = append(hosts[ipStr], hostname)
}
return writeHosts(path, hosts)
}
func parseHosts(path string) (map[string][]string, error) {
f, err := os.Open(path)
if err != nil {
return nil, 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:]...)
}
}
if scanner.Err() != nil {
return nil, scanner.Err()
}
return ips, nil
}
func writeHosts(path string, contents map[string][]string) error {
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), " "))
}
}
return ioutil.WriteFile(path, 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
}
+1 -2
View File
@@ -35,8 +35,7 @@ func (i *createExecInterceptor) InterceptRequest(r *http.Request) error {
Log.Infof("Leaving container %s alone because %s", container.ID, err)
} else if hasWeaveWait {
Log.Infof("Exec in container %s with WEAVE_CIDR \"%s\"", container.ID, strings.Join(cidrs, " "))
cmd := weaveWaitEntrypoint
options.Cmd = append(cmd, options.Cmd...)
options.Cmd = append(weaveWaitEntrypoint, options.Cmd...)
}
if err := marshalRequestBody(r, options); err != nil {
+4 -132
View File
@@ -1,18 +1,10 @@
package proxy
import (
"bufio"
"bytes"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"sort"
"strings"
"github.com/fsouza/go-dockerclient"
. "github.com/weaveworks/weave/common"
)
@@ -40,6 +32,9 @@ func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
Log.Infof("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " "))
args := []string{"attach"}
args = append(args, cidrs...)
if !i.proxy.NoRewriteHosts {
args = append(args, "--rewrite-hosts")
}
args = append(args, "--or-die", container.ID)
if _, stderr, err := callWeave(args...); err != nil {
Log.Warningf("Attaching container %s to weave network failed: %s", container.ID, string(stderr))
@@ -48,128 +43,5 @@ func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
Log.Warningf("Attaching container %s to weave network: %s", container.ID, string(stderr))
}
if !i.proxy.NoRewriteHosts {
ips, err := weaveContainerIPs(container)
if err != nil {
return err
}
if len(ips) > 0 {
if err := updateHosts(container.HostsPath, container.Config.Hostname, ips); err != nil {
return err
}
}
}
return i.proxy.client.KillContainer(docker.KillContainerOptions{ID: container.ID, Signal: docker.SIGUSR2})
}
func weaveContainerIPs(container *docker.Container) ([]net.IP, error) {
stdout, stderr, err := callWeave("ps", container.ID)
if err != nil || len(stderr) > 0 {
return nil, errors.New(string(stderr))
}
if len(stdout) <= 0 {
return nil, nil
}
fields := strings.Fields(string(stdout))
if len(fields) <= 2 {
return nil, nil
}
var ips []net.IP
for _, cidr := range fields[2:] {
ip, _, err := net.ParseCIDR(cidr)
if err != nil {
return nil, err
}
ips = append(ips, ip)
}
return ips, nil
}
func updateHosts(path, hostname string, ips []net.IP) error {
hosts, err := parseHosts(path)
if err != nil {
return err
}
// 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 _, ip := range ips {
ipStr := ip.String()
hosts[ipStr] = append(hosts[ipStr], hostname)
}
return writeHosts(path, hosts)
}
func parseHosts(path string) (map[string][]string, error) {
f, err := os.Open(path)
if err != nil {
return nil, 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:]...)
}
}
if scanner.Err() != nil {
return nil, scanner.Err()
}
return ips, nil
}
func writeHosts(path string, contents map[string][]string) error {
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), " "))
}
}
return ioutil.WriteFile(path, 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
return nil
}
+18 -4
View File
@@ -1446,14 +1446,28 @@ case "$COMMAND" in
attach)
collect_cidr_args "$@"
shift $CIDR_ARG_COUNT
if [ "$1" = "--or-die" ] ; then
ATTACH_TYPE="_or_die"
shift
fi
while [ $# -gt 0 ]; do
case "$1" in
--or-die)
ATTACH_TYPE="_or_die"
;;
--rewrite-hosts)
REWRITE_HOSTS=1
;;
*)
break
;;
esac
shift
done
[ $# -eq 1 ] || usage
CONTAINER=$(container_id $1)
create_bridge
ipam_cidrs$ATTACH_TYPE $CONTAINER $CIDR_ARGS
if [ -n "$REWRITE_HOSTS" ] && command_exists weavehosts ; then
PATH_AND_NAME=$(docker inspect -f '{{.HostsPath}} {{.Config.Hostname}}' $CONTAINER)
weavehosts $PATH_AND_NAME $ALL_CIDRS
fi
with_container_netns$ATTACH_TYPE $CONTAINER attach $ALL_CIDRS >/dev/null
when_weave_running with_container_fqdn $CONTAINER put_dns_fqdn $ALL_CIDRS
show_addrs $ALL_CIDRS