Renamed variables for consistency

This commit is contained in:
Michael Bridgen committed 2014-10-23 16:23:55 +01:00
1 parent c63b163703
commit 840c0b9f86
10 files changed
+135 -134

No files matched your search

+17 -17
View File
@@ -35,32 +35,32 @@ func ListenHttp(domain string, db Zone, port int) {
switch r.Method {
case "PUT":
identifier, weave_ipstr, err := parseUrl(r.URL.Path)
identifier, weaveIPstr, err := parseUrl(r.URL.Path)
name := r.FormValue("fqdn")
prefix := r.FormValue("routing_prefix")
local_ip := r.FormValue("local_ip")
localIP := r.FormValue("local_ip")
if identifier == "" || weave_ipstr == "" || name == "" || prefix == "" || local_ip == "" {
if identifier == "" || weaveIPstr == "" || name == "" || prefix == "" || localIP == "" {
reqError("Invalid request", "Invalid request: %s, %s", r.URL, r.Form)
return
}
ip := net.ParseIP(local_ip)
ip := net.ParseIP(localIP)
if ip == nil {
reqError("Invalid IP in request", "Invalid IP in request: %s", local_ip)
reqError("Invalid IP in request", "Invalid IP in request: %s", localIP)
return
}
weave_cidr := weave_ipstr + "/" + prefix
weave_ip, subnet, err := net.ParseCIDR(weave_cidr)
weaveCIDR := weaveIPstr + "/" + prefix
weaveIP, subnet, err := net.ParseCIDR(weaveCIDR)
if err != nil {
reqError("Invalid CIDR", "Invalid CIDR in request: %s", weave_cidr)
reqError("Invalid CIDR", "Invalid CIDR in request: %s", weaveCIDR)
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)
Info.Printf("Adding %s (%s) -> %s", name, localIP, weaveCIDR)
err = db.AddRecord(identifier, name, ip, weaveIP, subnet)
if err != nil {
dup, ok := err.(DuplicateError)
if !ok {
@@ -78,19 +78,19 @@ func ListenHttp(domain string, db Zone, port int) {
}
case "DELETE":
identifier, weave_ipstr, err := parseUrl(r.URL.Path)
if identifier == "" || weave_ipstr == "" {
identifier, weaveIPstr, err := parseUrl(r.URL.Path)
if identifier == "" || weaveIPstr == "" {
reqError("Invalid Request", "Invalid request: %s, %s", r.URL, r.Form)
return
}
weave_ip := net.ParseIP(weave_ipstr)
if weave_ip == nil {
reqError("Invalid IP in request", "Invalid IP in request: %s", weave_ipstr)
weaveIP := net.ParseIP(weaveIPstr)
if weaveIP == nil {
reqError("Invalid IP in request", "Invalid IP in request: %s", weaveIPstr)
return
}
Info.Printf("Deleting %s (%s)", identifier, weave_ipstr)
err = db.DeleteRecord(identifier, weave_ip)
Info.Printf("Deleting %s (%s)", identifier, weaveIPstr)
err = db.DeleteRecord(identifier, weaveIP)
if err != nil {
if _, ok := err.(LookupError); !ok {
httpErrorAndLog(
+22 -22
View File
@@ -19,60 +19,60 @@ func genForm(method string, url string, data url.Values) (resp *http.Response, e
func TestHttp(t *testing.T) {
var (
container_id = "deadbeef"
test_domain = "weave.local."
success_test_name = "test1." + test_domain
test_addr1 = "10.0.2.1/24"
docker_ip = "9.8.7.6"
containerID = "deadbeef"
testDomain = "weave.local."
successTestName = "test1." + testDomain
testAddr1 = "10.0.2.1/24"
dockerIP = "9.8.7.6"
)
var zone = new(ZoneDb)
port := rand.Intn(10000) + 32768
fmt.Println("Http test on port", port)
go ListenHttp(test_domain, zone, port)
go ListenHttp(testDomain, zone, port)
time.Sleep(100 * time.Millisecond) // Allow for http server to get going
// Ask the http server to add our test address into the database
addr_parts := strings.Split(test_addr1, "/")
addr_url := fmt.Sprintf("http://localhost:%d/name/%s/%s", port, container_id, addr_parts[0])
resp, err := genForm("PUT", addr_url,
url.Values{"fqdn": {success_test_name}, "local_ip": {docker_ip}, "routing_prefix": {addr_parts[1]}})
addrParts := strings.Split(testAddr1, "/")
addrUrl := fmt.Sprintf("http://localhost:%d/name/%s/%s", port, containerID, addrParts[0])
resp, err := genForm("PUT", addrUrl,
url.Values{"fqdn": {successTestName}, "local_ip": {dockerIP}, "routing_prefix": {addrParts[1]}})
assertNoErr(t, err)
assertStatus(t, resp.StatusCode, http.StatusOK, "http response")
// Check that the address is now there.
ip, err := zone.MatchLocal(success_test_name)
ip, err := zone.MatchLocal(successTestName)
assertNoErr(t, err)
weave_ip, _, _ := net.ParseCIDR(test_addr1)
if !ip.Equal(weave_ip) {
t.Fatal("Unexpected result for", success_test_name, ip)
weaveIP, _, _ := net.ParseCIDR(testAddr1)
if !ip.Equal(weaveIP) {
t.Fatal("Unexpected result for", successTestName, ip)
}
// Adding exactly the same address should be OK
resp, err = genForm("PUT", addr_url,
url.Values{"fqdn": {success_test_name}, "local_ip": {docker_ip}, "routing_prefix": {addr_parts[1]}})
resp, err = genForm("PUT", addrUrl,
url.Values{"fqdn": {successTestName}, "local_ip": {dockerIP}, "routing_prefix": {addrParts[1]}})
assertNoErr(t, err)
assertStatus(t, resp.StatusCode, http.StatusOK, "http success response for duplicate add")
// Now try adding the same address again with a different ident - should fail
other_url := fmt.Sprintf("http://localhost:%d/name/%s/%s", port, "other", addr_parts[0])
resp, err = genForm("PUT", other_url,
url.Values{"fqdn": {success_test_name}, "local_ip": {docker_ip}, "routing_prefix": {addr_parts[1]}})
otherUrl := fmt.Sprintf("http://localhost:%d/name/%s/%s", port, "other", addrParts[0])
resp, err = genForm("PUT", otherUrl,
url.Values{"fqdn": {successTestName}, "local_ip": {dockerIP}, "routing_prefix": {addrParts[1]}})
assertNoErr(t, err)
assertStatus(t, resp.StatusCode, http.StatusConflict, "http response")
// Delete the address
resp, err = genForm("DELETE", addr_url, nil)
resp, err = genForm("DELETE", addrUrl, nil)
assertNoErr(t, err)
assertStatus(t, resp.StatusCode, http.StatusOK, "http response")
// Check that the address is not there now.
_, err = zone.MatchLocal(success_test_name)
_, err = zone.MatchLocal(successTestName)
assertErrorType(t, err, (*LookupError)(nil), "nonexistent lookup")
// Delete the address again, it should accept this
resp, err = genForm("DELETE", addr_url, nil)
resp, err = genForm("DELETE", addrUrl, nil)
assertNoErr(t, err)
assertStatus(t, resp.StatusCode, http.StatusOK, "http response")
+5 -5
View File
@@ -8,7 +8,7 @@ import (
)
const (
standard_log_flags = log.Ldate | log.Ltime | log.Lshortfile
standardLogFlags = log.Ldate | log.Ltime | log.Lshortfile
)
// Inspired by http://www.goinggo.net/2013/11/using-log-package-in-go.html
@@ -25,10 +25,10 @@ func InitLogging(debugHandle io.Writer,
warningHandle io.Writer,
errorHandle io.Writer) {
Debug = log.New(debugHandle, "DEBUG: ", standard_log_flags)
Info = log.New(infoHandle, "INFO: ", standard_log_flags)
Warning = log.New(warningHandle, "WARNING: ", standard_log_flags)
Error = log.New(errorHandle, "ERROR: ", standard_log_flags)
Debug = log.New(debugHandle, "DEBUG: ", standardLogFlags)
Info = log.New(infoHandle, "INFO: ", standardLogFlags)
Warning = log.New(warningHandle, "WARNING: ", standardLogFlags)
Error = log.New(errorHandle, "ERROR: ", standardLogFlags)
}
func init() {
+3 -3
View File
@@ -141,12 +141,12 @@ func (c *MDNSClient) checkInFlightQueries() time.Duration {
after := MaxDuration
for name, query := range c.inflight {
// Invariant on responseInfos: they are in non-descending order of timeout.
num_closed := 0
numClosed := 0
for _, item := range query.responseInfos {
duration := item.timeout.Sub(now)
if duration <= 0 { // timed out
close(item.ch)
num_closed++
numClosed++
} else {
if duration < after {
after = duration
@@ -155,7 +155,7 @@ func (c *MDNSClient) checkInFlightQueries() time.Duration {
}
}
// Remove timed-out items from the slice
query.responseInfos = query.responseInfos[num_closed:]
query.responseInfos = query.responseInfos[numClosed:]
if len(query.responseInfos) == 0 {
delete(c.inflight, name)
}
+21 -21
View File
@@ -9,9 +9,9 @@ import (
)
var (
success_test_name = "test1.weave."
fail_test_name = "test2.weave."
test_addr = net.ParseIP("9.8.7.6")
successTestName = "test1.weave."
failTestName = "test2.weave."
testAddr = net.ParseIP("9.8.7.6")
)
func minimalServer(w dns.ResponseWriter, req *dns.Msg) {
@@ -22,7 +22,7 @@ func minimalServer(w dns.ResponseWriter, req *dns.Msg) {
if len(req.Question) != 1 {
return // We only handle single-question messages
}
if req.Question[0].Name != success_test_name {
if req.Question[0].Name != successTestName {
return // This is not the DNS record you are looking for
}
@@ -31,7 +31,7 @@ func minimalServer(w dns.ResponseWriter, req *dns.Msg) {
hdr := dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeA,
Class: dns.ClassINET, Ttl: 3600}
a := &dns.A{hdr, test_addr}
a := &dns.A{hdr, testAddr}
m.Answer = append(m.Answer, a)
buf, err := m.Pack()
@@ -78,24 +78,24 @@ func setup(t *testing.T) (*MDNSClient, *dns.Server, error) {
}
type testContext struct {
received_addr net.IP
received_count int
channel chan *ResponseA
receivedAddr net.IP
receivedCount int
channel chan *ResponseA
}
func newTestContext() *testContext {
return &testContext{channel: make(chan *ResponseA, 4)}
}
func (c *testContext) checkResponse(t *testing.T, channel_ok bool, resp *ResponseA) {
if !channel_ok {
func (c *testContext) checkResponse(t *testing.T, channelOk bool, resp *ResponseA) {
if !channelOk {
c.channel = nil
return
}
assertNoErr(t, resp.Err)
log.Printf("Got address response %s addr %s", resp.Name, resp.Addr)
c.received_addr = resp.Addr
c.received_count++
c.receivedAddr = resp.Addr
c.receivedCount++
}
func TestSimpleQuery(t *testing.T) {
@@ -107,13 +107,13 @@ func TestSimpleQuery(t *testing.T) {
context := newTestContext()
// First, a test we expect to succeed
mdnsClient.SendQuery(success_test_name, dns.TypeA, context.channel)
mdnsClient.SendQuery(successTestName, dns.TypeA, context.channel)
for resp := range context.channel {
context.checkResponse(t, true, resp)
}
if !context.received_addr.Equal(test_addr) || context.received_count != 1 {
t.Log("Unexpected result for", success_test_name, context.received_addr, context.received_count)
if !context.receivedAddr.Equal(testAddr) || context.receivedCount != 1 {
t.Log("Unexpected result for", successTestName, context.receivedAddr, context.receivedCount)
t.Fail()
}
@@ -124,8 +124,8 @@ func TestSimpleQuery(t *testing.T) {
context.checkResponse(t, true, resp)
}
if context.received_count > 0 {
t.Log("Unexpected result for test2.weave", context.received_addr)
if context.receivedCount > 0 {
t.Log("Unexpected result for test2.weave", context.receivedAddr)
t.Fail()
}
}
@@ -139,8 +139,8 @@ func TestParallelQuery(t *testing.T) {
context1 := newTestContext()
context2 := newTestContext()
go mdnsClient.SendQuery(success_test_name, dns.TypeA, context1.channel)
go mdnsClient.SendQuery(success_test_name, dns.TypeA, context2.channel)
go mdnsClient.SendQuery(successTestName, dns.TypeA, context1.channel)
go mdnsClient.SendQuery(successTestName, dns.TypeA, context2.channel)
timeout := time.After(2 * time.Second)
outerloop:
for context1.channel != nil || context2.channel != nil {
@@ -154,8 +154,8 @@ outerloop:
}
}
if !context1.received_addr.Equal(test_addr) || !context2.received_addr.Equal(test_addr) || context1.received_count != 1 || context2.received_count != 1 {
t.Log("Unexpected result for", success_test_name, context1.received_addr, context2.received_addr, context1.received_count, context2.received_count)
if !context1.receivedAddr.Equal(testAddr) || !context2.receivedAddr.Equal(testAddr) || context1.receivedCount != 1 || context2.receivedCount != 1 {
t.Log("Unexpected result for", successTestName, context1.receivedAddr, context2.receivedAddr, context1.receivedCount, context2.receivedCount)
t.Fail()
}
}
+16 -16
View File
@@ -9,8 +9,8 @@ import (
)
var (
container_id = "deadbeef"
test_addr1 = "10.0.2.1/24"
containerID = "deadbeef"
testAddr1 = "10.0.2.1/24"
)
func sendQuery(name string, querytype uint16) error {
@@ -32,17 +32,17 @@ func sendQuery(name string, querytype uint16) error {
func TestServerSimpleQuery(t *testing.T) {
log.Println("TestServerSimpleQuery starting")
var zone = new(ZoneDb)
docker_ip := net.ParseIP("9.8.7.6")
weave_ip, subnet, _ := net.ParseCIDR(test_addr1)
zone.AddRecord(container_id, "test.weave.", docker_ip, weave_ip, subnet)
dockerIP := net.ParseIP("9.8.7.6")
weaveIP, subnet, _ := net.ParseCIDR(testAddr1)
zone.AddRecord(containerID, "test.weave.", dockerIP, weaveIP, subnet)
mdnsServer, err := NewMDNSServer(zone)
assertNoErr(t, err)
err = mdnsServer.Start(nil)
assertNoErr(t, err)
var received_addr net.IP
received_count := 0
var receivedAddr net.IP
receivedCount := 0
// Implement a minimal listener for responses
multicast, err := LinkLocalMulticastListener(nil)
@@ -54,8 +54,8 @@ func TestServerSimpleQuery(t *testing.T) {
for _, answer := range r.Answer {
switch rr := answer.(type) {
case *dns.A:
received_addr = rr.A
received_count++
receivedAddr = rr.A
receivedCount++
}
}
}
@@ -71,21 +71,21 @@ func TestServerSimpleQuery(t *testing.T) {
time.Sleep(time.Second)
if received_count != 1 {
t.Log("Unexpected result count for test.weave", received_count)
if receivedCount != 1 {
t.Log("Unexpected result count for test.weave", receivedCount)
t.Fail()
}
if !received_addr.Equal(weave_ip) {
t.Log("Unexpected result for test.weave", received_addr)
if !receivedAddr.Equal(weaveIP) {
t.Log("Unexpected result for test.weave", receivedAddr)
t.Fail()
}
received_count = 0
receivedCount = 0
sendQuery("testfail.weave.", dns.TypeA)
if received_count != 0 {
t.Log("Unexpected result count for testfail.weave", received_count)
if receivedCount != 0 {
t.Log("Unexpected result count for testfail.weave", receivedCount)
t.Fail()
}
}
+8 -8
View File
@@ -48,13 +48,13 @@ func queryHandler(zone Zone, mdnsClient *MDNSClient) dns.HandlerFunc {
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
var responseMsg *dns.Msg
if len(replies) > 0 {
response_msg = makeDNSReply(r, q.Name, dns.TypeA, replies)
responseMsg = makeDNSReply(r, q.Name, dns.TypeA, replies)
} else {
response_msg = makeDNSFailResponse(r)
responseMsg = makeDNSFailResponse(r)
}
w.WriteMsg(response_msg)
w.WriteMsg(responseMsg)
}()
mdnsClient.SendQuery(q.Name, dns.TypeA, channel)
}
@@ -71,14 +71,14 @@ func notUsHandler() dns.HandlerFunc {
q := r.Question[0]
Debug.Printf("Non-local query: %s", q)
addrs, err := net.LookupIP(q.Name)
var response_msg *dns.Msg
var responseMsg *dns.Msg
if err == nil {
response_msg = makeDNSReply(r, q.Name, q.Qtype, addrs)
responseMsg = makeDNSReply(r, q.Name, q.Qtype, addrs)
} else {
response_msg = makeDNSFailResponse(r)
responseMsg = makeDNSFailResponse(r)
Debug.Print("Failed fallback lookup", err)
}
w.WriteMsg(response_msg)
w.WriteMsg(responseMsg)
}
}
+6 -6
View File
@@ -18,15 +18,15 @@ func assertStatus(t *testing.T, got int, wanted int, desc string) {
}
func assertErrorInterface(t *testing.T, got interface{}, wanted interface{}, desc string) {
got_t, wanted_t := reflect.TypeOf(got), reflect.TypeOf(wanted).Elem()
if !got_t.Implements(wanted_t) {
t.Fatalf("Expected %s but got %s (%s)", wanted_t.String(), got_t.String(), desc)
gotT, wantedT := reflect.TypeOf(got), reflect.TypeOf(wanted).Elem()
if !gotT.Implements(wantedT) {
t.Fatalf("Expected %s but got %s (%s)", wantedT.String(), gotT.String(), desc)
}
}
func assertErrorType(t *testing.T, got interface{}, wanted interface{}, desc string) {
got_t, wanted_t := reflect.TypeOf(got), reflect.TypeOf(wanted).Elem()
if got_t != wanted_t {
t.Fatalf("Expected %s but got %s (%s)", wanted_t.String(), got_t.String(), desc)
gotT, wantedT := reflect.TypeOf(got), reflect.TypeOf(wanted).Elem()
if gotT != wantedT {
t.Fatalf("Expected %s but got %s (%s)", wantedT.String(), gotT.String(), desc)
}
}
+15 -14
View File
@@ -7,17 +7,18 @@ import (
)
type Zone interface {
AddRecord(string, string, net.IP, net.IP, *net.IPNet) error
DeleteRecord(ident string, weave_ip net.IP) error
AddRecord(ident string, name string, localIP net.IP,
weaveIP net.IP, weaveSubnet *net.IPNet) error
DeleteRecord(ident string, weaveIp net.IP) error
DeleteRecordsFor(ident string) error
MatchLocal(string) (net.IP, error)
MatchLocal(name string) (net.IP, error)
}
type Record struct {
Ident string
Name string
Ip net.IP
WeaveIp net.IP
LocalIP net.IP
WeaveIP net.IP
Subnet *net.IPNet
}
@@ -36,12 +37,12 @@ func (ops LookupError) Error() string {
type DuplicateError struct {
Name string
WeaveIp net.IP
WeaveIP net.IP
Ident string
}
func (err DuplicateError) Error() string {
return "Duplicate " + err.Name + "," + err.WeaveIp.String() + " in container " + err.Ident
return "Duplicate " + err.Name + "," + err.WeaveIP.String() + " for identity " + err.Ident
}
func (zone *ZoneDb) indexOf(match func(Record) bool) int {
@@ -58,29 +59,29 @@ func (zone *ZoneDb) MatchLocal(name string) (net.IP, error) {
defer zone.mx.RUnlock()
for _, r := range zone.recs {
if r.Name == name {
return r.WeaveIp, nil
return r.WeaveIP, nil
}
}
return nil, LookupError(name)
}
func (zone *ZoneDb) AddRecord(identifier string, name string, ip net.IP, weave_ip net.IP, weave_subnet *net.IPNet) error {
func (zone *ZoneDb) AddRecord(ident string, name string, localIP net.IP, weaveIP net.IP, weaveSubnet *net.IPNet) error {
zone.mx.Lock()
defer zone.mx.Unlock()
fqdn := dns.Fqdn(name)
if index := zone.indexOf(
func(r Record) bool { return r.Name == fqdn && r.WeaveIp.Equal(weave_ip) }); index != -1 {
return DuplicateError{fqdn, weave_ip, zone.recs[index].Ident}
func(r Record) bool { return r.Name == fqdn && r.WeaveIP.Equal(weaveIP) }); index != -1 {
return DuplicateError{fqdn, weaveIP, zone.recs[index].Ident}
}
zone.recs = append(zone.recs, Record{identifier, fqdn, ip, weave_ip, weave_subnet})
zone.recs = append(zone.recs, Record{ident, fqdn, localIP, weaveIP, weaveSubnet})
return nil
}
func (zone *ZoneDb) DeleteRecord(ident string, weave_ip net.IP) error {
func (zone *ZoneDb) DeleteRecord(ident string, weaveIP net.IP) error {
zone.mx.Lock()
defer zone.mx.Unlock()
if index := zone.indexOf(
func(r Record) bool { return r.Ident == ident && r.WeaveIp.Equal(weave_ip) }); index == -1 {
func(r Record) bool { return r.Ident == ident && r.WeaveIP.Equal(weaveIP) }); index == -1 {
return LookupError(ident)
} else {
zone.recs = append(zone.recs[:index], zone.recs[index+1:]...)
+22 -22
View File
@@ -7,57 +7,57 @@ import (
func TestZone(t *testing.T) {
var (
container_id = "deadbeef"
success_test_name = "test1.weave."
test_addr1 = "10.0.2.1/24"
docker_ip = "9.8.7.6"
containerID = "deadbeef"
successTestName = "test1.weave."
testAddr1 = "10.0.2.1/24"
dockerIP = "9.8.7.6"
)
var zone = new(ZoneDb)
ip := net.ParseIP(docker_ip)
weave_ip, subnet, _ := net.ParseCIDR(test_addr1)
err := zone.AddRecord(container_id, success_test_name, ip, weave_ip, subnet)
ip := net.ParseIP(dockerIP)
weaveIP, subnet, _ := net.ParseCIDR(testAddr1)
err := zone.AddRecord(containerID, successTestName, ip, weaveIP, subnet)
assertNoErr(t, err)
// Check that the address is now there.
found_ip, err := zone.MatchLocal(success_test_name)
foundIP, err := zone.MatchLocal(successTestName)
assertNoErr(t, err)
if !found_ip.Equal(weave_ip) {
t.Fatal("Unexpected result for", success_test_name, ip)
if !foundIP.Equal(weaveIP) {
t.Fatal("Unexpected result for", successTestName, ip)
}
// Now try to add the same address again
err = zone.AddRecord(container_id, success_test_name, ip, weave_ip, subnet)
err = zone.AddRecord(containerID, successTestName, ip, weaveIP, subnet)
assertErrorType(t, err, (*DuplicateError)(nil), "duplicate add")
// Now delete the record
err = zone.DeleteRecord(container_id, weave_ip)
err = zone.DeleteRecord(containerID, weaveIP)
assertNoErr(t, err)
// Check that the address is not there now.
_, err = zone.MatchLocal(success_test_name)
_, err = zone.MatchLocal(successTestName)
assertErrorType(t, err, (*LookupError)(nil), "after deleting record")
// Delete a record that isn't there
err = zone.DeleteRecord(container_id, net.ParseIP("0.0.0.0"))
err = zone.DeleteRecord(containerID, net.ParseIP("0.0.0.0"))
assertErrorType(t, err, (*LookupError)(nil), "when deleting record that doesn't exist")
}
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"
id = "foobar"
name = "foo.weave."
addr1 = "10.1.2.3/24"
addr2 = "10.2.7.8/24"
dockerIP = "172.16.0.4"
)
zone := new(ZoneDb)
ip := net.ParseIP(docker_ip)
ip := net.ParseIP(dockerIP)
for _, addr := range []string{addr1, addr2} {
weave_ip, subnet, _ := net.ParseCIDR(addr)
err := zone.AddRecord(id, name, ip, weave_ip, subnet)
weaveIP, subnet, _ := net.ParseCIDR(addr)
err := zone.AddRecord(id, name, ip, weaveIP, subnet)
assertNoErr(t, err)
}