Moved updater into server

While we're only reacting to containers going away, it's more
convenient to bundle the docker events watcher into the server.

I've added a flag to switch it on; and switched it on by default in
the container.

I also implemented `Zone.DeleteRecordsFor(ident)`, which removes all
records for a particular container.

One minor change to the structure of the code is that the Zone is now
constructed *outside* the server, and given to it and the updater.
This commit is contained in:
Michael Bridgen committed 2014-10-16 15:38:32 +01:00
1 parent 0fb4bce24d
commit 0749460652
9 files changed
+102 -72

No files matched your search

+1 -1
View File
@@ -2,4 +2,4 @@ FROM scratch
# EXPOSE 53/udp
WORKDIR /home/weave
ADD ./weavedns /home/weave/
ENTRYPOINT ["/home/weave/weavedns", "-wait", "5", "-iface", "ethwe"]
ENTRYPOINT ["/home/weave/weavedns", "-wait", "5", "-iface", "ethwe", "--watch", "--api", "unix:///var/run/docker.sock"]
+4 -13
View File
@@ -1,28 +1,19 @@
.DEFAULT: all
all: server-image updater-image
all: server-image
weavedns: ../server/*.go ../main.go
go get -tags netgo ../ && go build -tags netgo -ldflags '-linkmode external -extldflags "-static"' -o $@ -v ../
updater: ../updater/main.go
go get -tags netgo ../updater/ && go build -tags netgo -ldflags '-linkmode external -extldflags "-static"' -o $@ -v ../updater/
.PHONY: server-image
.PHONY: server-image updater-image
updater-image: /var/tmp/updater.tar
server-image: /var/tmp/weavedns.tar
/var/tmp/weavedns.tar: Dockerfile weavedns
sudo -E docker build -t zettio/weavedns .
sudo -E docker save zettio/weavedns > $@
/var/tmp/updater.tar: ../updater/Dockerfile updater
sudo -E docker build -t zettio/updater ../updater/
sudo -E docker save zettio/updater > $@
clean:
-sudo docker rmi zettio/weavedns
-sudo docker rmi zettio/updater
rm -f weavedns updater
rm -f /var/tmp/{updater,weavedns}.tar
rm -f weavedns
rm -f /var/tmp/weavedns.tar
+14 -1
View File
@@ -9,18 +9,31 @@ import (
func main() {
var (
ifaceName string
apiPath string
dnsPort int
httpPort int
wait int
watch bool
)
flag.StringVar(&ifaceName, "iface", "", "name of interface to use for multicast")
flag.StringVar(&apiPath, "api", "unix:///var/run/docker.sock", "Path to Docker API socket")
flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up (defaults to 0)")
flag.IntVar(&dnsPort, "dnsport", 53, "port to listen to dns requests (defaults to 53)")
flag.IntVar(&httpPort, "httpport", 6785, "port to listen to HTTP requests (defaults to 6785)")
flag.BoolVar(&watch, "watch", false, "watch the docker socket for container events")
flag.Parse()
err := weavedns.StartServer(ifaceName, dnsPort, httpPort, wait)
var zone = new(weavedns.ZoneDb)
if watch {
err := weavedns.StartUpdater(apiPath, zone)
if err != nil {
log.Fatal("Unable to start watcher", err)
}
}
err := weavedns.StartServer(zone, ifaceName, dnsPort, httpPort, wait)
if err != nil {
log.Fatalf("Failed to start server: %s", err)
}
+2 -2
View File
@@ -9,10 +9,10 @@ import (
type MDNSServer struct {
localAddrs []net.Addr
sendconn *net.UDPConn
zone *ZoneDb
zone Zone
}
func NewMDNSServer(zone *ZoneDb) (*MDNSServer, error) {
func NewMDNSServer(zone Zone) (*MDNSServer, error) {
//log.Println("minimalServer sending:", buf)
// This is a bit of a kludge - per the RFC we should send responses from 5353, but that doesn't seem to work
sendconn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
+1 -2
View File
@@ -100,9 +100,8 @@ func notUsHandler() dns.HandlerFunc {
}
}
func StartServer(ifaceName string, dnsPort int, httpPort int, wait int) error {
func StartServer(zone Zone, ifaceName string, dnsPort int, httpPort int, wait int) error {
var zone = new(ZoneDb)
go ListenHttp(zone, httpPort)
var iface *net.Interface = nil
+34
View File
@@ -0,0 +1,34 @@
package weavedns
import (
"github.com/fsouza/go-dockerclient"
"log"
)
func StartUpdater(apiPath string, zone Zone) error {
client, err := docker.NewClient(apiPath)
if err != nil {
log.Fatalf("Unable to connect to Docker API on %s: %s", apiPath, err)
}
events := make(chan *docker.APIEvents)
client.AddEventListener(events)
log.Printf("Using Docker API on %s", apiPath)
go func() {
for event := range events {
handleEvent(zone, event, client)
}
}()
return nil
}
func handleEvent(zone Zone, event *docker.APIEvents, client *docker.Client) error {
switch event.Status {
case "die":
id := event.ID
zone.DeleteRecordsFor(id)
}
return nil
}
+16
View File
@@ -10,6 +10,7 @@ import (
type Zone interface {
AddRecord(string, string, net.IP, net.IP, *net.IPNet) error
DeleteRecord(ident string, weave_ip net.IP) error
DeleteRecordsFor(ident string) error
MatchLocal(string) (net.IP, error)
}
@@ -99,3 +100,18 @@ func (zone *ZoneDb) DeleteRecord(ident string, weave_ip net.IP) error {
return nil
}
func (zone *ZoneDb) DeleteRecordsFor(ident string) error {
zone.mx.Lock()
defer zone.mx.Unlock()
w := 0 // write index
for _, r := range zone.recs {
if r.Ident != ident {
zone.recs[w] = r
w++
}
}
zone.recs = zone.recs[:w]
return nil
}
+30
View File
@@ -48,4 +48,34 @@ func TestZone(t *testing.T) {
if _, ok := err.(LookupError); !ok {
t.Fatal("Unexpected result when deleting record", success_test_name, err)
}
}
func TestDeleteFor(t *testing.T) {
var (
id = "foobar"
name = "foo.weave."
addr1 = "10.1.2.3/24"
addr2 = "10.2.7.8/24"
docker_ip = "172.16.0.4"
)
zone := new(ZoneDb)
ip := net.ParseIP(docker_ip)
for _, addr := range []string{addr1, addr2} {
weave_ip, subnet, _ := net.ParseCIDR(addr)
err := zone.AddRecord(id, name, ip, weave_ip, subnet)
if err != nil {
t.Fatal(err)
}
}
_, err := zone.MatchLocal(name)
if err != nil {
t.Fatal("Did not get result for lookup")
}
err = zone.DeleteRecordsFor(id)
_, err = zone.MatchLocal(name)
if _, ok := err.(LookupError); !ok {
t.Fatal("Expected no results after deleting records for ident")
}
}
-53
View File
@@ -1,53 +0,0 @@
package main
import (
"flag"
"fmt"
"github.com/fsouza/go-dockerclient"
"log"
"net/http"
)
func main() {
var (
updatePath string
apiPath string
)
flag.StringVar(&updatePath, "endpoint", "", "Endpoint to which to send updates")
flag.StringVar(&apiPath, "api", "unix:///var/run/docker.sock", "Path to Docker API socket")
flag.Parse()
// TODO: check status on endpoint
client, err := docker.NewClient(apiPath)
if err != nil {
log.Fatalf("Unable to connect to Docker API on %s: %s", apiPath, err)
}
events := make(chan *docker.APIEvents)
done := make(chan bool)
client.AddEventListener(events)
log.Printf("Using Docker API on %s", apiPath)
log.Printf("Posting updates to ", updatePath)
go func() {
for event := range events {
handleEvent(event, client, updatePath)
}
done <- true
}()
<-done
}
func handleEvent(event *docker.APIEvents, client *docker.Client, endpoint string) error {
switch event.Status {
case "die":
id := event.ID
url := fmt.Sprintf("%s/name/%s", endpoint, id)
client := &http.Client{}
req, _ := http.NewRequest("DELETE", url, nil)
client.Do(req)
}
return nil
}