Files
weave-scope/app/weave.go
Roland Schilter 651e52b5a5 Honor DOCKER_* env variables in probe and app
Changed default for flag `-app.docker` to use the DOCKER_* env variables
instead of hardcoded /var/run/docker.sock; uses docker's default if
no DOCKER_HOST defined, for both probe and app.

Fixes #1975
2017-06-27 17:14:49 +02:00

149 lines
3.3 KiB
Go

package app
import (
"fmt"
"net"
"strings"
fsouza "github.com/fsouza/go-dockerclient"
"github.com/weaveworks/common/backoff"
)
// Default values for weave app integration
const (
DefaultHostname = "scope.weave.local."
DefaultWeaveURL = "http://127.0.0.1:6784"
DefaultContainerName = "weavescope"
)
// WeavePublisher is a thing which periodically registers this app with WeaveDNS.
type WeavePublisher struct {
containerName string
hostname string
dockerClient DockerClient
weaveClient WeaveClient
backoff backoff.Interface
interfaces InterfaceFunc
}
// DockerClient is the little bit of the docker client we need.
type DockerClient interface {
ListContainers(fsouza.ListContainersOptions) ([]fsouza.APIContainers, error)
}
// WeaveClient is the little bit of the weave clent we need.
type WeaveClient interface {
AddDNSEntry(hostname, containerid string, ip net.IP) error
Expose() error
}
// Interface is because net.Interface isn't mockable.
type Interface struct {
Name string
Addrs []net.Addr
}
// InterfaceFunc is the type of Interfaces()
type InterfaceFunc func() ([]Interface, error)
// Interfaces returns the list of Interfaces on the machine.
func Interfaces() ([]Interface, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
result := []Interface{}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
continue
}
result = append(result, Interface{
Name: i.Name,
Addrs: addrs,
})
}
return result, nil
}
// NewWeavePublisher makes a new Weave.
func NewWeavePublisher(weaveClient WeaveClient, dockerClient DockerClient, interfaces InterfaceFunc, hostname, containerName string) *WeavePublisher {
w := &WeavePublisher{
containerName: containerName,
hostname: hostname,
dockerClient: dockerClient,
weaveClient: weaveClient,
interfaces: interfaces,
}
w.backoff = backoff.New(w.updateDNS, "updating weaveDNS")
go w.backoff.Start()
return w
}
// Stop the Weave.
func (w *WeavePublisher) Stop() {
w.backoff.Stop()
}
func (w *WeavePublisher) updateDNS() (bool, error) {
// 0. expose this host
if err := w.weaveClient.Expose(); err != nil {
return false, err
}
// 1. work out my IP addresses
ifaces, err := w.interfaces()
if err != nil {
return false, err
}
ips := []net.IP{}
for _, i := range ifaces {
if strings.HasPrefix(i.Name, "lo") ||
strings.HasPrefix(i.Name, "docker") ||
strings.HasPrefix(i.Name, "veth") {
continue
}
for _, addr := range i.Addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPAddr:
ip = v.IP
case *net.IPNet:
ip = v.IP
}
if ip != nil && ip.To4() != nil {
ips = append(ips, ip)
}
}
}
// 2. work out my container name
containers, err := w.dockerClient.ListContainers(fsouza.ListContainersOptions{})
if err != nil {
return false, err
}
containerID := ""
outer:
for _, container := range containers {
for _, name := range container.Names {
if name == "/"+w.containerName {
containerID = container.ID
break outer
}
}
}
if containerID == "" {
return false, fmt.Errorf("Container %s not found", w.containerName)
}
// 3. Register these with weave dns
for _, ip := range ips {
if err := w.weaveClient.AddDNSEntry(w.hostname, containerID, ip); err != nil {
return false, err
}
}
return false, nil
}