Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
dd27396ce0
9 files changed
+80
-47
No files matched your search
@@ -25,20 +25,20 @@ for other containers:
|
||||
|
||||
```bash
|
||||
$ dns_ip=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' weavedns)
|
||||
$ shell1=$(weave run 10.0.1.2/24 --dns=$dns_ip -t ubuntu /bin/bash)
|
||||
$ shell1=$(weave run 10.0.1.2/24 -h shell.weave.local --dns=$dns_ip -t ubuntu /bin/bash)
|
||||
```
|
||||
|
||||
To associate a hostname with an IP, use an HTTP PUT to the DNS server:
|
||||
|
||||
```bash
|
||||
$ shell1_ip=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' $shell1)
|
||||
$ curl -X PUT "http://$dns_ip:6785/name/$shell1/10.0.1.2?fqdn=shell1.weave&routing_prefix=24&local_ip=$shell1_ip"
|
||||
$ curl -X PUT "http://$dns_ip:6785/name/$shell1/10.0.1.2?fqdn=shell1.weave.local&routing_prefix=24&local_ip=$shell1_ip"
|
||||
```
|
||||
|
||||
You should now be able to look up the name:
|
||||
|
||||
```bash
|
||||
$ dig @$dns_ip +short shell1.weave
|
||||
$ dig @$dns_ip +short shell1.weave.local
|
||||
```
|
||||
|
||||
By default, the server will also watch docker events and remove
|
||||
|
||||
@@ -3,14 +3,12 @@ package main
|
||||
import (
|
||||
"flag"
|
||||
"github.com/zettio/weavedns/server"
|
||||
"log"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Println(os.Args)
|
||||
|
||||
var (
|
||||
ifaceName string
|
||||
apiPath string
|
||||
@@ -18,6 +16,7 @@ func main() {
|
||||
httpPort int
|
||||
wait int
|
||||
watch bool
|
||||
debug bool
|
||||
)
|
||||
|
||||
flag.StringVar(&ifaceName, "iface", "", "name of interface to use for multicast")
|
||||
@@ -26,14 +25,21 @@ func main() {
|
||||
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", true, "watch the docker socket for container events")
|
||||
flag.BoolVar(&debug, "debug", false, "output debugging info to stderr")
|
||||
flag.Parse()
|
||||
|
||||
debugOut := ioutil.Discard
|
||||
if debug {
|
||||
debugOut = os.Stderr
|
||||
}
|
||||
weavedns.InitLogging(debugOut, os.Stdout, os.Stdout, os.Stderr)
|
||||
|
||||
var zone = new(weavedns.ZoneDb)
|
||||
|
||||
if watch {
|
||||
err := weavedns.StartUpdater(apiPath, zone)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to start watcher", err)
|
||||
weavedns.Error.Fatal("Unable to start watcher", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +48,12 @@ func main() {
|
||||
var err error
|
||||
iface, err = weavedns.EnsureInterface(ifaceName, wait)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
weavedns.Error.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
err := weavedns.StartServer(zone, iface, dnsPort, httpPort, wait)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to start server", err)
|
||||
weavedns.Error.Fatal("Failed to start server", err)
|
||||
}
|
||||
}
|
||||
+19
-15
@@ -3,7 +3,7 @@ package weavedns
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"github.com/miekg/dns"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -18,7 +18,7 @@ func parseUrl(url string) (identifier string, ipaddr string, err error) {
|
||||
return parts[2], parts[3], nil
|
||||
}
|
||||
|
||||
func ListenHttp(db Zone, port int) {
|
||||
func ListenHttp(domain string, db Zone, port int) {
|
||||
http.HandleFunc("/name/", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case "PUT":
|
||||
@@ -27,56 +27,60 @@ func ListenHttp(db Zone, port int) {
|
||||
prefix := r.FormValue("routing_prefix")
|
||||
local_ip := r.FormValue("local_ip")
|
||||
if identifier == "" || weave_ipstr == "" || name == "" || prefix == "" || local_ip == "" {
|
||||
log.Printf("Invalid request: %s, %s", r.URL, r.Form)
|
||||
Warning.Printf("Invalid request: %s, %s", r.URL, r.Form)
|
||||
http.Error(w, "Invalid Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
ip := net.ParseIP(local_ip)
|
||||
if ip == nil {
|
||||
log.Printf("Invalid IP in request: %s", local_ip)
|
||||
Warning.Printf("Invalid IP in request: %s", local_ip)
|
||||
http.Error(w, "Invalid IP in request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
weave_cidr := weave_ipstr + "/" + prefix
|
||||
weave_ip, subnet, err := net.ParseCIDR(weave_cidr)
|
||||
if err != nil {
|
||||
log.Printf("Invalid CIDR in request: %s", weave_cidr)
|
||||
Warning.Printf("Invalid CIDR in request: %s", weave_cidr)
|
||||
http.Error(w, fmt.Sprintf("Invalid CIDR: %s", weave_cidr), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
log.Printf("Adding %s (%s) -> %s", name, local_ip, weave_cidr)
|
||||
err = db.AddRecord(identifier, name, ip, weave_ip, subnet)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusConflict)
|
||||
return
|
||||
if dns.IsSubDomain(domain, name) {
|
||||
Info.Printf("Adding %s (%s) -> %s", name, local_ip, weave_cidr)
|
||||
err = db.AddRecord(identifier, name, ip, weave_ip, subnet)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusConflict)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
Info.Printf("Ignoring name %s, not in %s", name, domain)
|
||||
}
|
||||
case "DELETE":
|
||||
identifier, weave_ipstr, err := parseUrl(r.URL.Path)
|
||||
if identifier == "" || weave_ipstr == "" {
|
||||
log.Printf("Invalid request: %s, %s", r.URL, r.Form)
|
||||
Warning.Printf("Invalid request: %s, %s", r.URL, r.Form)
|
||||
http.Error(w, "Invalid Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
weave_ip := net.ParseIP(weave_ipstr)
|
||||
if weave_ip == nil {
|
||||
log.Printf("Invalid IP in request: %s", weave_ipstr)
|
||||
Warning.Printf("Invalid IP in request: %s", weave_ipstr)
|
||||
http.Error(w, "Invalid IP in request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
log.Printf("Deleting %s (%s)", identifier, weave_ipstr)
|
||||
Info.Printf("Deleting %s (%s)", identifier, weave_ipstr)
|
||||
err = db.DeleteRecord(identifier, weave_ip)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
default:
|
||||
log.Println("Unexpected http method", r.Method)
|
||||
Warning.Println("Unexpected http method", r.Method)
|
||||
http.Error(w, "Unexpected http method: "+r.Method, http.StatusBadRequest)
|
||||
}
|
||||
})
|
||||
address := fmt.Sprintf(":%d", port)
|
||||
err := http.ListenAndServe(address, nil)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to create http listener: ", err)
|
||||
Error.Fatal("Unable to create http listener: ", err)
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -2,7 +2,6 @@ package weavedns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
@@ -12,13 +11,13 @@ func EnsureInterface(ifaceName string, wait int) (iface *net.Interface, err erro
|
||||
if err == nil || wait == 0 {
|
||||
return
|
||||
}
|
||||
log.Println("Waiting for interface", ifaceName, "to come up")
|
||||
Info.Println("Waiting for interface", ifaceName, "to come up")
|
||||
for ; err != nil && wait > 0; wait -= 1 {
|
||||
time.Sleep(1 * time.Second)
|
||||
iface, err = findInterface(ifaceName)
|
||||
}
|
||||
if err == nil {
|
||||
log.Println("Interface", ifaceName, "is up")
|
||||
Info.Println("Interface", ifaceName, "is up")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package weavedns
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
// Inspired by http://www.goinggo.net/2013/11/using-log-package-in-go.html
|
||||
|
||||
var (
|
||||
Debug *log.Logger
|
||||
Info *log.Logger
|
||||
Warning *log.Logger
|
||||
Error *log.Logger
|
||||
)
|
||||
|
||||
func InitLogging(debugHandle io.Writer,
|
||||
infoHandle io.Writer,
|
||||
warningHandle io.Writer,
|
||||
errorHandle io.Writer) {
|
||||
|
||||
Debug = log.New(debugHandle, "DEBUG: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
Info = log.New(infoHandle, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
Warning = log.New(warningHandle, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
Error = log.New(errorHandle, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
}
|
||||
@@ -79,7 +79,6 @@ func (c *MDNSClient) Start(ifi *net.Interface) error {
|
||||
}
|
||||
|
||||
handleMDNS := func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
//log.Println("client received:", r)
|
||||
// Don't want to handle queries here, so filter anything out that isn't a response
|
||||
if len(r.Answer) > 0 {
|
||||
c.ResponseCallback(r)
|
||||
|
||||
@@ -2,7 +2,6 @@ package weavedns
|
||||
|
||||
import (
|
||||
"github.com/miekg/dns"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
@@ -13,7 +12,6 @@ type MDNSServer struct {
|
||||
}
|
||||
|
||||
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})
|
||||
if err != nil {
|
||||
@@ -69,7 +67,7 @@ func (s *MDNSServer) Start(ifi *net.Interface) error {
|
||||
} else if s.addrIsLocal(w.RemoteAddr()) {
|
||||
// ignore this - it's our own query received via multicast
|
||||
} else {
|
||||
log.Printf("Failed MDNS lookup for %s", q.Name)
|
||||
Debug.Printf("Failed MDNS lookup for %s", q.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-12
@@ -3,12 +3,11 @@ package weavedns
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/miekg/dns"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
const (
|
||||
LOCAL_DOMAIN = "weave"
|
||||
LOCAL_DOMAIN = "weave.local."
|
||||
)
|
||||
|
||||
func makeDNSFailResponse(r *dns.Msg) *dns.Msg {
|
||||
@@ -22,19 +21,20 @@ func makeDNSFailResponse(r *dns.Msg) *dns.Msg {
|
||||
func queryHandler(zone Zone, mdnsClient *MDNSClient) dns.HandlerFunc {
|
||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
q := r.Question[0]
|
||||
Debug.Printf("Local query: %s", q)
|
||||
ip, err := zone.MatchLocal(q.Name)
|
||||
if err == nil {
|
||||
m := makeDNSReply(r, q.Name, dns.TypeA, []net.IP{ip})
|
||||
w.WriteMsg(m)
|
||||
} else {
|
||||
log.Printf("Failed lookup for %s; sending mDNS query", q.Name)
|
||||
Debug.Printf("Failed lookup for %s; sending mDNS query", q.Name)
|
||||
// We don't know the answer; see if someone else does
|
||||
channel := make(chan *ResponseA, ChannelSize)
|
||||
replies := make([]net.IP, 0)
|
||||
go func() {
|
||||
// Loop terminates when channel is closed by MDNSClient on timeout
|
||||
for resp := range channel {
|
||||
log.Printf("Got address response %s to query %s addr %s", resp.Name, q.Name, resp.Addr)
|
||||
Debug.Printf("Got address response %s to query %s addr %s", resp.Name, q.Name, resp.Addr)
|
||||
replies = append(replies, resp.Addr)
|
||||
}
|
||||
var response_msg *dns.Msg
|
||||
@@ -58,29 +58,31 @@ func queryHandler(zone Zone, mdnsClient *MDNSClient) dns.HandlerFunc {
|
||||
func notUsHandler() dns.HandlerFunc {
|
||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
q := r.Question[0]
|
||||
Debug.Printf("Non-local query: %s", q)
|
||||
addrs, err := net.LookupIP(q.Name)
|
||||
var response_msg *dns.Msg
|
||||
if err == nil {
|
||||
response_msg = makeDNSReply(r, q.Name, q.Qtype, addrs)
|
||||
} else {
|
||||
response_msg = makeDNSFailResponse(r)
|
||||
Debug.Print("Failed fallback lookup", err)
|
||||
}
|
||||
w.WriteMsg(response_msg)
|
||||
}
|
||||
}
|
||||
|
||||
func StartServer(zone Zone, iface *net.Interface, dnsPort int, httpPort int, wait int) error {
|
||||
go ListenHttp(zone, httpPort)
|
||||
go ListenHttp(LOCAL_DOMAIN, zone, httpPort)
|
||||
|
||||
mdnsClient, err := NewMDNSClient()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
Error.Fatal(err)
|
||||
} else {
|
||||
log.Printf("Using mDNS on %s", iface.Name)
|
||||
Info.Printf("Using mDNS on %s", iface.Name)
|
||||
}
|
||||
err = mdnsClient.Start(iface)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
Error.Fatal(err)
|
||||
}
|
||||
|
||||
LocalServeMux := dns.NewServeMux()
|
||||
@@ -89,19 +91,19 @@ func StartServer(zone Zone, iface *net.Interface, dnsPort int, httpPort int, wai
|
||||
|
||||
mdnsServer, err := NewMDNSServer(zone)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
Error.Fatal(err)
|
||||
}
|
||||
err = mdnsServer.Start(iface)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
Error.Fatal(err)
|
||||
}
|
||||
|
||||
address := fmt.Sprintf(":%d", dnsPort)
|
||||
err = dns.ListenAndServe(address, "udp", LocalServeMux)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
Error.Fatal(err)
|
||||
} else {
|
||||
log.Printf("Listening for DNS on %s", address)
|
||||
Info.Printf("Listening for DNS on %s", address)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+3
-4
@@ -2,19 +2,18 @@ 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)
|
||||
Error.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)
|
||||
Info.Printf("Using Docker API on %s", apiPath)
|
||||
|
||||
go func() {
|
||||
for event := range events {
|
||||
@@ -28,7 +27,7 @@ func handleEvent(zone Zone, event *docker.APIEvents, client *docker.Client) erro
|
||||
switch event.Status {
|
||||
case "die":
|
||||
id := event.ID
|
||||
log.Printf("Container %s down. Removing records", id)
|
||||
Info.Printf("Container %s down. Removing records", id)
|
||||
zone.DeleteRecordsFor(id)
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in new issue
Block a user