123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- 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
- }
|