diff --git a/server/http.go b/server/http.go index 29484521..34c929be 100644 --- a/server/http.go +++ b/server/http.go @@ -50,6 +50,25 @@ func ListenHttp(db Zone, port int) { http.Error(w, err.Error(), http.StatusConflict) return } + case "DELETE": + identifier, weave_ipstr, err := parseUrl(r.URL.Path) + if identifier == "" || weave_ipstr == "" { + log.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) + http.Error(w, "Invalid IP in request", http.StatusBadRequest) + return + } + log.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) http.Error(w, "Unexpected http method: "+r.Method, http.StatusBadRequest) diff --git a/server/http_test.go b/server/http_test.go index 662f86d8..483dc920 100644 --- a/server/http_test.go +++ b/server/http_test.go @@ -63,6 +63,22 @@ func TestHttp(t *testing.T) { if resp.StatusCode != http.StatusConflict { t.Fatal("Unexpected http response", resp.Status) } + + // Delete the address + resp, err = genForm("DELETE", addr_url, nil) + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != http.StatusOK { + t.Fatal("Unexpected http response", resp.Status) + } + + // Check that the address is not there now. + _, err = zone.MatchLocal(success_test_name) + if _, ok := err.(LookupError); !ok { + t.Fatal(err) + } + // Would like to shut down the http server at the end of this test // but it's complicated. // See https://groups.google.com/forum/#!topic/golang-nuts/vLHWa5sHnCE diff --git a/server/zone.go b/server/zone.go index bc33fd5c..d3173949 100644 --- a/server/zone.go +++ b/server/zone.go @@ -9,6 +9,7 @@ import ( type Zone interface { AddRecord(string, string, net.IP, net.IP, *net.IPNet) error + DeleteRecord(ident string, weave_ip net.IP) error MatchLocal(string) (net.IP, error) } @@ -61,6 +62,15 @@ func (zone *ZoneDb) indexOfNameAddr(name string, addr net.IP) int { return -1 } +func (zone *ZoneDb) indexOfIdentAddr(ident string, addr net.IP) int { + for i, r := range zone.recs { + if r.Ident == ident && r.WeaveIp.Equal(addr) { + return i + } + } + return -1 +} + func (zone *ZoneDb) MatchLocal(name string) (net.IP, error) { zone.mx.Lock() defer zone.mx.Unlock() @@ -77,3 +87,15 @@ func (zone *ZoneDb) AddRecord(identifier string, name string, ip net.IP, weave_i zone.recs = append(zone.recs, Record{identifier, fqdn, ip, weave_ip, weave_subnet}) return nil } + +func (zone *ZoneDb) DeleteRecord(ident string, weave_ip net.IP) error { + zone.mx.Lock() + defer zone.mx.Unlock() + if index := zone.indexOfIdentAddr(ident, weave_ip); index == -1 { + return LookupError(ident) + } else { + zone.recs = append(zone.recs[:index], zone.recs[index+1:]...) + } + + return nil +} diff --git a/server/zone_test.go b/server/zone_test.go index 6f392c9d..a3c7b252 100644 --- a/server/zone_test.go +++ b/server/zone_test.go @@ -36,4 +36,16 @@ func TestZone(t *testing.T) { if _, ok := err.(DuplicateError); !ok { t.Fatal(err) } + + // Now delete the record + err = zone.DeleteRecord(container_id, weave_ip) + if err != nil { + t.Fatal(err) + } + + // Check that the address is not there now. + _, err = zone.MatchLocal(success_test_name) + if _, ok := err.(LookupError); !ok { + t.Fatal("Unexpected result when deleting record", success_test_name, err) + } }