From 791584d9f3381ca62d7a20aff0e4220a6e356d9f Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Tue, 2 Jun 2015 17:31:25 +0100 Subject: [PATCH] Allow lookup of IPAM-allocated addresses --- ipam/allocator.go | 14 ++++++++++++++ ipam/http.go | 9 +++++++++ ipam/http_test.go | 15 ++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ipam/allocator.go b/ipam/allocator.go index 62017db6..b6260b50 100644 --- a/ipam/allocator.go +++ b/ipam/allocator.go @@ -208,6 +208,20 @@ func (alloc *Allocator) Allocate(ident string, cancelChan <-chan bool) (address. return result.addr, result.err } +func (alloc *Allocator) Lookup(ident string) (address.Address, error) { + resultChan := make(chan allocateResult) + alloc.actionChan <- func() { + addr, found := alloc.owned[ident] + if found { + resultChan <- allocateResult{addr: addr} + return + } + resultChan <- allocateResult{err: fmt.Errorf("lookup: no address found")} + } + result := <-resultChan + return result.addr, result.err +} + // Claim an address that we think we should own (Sync) func (alloc *Allocator) Claim(ident string, addr address.Address, cancelChan <-chan bool) error { resultChan := make(chan error) diff --git a/ipam/http.go b/ipam/http.go index c7778996..4e7cd907 100644 --- a/ipam/http.go +++ b/ipam/http.go @@ -33,6 +33,15 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router) { w.WriteHeader(204) }) + router.Methods("GET").Path("/ip/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + addr, err := alloc.Lookup(mux.Vars(r)["id"]) + if err != nil { + http.NotFound(w, r) + return + } + fmt.Fprintf(w, "%s/%d", addr.String(), alloc.prefixLen) + }) + router.Methods("POST").Path("/ip/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { closedChan := w.(http.CloseNotifier).CloseNotify() ident := mux.Vars(r)["id"] diff --git a/ipam/http_test.go b/ipam/http_test.go index b8c972f0..f1a828d1 100644 --- a/ipam/http_test.go +++ b/ipam/http_test.go @@ -25,6 +25,14 @@ func HTTPPost(t *testing.T, url string) string { return string(body) } +func HTTPGet(t *testing.T, url string) string { + resp, err := http.Get(url) + wt.AssertNoErr(t, err) + defer resp.Body.Close() + body, _ := ioutil.ReadAll(resp.Body) + return string(body) +} + func doHTTP(method string, url string) (resp *http.Response, err error) { req, _ := http.NewRequest(method, url, nil) return http.DefaultClient.Do(req) @@ -72,6 +80,8 @@ func TestHttp(t *testing.T) { // Ask the http server for a new address cidr1 := HTTPPost(t, allocURL(port, containerID)) wt.AssertEqualString(t, cidr1, testAddr1+netSuffix, "address") + check := HTTPGet(t, allocURL(port, containerID)) + wt.AssertEqualString(t, check, cidr1, "address") // Ask the http server for another address and check it's different cidr2 := HTTPPost(t, allocURL(port, container2)) @@ -80,9 +90,12 @@ func TestHttp(t *testing.T) { // Ask for the first container again and we should get the same address again cidr1a := HTTPPost(t, allocURL(port, containerID)) wt.AssertEqualString(t, cidr1a, testAddr1+netSuffix, "address") - // Now free the first one, and we should get it back when we ask doHTTP("DELETE", allocURL(port, containerID)) + resp, err := doHTTP("GET", allocURL(port, containerID)) + wt.AssertNoErr(t, err) + wt.AssertStatus(t, resp.StatusCode, http.StatusNotFound, "http response") + cidr3 := HTTPPost(t, allocURL(port, container3)) wt.AssertEqualString(t, cidr3, testAddr1+netSuffix, "address")