Files
weave/proxy/proxy.go
T
Paul Bellamy 2d5e362115 [proxy] use logs for getting proxy-env and proxy-config
It's ugly, but beats arg-parsing, inspecting the container and piecing
the address together from exposed ports.

We could just use the host from DOCKER_HOST, but that will fail in the
case of a host with multiple IPs, where the proxy only listens on one.
2015-06-10 15:24:53 +01:00

115 lines
2.3 KiB
Go

package proxy
import (
"crypto/tls"
"net"
"net/http"
"net/url"
"regexp"
"github.com/fsouza/go-dockerclient"
. "github.com/weaveworks/weave/common"
)
const (
defaultCaFile = "ca.pem"
defaultKeyFile = "key.pem"
defaultCertFile = "cert.pem"
)
var (
containerCreateRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/create$")
containerStartRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/[^/]*/(re)?start$")
execCreateRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/[^/]*/exec$")
)
type Proxy struct {
Config
dial func() (net.Conn, error)
client *docker.Client
dockerBridgeIP string
}
type Config struct {
DockerAddr string
ListenAddr string
TLSConfig TLSConfig
Version string
WithDNS bool
WithIPAM bool
}
func NewProxy(c Config) (*Proxy, error) {
u, err := url.Parse(c.DockerAddr)
if err != nil {
return nil, err
}
targetAddr := ""
switch u.Scheme {
case "tcp":
targetAddr = u.Host
case "unix":
targetAddr = u.Path
}
p := &Proxy{
Config: c,
dial: func() (net.Conn, error) {
return net.Dial(u.Scheme, targetAddr)
},
}
if p.WithDNS {
dockerBridgeIP, err := callWeave("docker-bridge-ip")
if err != nil {
return nil, err
}
p.dockerBridgeIP = string(dockerBridgeIP)
}
if err := p.TLSConfig.loadCerts(); err != nil {
Error.Fatalf("Could not configure tls for proxy: %s", err)
}
p.client, err = docker.NewClient(p.DockerAddr)
if err != nil {
return nil, err
}
return p, nil
}
func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Info.Printf("%s %s", r.Method, r.URL)
path := r.URL.Path
var i interceptor
switch {
case containerCreateRegexp.MatchString(path):
i = &createContainerInterceptor{proxy}
case containerStartRegexp.MatchString(path):
i = &startContainerInterceptor{proxy}
case execCreateRegexp.MatchString(path):
i = &createExecInterceptor{proxy}
default:
i = &nullInterceptor{}
}
proxy.Intercept(i, w, r)
}
func (proxy *Proxy) ListenAndServe() error {
listener, err := net.Listen("tcp", proxy.ListenAddr)
if err != nil {
return err
}
if proxy.TLSConfig.enabled() {
listener = tls.NewListener(listener, proxy.TLSConfig.Config)
}
Info.Println("proxy listening on", proxy.ListenAddr)
return (&http.Server{Handler: proxy}).Serve(listener)
}