From a22b88ed89110125893ddcb76fa3d0eb437b8f9e Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 27 Nov 2015 16:14:23 +0000 Subject: [PATCH] Track endpoints so we can register the right address with DNS --- plugin/driver.go | 36 +++++++++++++++++++++++++++--------- plugin/watcher.go | 43 +++++++++++++++---------------------------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/plugin/driver.go b/plugin/driver.go index 85cded7c..e5b1e413 100644 --- a/plugin/driver.go +++ b/plugin/driver.go @@ -2,6 +2,7 @@ package plugin import ( "fmt" + "sync" "github.com/docker/libnetwork/drivers/remote/api" "github.com/docker/libnetwork/types" @@ -22,6 +23,8 @@ const ( type driver struct { version string nameserver string + sync.RWMutex + endpoints map[string]struct{} } func New(version string, nameserver string) (skel.Driver, error) { @@ -30,15 +33,17 @@ func New(version string, nameserver string) (skel.Driver, error) { return nil, errorf("could not connect to docker: %s", err) } - _, err = NewWatcher(client) + driver := &driver{ + nameserver: nameserver, + version: version, + endpoints: make(map[string]struct{}), + } + + _, err = NewWatcher(client, driver) if err != nil { return nil, err } - - return &driver{ - nameserver: nameserver, - version: version, - }, nil + return driver, nil } func errorf(format string, a ...interface{}) error { @@ -76,18 +81,31 @@ func (driver *driver) CreateEndpoint(create *api.CreateEndpointRequest) (*api.Cr if create.Interface == nil { return nil, fmt.Errorf("Not supported: creating an interface from within CreateEndpoint") } + driver.Lock() + driver.endpoints[endID] = struct{}{} + driver.Unlock() resp := &api.CreateEndpointResponse{} Log.Infof("Create endpoint %s %+v", endID, resp) return resp, nil } -func (driver *driver) DeleteEndpoint(delete *api.DeleteEndpointRequest) error { - Log.Debugf("Delete endpoint request: %+v", delete) - Log.Infof("Delete endpoint %s", delete.EndpointID) +func (driver *driver) DeleteEndpoint(deleteReq *api.DeleteEndpointRequest) error { + Log.Debugf("Delete endpoint request: %+v", deleteReq) + Log.Infof("Delete endpoint %s", deleteReq.EndpointID) + driver.Lock() + delete(driver.endpoints, deleteReq.EndpointID) + driver.Unlock() return nil } +func (driver *driver) HasEndpoint(endpointID string) bool { + driver.Lock() + _, found := driver.endpoints[endpointID] + driver.Unlock() + return found +} + func (driver *driver) EndpointInfo(req *api.EndpointInfoRequest) (*api.EndpointInfoResponse, error) { Log.Debugf("Endpoint info request: %+v", req) Log.Infof("Endpoint info %s", req.EndpointID) diff --git a/plugin/watcher.go b/plugin/watcher.go index c37b41e0..fbf43014 100644 --- a/plugin/watcher.go +++ b/plugin/watcher.go @@ -2,7 +2,6 @@ package plugin import ( "fmt" - "strings" weaveapi "github.com/weaveworks/weave/api" . "github.com/weaveworks/weave/common" @@ -16,13 +15,14 @@ const ( type watcher struct { client *docker.Client weave *weaveapi.Client + driver *driver } type Watcher interface { } -func NewWatcher(client *docker.Client) (Watcher, error) { - w := &watcher{client: client} +func NewWatcher(client *docker.Client, driver *driver) (Watcher, error) { + w := &watcher{client: client, driver: driver} err := client.AddObserver(w) if err != nil { return nil, err @@ -50,34 +50,21 @@ func (w *watcher) ContainerStarted(id string) { Log.Warningf("error inspecting container: %s", err) return } - // FIXME: check that it's on our network; but, the docker client lib doesn't know about .NetworkID - if isSubdomain(info.Config.Domainname, WeaveDomain) && w.haveWeaveClient() { - // one of ours - ip := info.NetworkSettings.IPAddress - fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname) - if err := w.weave.RegisterWithDNS(id, fqdn, ip); err != nil { - Log.Warningf("unable to register with weaveDNS: %s", err) + if !w.haveWeaveClient() { + return + } + // check that it's on our network, via the endpointID + for _, net := range info.NetworkSettings.Networks { + if w.driver.HasEndpoint(net.EndpointID) { + fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname) + if err := w.weave.RegisterWithDNS(id, fqdn, net.IPAddress); err != nil { + Log.Warningf("unable to register with weaveDNS: %s", err) + } } } } func (w *watcher) ContainerDied(id string) { - Log.Debugf("Container died %s", id) - info, err := w.client.InspectContainer(id) - if err != nil { - Log.Warningf("error inspecting container: %s", err) - return - } - if isSubdomain(info.Config.Domainname, WeaveDomain) && w.haveWeaveClient() { - ip := info.NetworkSettings.IPAddress - if err := w.weave.DeregisterWithDNS(id, ip); err != nil { - Log.Warningf("unable to deregister with weaveDNS: %s", err) - } - } -} - -// Cheap and cheerful way to check x is, or is a subdomain, of -// y. Neither are expected to start with a '.'. -func isSubdomain(x string, y string) bool { - return x == y || strings.HasSuffix(x, "."+y) + // don't need to do this as WeaveDNS removes names on container died anyway + // (note by the time we get this event we can't see the EndpointID) }