Files
weave/proxy/create_container_interceptor.go
T
Paul Bellamy 96a69d2303 Add dns support for the proxy
In the proxy, I swapped the 'flag' library for
'code.google.com/p/getopt', which uses double-dash flags.

proxy lets 'weave attach' do dns registration on container start

proxy needs to set DNSSearch if not specified
2015-05-19 10:34:45 +01:00

135 lines
3.2 KiB
Go

package proxy
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/fsouza/go-dockerclient"
)
type createContainerInterceptor struct {
client *docker.Client
withDNS bool
}
type createContainerRequestBody struct {
*docker.Config
HostConfig *docker.HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"`
MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
}
func (i *createContainerInterceptor) InterceptRequest(r *http.Request) (*http.Request, error) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
r.Body.Close()
container := createContainerRequestBody{}
if err := json.Unmarshal(body, &container); err != nil {
return nil, err
}
if _, ok := weaveCIDRsFromConfig(container.Config); ok {
i.addToVolumesFrom(container.HostConfig, "weaveproxy")
if err := i.setWeaveWaitEntrypoint(container.Config); err != nil {
return nil, err
}
if err := i.setWeaveDNS(&container); err != nil {
return nil, err
}
}
newBody, err := json.Marshal(container)
if err != nil {
return nil, err
}
r.Body = ioutil.NopCloser(bytes.NewReader(newBody))
r.ContentLength = int64(len(newBody))
return r, nil
}
func (i *createContainerInterceptor) addToVolumesFrom(config *docker.HostConfig, mounts ...string) {
config.VolumesFrom = append(config.VolumesFrom, mounts...)
}
func (i *createContainerInterceptor) setWeaveWaitEntrypoint(container *docker.Config) error {
var image *docker.Config
if !configHasEntrypoint(container) || !configHasCmd(container) {
imageInfo, err := i.client.InspectImage(container.Image)
if err != nil {
return err
}
image = imageInfo.Config
}
var entry, command []string
if configHasEntrypoint(container) {
entry = container.Entrypoint
} else if configHasEntrypoint(image) {
entry = image.Entrypoint
}
if configHasCmd(container) {
command = container.Cmd
} else if configHasCmd(image) {
command = image.Cmd
}
container.Entrypoint = []string{"/home/weavewait/weavewait"}
container.Cmd = append(entry, command...)
return nil
}
func configHasEntrypoint(c *docker.Config) bool {
return c != nil && len(c.Entrypoint) > 0
}
func configHasCmd(c *docker.Config) bool {
return c != nil && len(c.Cmd) > 0
}
func (i *createContainerInterceptor) setWeaveDNS(container *createContainerRequestBody) error {
if !i.withDNS {
return nil
}
dockerBridgeIP, err := getDockerBridgeIP()
if err != nil {
return err
}
container.HostConfig.DNS = append(container.HostConfig.DNS, dockerBridgeIP)
if len(container.HostConfig.DNSSearch) == 0 {
container.HostConfig.DNSSearch = []string{"."}
}
return nil
}
func getDockerBridgeIP() (string, error) {
out, err := callWeave("dns-args")
if err != nil {
return "", fmt.Errorf("Error fetching weave dns-args: %s", err)
}
var dockerBridgeIP string
segments := strings.Split(string(out), " ")
for i := 0; i < len(segments)-1; i++ {
if segments[i] == "--dns" {
dockerBridgeIP = segments[i+1]
}
}
if dockerBridgeIP == "" {
return "", fmt.Errorf("Docker bridge IP not found in weave output: %s", string(out))
}
return dockerBridgeIP, nil
}
func (i *createContainerInterceptor) InterceptResponse(res *http.Response) (*http.Response, error) {
return res, nil
}