[proxy] Override sneaky /start HostConfig params

This commit is contained in:
Paul Bellamy committed 2015-09-22 15:09:32 +01:00
1 parent 846aa98a9c
commit 74c3b0d079
5 files changed
+103 -70

No files matched your search

+5
View File
@@ -50,6 +50,10 @@ func unmarshalRequestBody(r *http.Request, target interface{}) error {
}
r.Body = ioutil.NopCloser(bytes.NewReader(body))
if len(body) == 0 {
return nil
}
d := json.NewDecoder(bytes.NewReader(body))
d.UseNumber() // don't want large numbers in scientific format
return d.Decode(&target)
@@ -62,6 +66,7 @@ func marshalRequestBody(r *http.Request, body interface{}) error {
}
r.Body = ioutil.NopCloser(bytes.NewReader(newBody))
r.ContentLength = int64(len(newBody))
r.Header.Set("Content-Type", "application/json")
return nil
}
+8 -65
View File
@@ -2,16 +2,11 @@ package proxy
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/fsouza/go-dockerclient"
. "github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/nameserver"
"github.com/weaveworks/weave/router"
)
const MaxDockerHostname = 64
@@ -55,7 +50,7 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error {
if container.Config == nil {
container.Config = &docker.Config{}
}
i.addWeaveWaitVolume(container.HostConfig)
i.proxy.addWeaveWaitVolume(container.HostConfig)
if err := i.setWeaveWaitEntrypoint(container.Config); err != nil {
return err
}
@@ -66,8 +61,11 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error {
}
}
hostname = i.proxy.hostnameMatchRegexp.ReplaceAllString(hostname, i.proxy.HostnameReplacement)
if err := i.setWeaveDNS(&container, hostname); err != nil {
return err
if dnsDomain, withDNS := i.proxy.getDNSDomain(); withDNS {
i.setHostname(&container, hostname, dnsDomain)
if err := i.proxy.setWeaveDNS(container.HostConfig, container.Hostname, dnsDomain); err != nil {
return err
}
}
return marshalRequestBody(r, container)
@@ -76,18 +74,6 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error {
return nil
}
func (i *createContainerInterceptor) addWeaveWaitVolume(hostConfig *docker.HostConfig) {
var binds []string
for _, bind := range hostConfig.Binds {
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", i.proxy.weaveWaitVolume))
}
func (i *createContainerInterceptor) setWeaveWaitEntrypoint(container *docker.Config) error {
if len(container.Entrypoint) == 0 {
image, err := i.proxy.client.InspectImage(container.Image)
@@ -117,18 +103,7 @@ func (i *createContainerInterceptor) setWeaveWaitEntrypoint(container *docker.Co
return nil
}
func (i *createContainerInterceptor) setWeaveDNS(container *createContainerRequestBody, name string) error {
if i.proxy.WithoutDNS {
return nil
}
dnsDomain, dnsRunning := i.getDNSDomain()
if !(dnsRunning || i.proxy.WithDNS) {
return nil
}
container.HostConfig.DNS = append(container.HostConfig.DNS, i.proxy.dockerBridgeIP)
func (i *createContainerInterceptor) setHostname(container *createContainerRequestBody, name, dnsDomain string) {
if container.Hostname == "" && name != "" {
// Strip trailing period because it's unusual to see it used on the end of a host name
trimmedDNSDomain := strings.TrimSuffix(dnsDomain, ".")
@@ -140,39 +115,7 @@ func (i *createContainerInterceptor) setWeaveDNS(container *createContainerReque
}
}
if len(container.HostConfig.DNSSearch) == 0 {
if container.Hostname == "" {
container.HostConfig.DNSSearch = []string{dnsDomain}
} else {
container.HostConfig.DNSSearch = []string{"."}
}
}
return nil
}
func (i *createContainerInterceptor) getDNSDomain() (domain string, running bool) {
domain = nameserver.DefaultDomain
weaveContainer, err := i.proxy.client.InspectContainer("weave")
if err != nil ||
weaveContainer.NetworkSettings == nil ||
weaveContainer.NetworkSettings.IPAddress == "" {
return
}
url := fmt.Sprintf("http://%s:%d/domain", weaveContainer.NetworkSettings.IPAddress, router.HTTPPort)
resp, err := http.Get(url)
if err != nil || resp.StatusCode != http.StatusOK {
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return string(b), true
return
}
func (i *createContainerInterceptor) InterceptResponse(r *http.Response) error {
+54
View File
@@ -4,6 +4,7 @@ import (
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
@@ -15,6 +16,8 @@ import (
docker "github.com/fsouza/go-dockerclient"
. "github.com/weaveworks/weave/common"
weavedocker "github.com/weaveworks/weave/common/docker"
"github.com/weaveworks/weave/nameserver"
"github.com/weaveworks/weave/router"
)
const (
@@ -365,3 +368,54 @@ func (proxy *Proxy) weaveCIDRsFromConfig(config *docker.Config, hostConfig *dock
}
return nil, nil
}
func (proxy *Proxy) addWeaveWaitVolume(hostConfig *docker.HostConfig) {
var binds []string
for _, bind := range hostConfig.Binds {
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))
}
func (proxy *Proxy) setWeaveDNS(hostConfig *docker.HostConfig, hostname, dnsDomain string) error {
hostConfig.DNS = append(hostConfig.DNS, proxy.dockerBridgeIP)
if len(hostConfig.DNSSearch) == 0 {
if hostname == "" {
hostConfig.DNSSearch = []string{dnsDomain}
} else {
hostConfig.DNSSearch = []string{"."}
}
}
return nil
}
func (proxy *Proxy) getDNSDomain() (domain string, running bool) {
domain = nameserver.DefaultDomain
running = proxy.WithDNS
weaveContainer, err := proxy.client.InspectContainer("weave")
if err != nil ||
weaveContainer.NetworkSettings == nil ||
weaveContainer.NetworkSettings.IPAddress == "" {
return
}
url := fmt.Sprintf("http://%s:%d/domain", weaveContainer.NetworkSettings.IPAddress, router.HTTPPort)
resp, err := http.Get(url)
if err != nil || resp.StatusCode != http.StatusOK {
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return string(b), true
}
+28 -3
View File
@@ -2,16 +2,41 @@ package proxy
import (
"net/http"
"github.com/fsouza/go-dockerclient"
)
type startContainerInterceptor struct{ proxy *Proxy }
type startContainerRequestBody struct {
HostConfig *docker.HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"`
}
func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error {
container, err := inspectContainerInPath(i.proxy.client, r.URL.Path)
if err == nil && containerShouldAttach(container) {
i.proxy.createWait(r, container.ID)
if err != nil || !containerShouldAttach(container) {
return err
}
return err
if r.Header.Get("Content-Type") != "application/json" {
i.proxy.createWait(r, container.ID)
return nil
}
hostConfig := &docker.HostConfig{}
if err := unmarshalRequestBody(r, &hostConfig); err != nil {
return err
}
i.proxy.addWeaveWaitVolume(hostConfig)
if dnsDomain, withDNS := i.proxy.getDNSDomain(); withDNS {
if err := i.proxy.setWeaveDNS(hostConfig, container.Config.Hostname, dnsDomain); err != nil {
return err
}
}
i.proxy.createWait(r, container.ID)
return marshalRequestBody(r, hostConfig)
}
func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
+8 -2
View File
@@ -9,7 +9,13 @@ weave_on $HOST1 launch
proxy_start_container $HOST1 --name=c1
proxy docker_on $HOST1 create --name=c2 $SMALL_IMAGE grep "^1$" /sys/class/net/ethwe/carrier
# Now start c2 with a sneaky HostConfig
curl -X POST -H Content-Type:application/json -d '{"HostConfig": {"NetworkMode": "container:c1"}}' http://$HOST1:12375/containers/c2/start
assert "docker_on $HOST1 inspect -f '{{.State.Running}} {{.State.ExitCode}}' c2" "false 0"
curl -X POST -H Content-Type:application/json -d '{"NetworkMode": "container:c1"}' http://$HOST1:12375/v1.20/containers/c2/start
docker_bridge_ip=$(weave_on $HOST1 docker-bridge-ip)
assert "docker_on $HOST1 inspect -f '{{.State.Running}} {{.State.ExitCode}} {{.HostConfig.Dns}}' c2" "false 0 [$docker_bridge_ip]"
# Now start c3 with a mostly null HostConfig
proxy docker_on $HOST1 create --name=c3 -v /tmp:/hosttmp $SMALL_IMAGE grep "^1$" /sys/class/net/ethwe/carrier
curl -X POST -H Content-Type:application/json -d '{"Binds":[],"ContainerIDFile":"","LxcConf":null,"Memory":0,"MemorySwap":0,"CpuShares":0,"CpuPeriod":0,"CpusetCpus":"","CpusetMems":"","CpuQuota":0,"BlkioWeight":0,"OomKillDisable":false,"Privileged":false,"PortBindings":null,"Links":[],"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,"Devices":null,"NetworkMode":"","IpcMode":"","PidMode":"","UTSMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"","MaximumRetryCount":0},"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"type":"","config":null},"CgroupParent":""}' http://$HOST1:12375/v1.20/containers/c3/start
assert "docker_on $HOST1 inspect -f '{{.State.Running}} {{.State.ExitCode}} {{.HostConfig.Dns}} {{index .HostConfig.Binds 0}}' c3" "false 0 [$docker_bridge_ip] /tmp:/hosttmp"
end_suite