mirror of
https://github.com/weaveworks/scope.git
synced 2026-02-14 18:09:59 +00:00
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
149 lines
3.3 KiB
Go
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
|
|
}
|