diff --git a/prog/weaveproxy/main.go b/prog/weaveproxy/main.go index 23073b745f..514ce5aab2 100644 --- a/prog/weaveproxy/main.go +++ b/prog/weaveproxy/main.go @@ -27,6 +27,7 @@ func main() { mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit") mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)") mflagext.ListVar(&c.ListenAddrs, []string{"H"}, nil, "addresses on which to listen") + mflag.StringVar(&c.HostnameFromLabel, []string{"-hostname-from-label"}, "", "Key of container label from which to obtain the container's hostname") mflag.StringVar(&c.HostnameMatch, []string{"-hostname-match"}, "(.*)", "Regexp pattern to apply on container names (e.g. '^aws-[0-9]+-(.*)$')") mflag.StringVar(&c.HostnameReplacement, []string{"-hostname-replacement"}, "$1", "Expression to generate hostnames based on matches from --hostname-match (e.g. 'my-app-$1')") mflag.BoolVar(&c.NoDefaultIPAM, []string{"#-no-default-ipam", "-no-default-ipalloc"}, false, "do not automatically allocate addresses for containers without a WEAVE_CIDR") diff --git a/proxy/create_container_interceptor.go b/proxy/create_container_interceptor.go index 759ec18e91..e54365a32a 100644 --- a/proxy/create_container_interceptor.go +++ b/proxy/create_container_interceptor.go @@ -68,8 +68,13 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error { if err := i.setWeaveWaitEntrypoint(container.Config); err != nil { return err } - containerName := r.URL.Query().Get("name") - hostname := i.proxy.hostnameMatchRegexp.ReplaceAllString(containerName, i.proxy.HostnameReplacement) + hostname := r.URL.Query().Get("name") + if i.proxy.Config.HostnameFromLabel != "" { + if labelValue, ok := container.Labels[i.proxy.Config.HostnameFromLabel]; ok { + hostname = labelValue + } + } + hostname = i.proxy.hostnameMatchRegexp.ReplaceAllString(hostname, i.proxy.HostnameReplacement) if err := i.setWeaveDNS(&container, hostname); err != nil { return err } diff --git a/proxy/proxy.go b/proxy/proxy.go index beb349152e..f70171e900 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -33,6 +33,7 @@ var ( ) type Config struct { + HostnameFromLabel string HostnameMatch string HostnameReplacement string ListenAddrs []string diff --git a/site/proxy.md b/site/proxy.md index 847ba8bb60..2f713c64d7 100644 --- a/site/proxy.md +++ b/site/proxy.md @@ -154,29 +154,43 @@ for registration. However, there are situations in which the final container name is out of the user's control (e.g. when using Docker orchestrators which append control/namespacing identifiers to the original container names). -For those situations, the proxy provides two flags: `--hostname-match ` -and `--hostname-replacement `. When launching a container, its name -is matched against regular expression ``. Then, based on that match, -`` will be used to generate a hostname, which will ultimately be -handed over to weaveDNS for registration. +For those situations, the proxy provides a few flags: `--hostname-from-label +`, `--hostname-match ` and `--hostname-replacement +`. When launching a container, the hostname is initialized to the +value of the container label with key ``, if `` wasn't +provided, the container name is used. Additionally, the hostname is matched +against regular expression ``. Then, based on that match, +`` will be used to obtainer the final hostname, which will +ultimately be handed over to weaveDNS for registration. + +For instance, we can launch the proxy using all three flags + + host1$ weave launch-router && weave launch-proxy --hostname-from-label hostname-label --hostname-match '^aws-[0-9]+-(.*)$' --hostname-replacement 'my-app-$1' + host1$ eval "$(weave env)" -For instance, if we launch the proxy using -`--hostname-match '^aws-[0-9]+-(.*)$'` and `--hostname-replacement 'my-app-$1'` +Note how regexp substitution groups should be prepended with a dollar sign +(e.g. `$1`). For further details on the regular expression syntax please see +[Google's re2 documentation](https://github.com/google/re2/wiki/Syntax). - host1$ weave launch-router && weave launch-proxy --hostname-match '^aws-[0-9]+-(.*)$' --hostname-replacement 'my-app-$1' - host1$ eval "$(weave env)" -then, running a container named `aws-12798186823-foo` will lead to weaveDNS registering -hostname `my-app-foo` and not `aws-12798186823-foo`. +Then, running a container named `aws-12798186823-foo` without labels will lead +to weaveDNS registering hostname `my-app-foo` and not `aws-12798186823-foo`. host1$ docker run -ti --name=aws-12798186823-foo ubuntu ping my-app-foo PING my-app-foo.weave.local (10.32.0.2) 56(84) bytes of data. 64 bytes from my-app-foo.weave.local (10.32.0.2): icmp_seq=1 ttl=64 time=0.027 ms 64 bytes from my-app-foo.weave.local (10.32.0.2): icmp_seq=2 ttl=64 time=0.067 ms -Note how regexp substitution groups should be prepended with a dollar sign -(e.g. `$1`). For further details on the regular expression syntax please see -[Google's re2 documentation](https://github.com/google/re2/wiki/Syntax). +Also, running a container named `foo` with label +`hostname-label=aws-12798186823-foo` leads to the same hostname registration. + + host1$ docker run -ti --name=foo --label=hostname-label=aws-12798186823-foo ubuntu ping my-app-foo + PING my-app-foo.weave.local (10.32.0.2) 56(84) bytes of data. + 64 bytes from my-app-foo.weave.local (10.32.0.2): icmp_seq=1 ttl=64 time=0.031 ms + 64 bytes from my-app-foo.weave.local (10.32.0.2): icmp_seq=2 ttl=64 time=0.042 ms + +This is because, as we explained above, when providing `--hostname-from-label` +to the proxy, the specified label has precedence over the container's name. ## Securing the docker communication with TLS diff --git a/test/680_proxy_hostname_derivation_test.sh b/test/680_proxy_hostname_derivation_test.sh index f3fa5f4f68..967c974849 100755 --- a/test/680_proxy_hostname_derivation_test.sh +++ b/test/680_proxy_hostname_derivation_test.sh @@ -5,24 +5,64 @@ C1=10.2.0.78 C2=10.2.0.34 C3=10.2.0.57 -CNAME1=qiuds71y827hdi-seeone-1io9qd9i0wd -NAME1=seeone.weave.local -CNAME2=124DJKSNK812-seetwo-128hbaJ881 -NAME2=seetwo.weave.local -CNAME3=doesnotmatchpattern -NAME3=doesnotmatchpattern.weave.local +ENAME1=qiuds71y827hdi-seeone-1io9qd9i0wd +HNAME1=seeone +FQDN1=seeone.weave.local +ENAME2=124DJKSNK812-seetwo-128hbaJ881 +HNAME2=seetwo +FQDN2=$HNAME2.weave.local +ENAME3=doesnotmatchpattern +HNAME3=doesnotmatchpattern +FQDN3=$HNAME3.weave.local -start_suite "Hostname derivation through container name substitutions" +EXPANDED_NAMES="$ENAME1 $ENAME2 $ENAME3" +HOSTNAMES="$HNAME1 $HNAME2 $HNAME3" -weave_on $HOST1 launch-router -weave_on $HOST1 launch-proxy --hostname-match '^[^-]+-(?P[^-]*)-[^-]+$' --hostname-replacement '$appname' +check_dns_records() { + ARG_PREFIX=$1 + shift + CID1=$(proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C1/24 ${ARG_PREFIX}$1) + CID2=$(proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 ${ARG_PREFIX}$2) + CID3=$(proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 ${ARG_PREFIX}$3) -proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C1/24 --name=$CNAME1 -proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 --name=$CNAME2 -proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 --name=$CNAME3 + assert_dns_a_record $HOST1 $CID1 $FQDN1 $C1 + assert_dns_a_record $HOST1 $CID2 $FQDN3 $C3 + assert_dns_a_record $HOST1 $CID2 $FQDN2 $C2 -assert_dns_a_record $HOST1 $CNAME1 $NAME2 $C2 -assert_dns_a_record $HOST1 $CNAME2 $NAME3 $C3 -assert_dns_a_record $HOST1 $CNAME3 $NAME1 $C1 + rm_containers $HOST1 $CID1 $CID2 $CID3 +} + +test_setup() { + weave_on $HOST1 launch-router + weave_on $HOST1 launch-proxy $@ +} + +test_cleanup() { + stop_router_on $HOST1 +} + + +start_suite "Hostname derivation" + +# Hostname derivation through container name substitutions +test_setup --hostname-match '^[^-]+-(?P[^-]*)-[^-]+$' --hostname-replacement '$appname' +# check that the normal container_name->hostname derivation doesn't break +check_dns_records --name= $HOSTNAMES +check_dns_records --name= $EXPANDED_NAMES +test_cleanup + +# Hostname derivation from container labels +test_setup --hostname-from-label hostname-label +check_dns_records --name= $HOSTNAMES +check_dns_records --label=hostname-label= $HOSTNAMES +test_cleanup + +# Hostname derivation combining container labels and substitutions +test_setup --hostname-from-label hostname-label --hostname-match '^[^-]+-(?P[^-]*)-[^-]+$' --hostname-replacement '$appname' +check_dns_records --name= $HOSTNAMES +check_dns_records --name= $EXPANDED_NAMES +check_dns_records --label=hostname-label= $HOSTNAMES +check_dns_records --label=hostname-label= $EXPANDED_NAMES +test_cleanup end_suite diff --git a/weave b/weave index 7d093c6609..5405cb61e5 100755 --- a/weave +++ b/weave @@ -54,6 +54,7 @@ weave launch-router [--password ] [--nickname ] [--no-discovery] [--init-peer-count ] ... weave launch-proxy [-H ] [--with-dns | --without-dns] [--no-default-ipalloc] [--no-rewrite-hosts] + [--hostname-from-label ] [--hostname-match ] [--hostname-replacement ] weave env [--restore]