mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #194 from aboch/rest
REST API: Support query by partial id
This commit is contained in:
commit
ef6ddb33f5
2 changed files with 129 additions and 7 deletions
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/docker/libnetwork/types"
|
||||
|
@ -15,6 +16,7 @@ var (
|
|||
successResponse = responseStatus{Status: "Success", StatusCode: http.StatusOK}
|
||||
createdResponse = responseStatus{Status: "Created", StatusCode: http.StatusCreated}
|
||||
mismatchResponse = responseStatus{Status: "Body/URI parameter mismatch", StatusCode: http.StatusBadRequest}
|
||||
badQueryresponse = responseStatus{Status: "Unsupported query", StatusCode: http.StatusBadRequest}
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -23,14 +25,19 @@ const (
|
|||
// Router URL variable definition
|
||||
nwName = "{" + urlNwName + ":" + regex + "}"
|
||||
nwID = "{" + urlNwID + ":" + regex + "}"
|
||||
nwPID = "{" + urlNwPID + ":" + regex + "}"
|
||||
epName = "{" + urlEpName + ":" + regex + "}"
|
||||
epID = "{" + urlEpID + ":" + regex + "}"
|
||||
epPID = "{" + urlEpPID + ":" + regex + "}"
|
||||
cnID = "{" + urlCnID + ":" + regex + "}"
|
||||
|
||||
// Internal URL variable name, they can be anything
|
||||
urlNwName = "network-name"
|
||||
urlNwID = "network-id"
|
||||
urlNwPID = "network-partial-id"
|
||||
urlEpName = "endpoint-name"
|
||||
urlEpID = "endpoint-id"
|
||||
urlEpPID = "endpoint-partial-id"
|
||||
urlCnID = "container-id"
|
||||
)
|
||||
|
||||
|
@ -77,9 +84,12 @@ func (h *httpHandler) initRouter() {
|
|||
"GET": {
|
||||
// Order matters
|
||||
{"/networks", []string{"name", nwName}, procGetNetworks},
|
||||
{"/networks", []string{"partial-id", nwPID}, procGetNetworks},
|
||||
{"/networks", nil, procGetNetworks},
|
||||
{"/networks/" + nwID, nil, procGetNetwork},
|
||||
{"/networks/" + nwID + "/endpoints", []string{"name", epName}, procGetEndpoints},
|
||||
{"/networks/" + nwID + "/endpoints", []string{"partial-id", epPID}, procGetEndpoints},
|
||||
|
||||
{"/networks/" + nwID + "/endpoints/" + epID, nil, procGetEndpoint},
|
||||
},
|
||||
"POST": {
|
||||
|
@ -234,12 +244,26 @@ func procGetNetwork(c libnetwork.NetworkController, vars map[string]string, body
|
|||
func procGetNetworks(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
|
||||
var list []*networkResource
|
||||
|
||||
// If query parameter is specified, return a filtered collection
|
||||
if name, queryByName := vars[urlNwName]; queryByName {
|
||||
nw, errRsp := findNetwork(c, name, byName)
|
||||
if errRsp.isOK() {
|
||||
// Look for query filters and validate
|
||||
name, queryByName := vars[urlNwName]
|
||||
shortID, queryByPid := vars[urlNwPID]
|
||||
if queryByName && queryByPid {
|
||||
return nil, &badQueryresponse
|
||||
}
|
||||
|
||||
if queryByName {
|
||||
if nw, errRsp := findNetwork(c, name, byName); errRsp.isOK() {
|
||||
list = append(list, buildNetworkResource(nw))
|
||||
}
|
||||
} else if queryByPid {
|
||||
// Return all the prefix-matching networks
|
||||
l := func(nw libnetwork.Network) bool {
|
||||
if strings.HasPrefix(nw.ID(), shortID) {
|
||||
list = append(list, buildNetworkResource(nw))
|
||||
}
|
||||
return false
|
||||
}
|
||||
c.WalkNetworks(l)
|
||||
} else {
|
||||
for _, nw := range c.Networks() {
|
||||
list = append(list, buildNetworkResource(nw))
|
||||
|
@ -295,6 +319,13 @@ func procGetEndpoint(c libnetwork.NetworkController, vars map[string]string, bod
|
|||
}
|
||||
|
||||
func procGetEndpoints(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
|
||||
// Look for query filters and validate
|
||||
name, queryByName := vars[urlEpName]
|
||||
shortID, queryByPid := vars[urlEpPID]
|
||||
if queryByName && queryByPid {
|
||||
return nil, &badQueryresponse
|
||||
}
|
||||
|
||||
nwT, nwBy := detectNetworkTarget(vars)
|
||||
nw, errRsp := findNetwork(c, nwT, nwBy)
|
||||
if !errRsp.isOK() {
|
||||
|
@ -304,11 +335,19 @@ func procGetEndpoints(c libnetwork.NetworkController, vars map[string]string, bo
|
|||
var list []*endpointResource
|
||||
|
||||
// If query parameter is specified, return a filtered collection
|
||||
if epT, queryByName := vars[urlEpName]; queryByName {
|
||||
ep, errRsp := findEndpoint(c, nwT, epT, nwBy, byName)
|
||||
if errRsp.isOK() {
|
||||
if queryByName {
|
||||
if ep, errRsp := findEndpoint(c, nwT, name, nwBy, byName); errRsp.isOK() {
|
||||
list = append(list, buildEndpointResource(ep))
|
||||
}
|
||||
} else if queryByPid {
|
||||
// Return all the prefix-matching networks
|
||||
l := func(ep libnetwork.Endpoint) bool {
|
||||
if strings.HasPrefix(ep.ID(), shortID) {
|
||||
list = append(list, buildEndpointResource(ep))
|
||||
}
|
||||
return false
|
||||
}
|
||||
nw.WalkEndpoints(l)
|
||||
} else {
|
||||
for _, ep := range nw.Endpoints() {
|
||||
epr := buildEndpointResource(ep)
|
||||
|
|
|
@ -482,6 +482,43 @@ func TestGetNetworksAndEndpoints(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDetectGetNetworksInvalidQueryComposition(t *testing.T) {
|
||||
c, err := libnetwork.New()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vars := map[string]string{urlNwName: "x", urlNwPID: "y"}
|
||||
_, errRsp := procGetNetworks(c, vars, nil)
|
||||
if errRsp.StatusCode != http.StatusBadRequest {
|
||||
t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectGetEndpointsInvalidQueryComposition(t *testing.T) {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
|
||||
c, err := libnetwork.New()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = c.ConfigureNetworkDriver(bridgeNetType, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = c.NewNetwork(bridgeNetType, "network", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vars := map[string]string{urlNwName: "network", urlEpName: "x", urlEpPID: "y"}
|
||||
_, errRsp := procGetEndpoints(c, vars, nil)
|
||||
if errRsp.StatusCode != http.StatusBadRequest {
|
||||
t.Fatalf("Expected %d. Got: %v", http.StatusBadRequest, errRsp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindNetworkUtil(t *testing.T) {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
|
||||
|
@ -1281,6 +1318,29 @@ func TestEndToEnd(t *testing.T) {
|
|||
t.Fatalf("Incongruent resource found: %v", list[0])
|
||||
}
|
||||
|
||||
// Query network by partial id
|
||||
chars := []byte(nid)
|
||||
partial := string(chars[0 : len(chars)/2])
|
||||
req, err = http.NewRequest("GET", "/networks?partial-id="+partial, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handleRequest(rsp, req)
|
||||
if rsp.statusCode != http.StatusOK {
|
||||
t.Fatalf("Unexpectded failure: (%d): %s", rsp.statusCode, rsp.body)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rsp.body, &list)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(list) == 0 {
|
||||
t.Fatalf("Expected non empty list")
|
||||
}
|
||||
if list[0].Name != "network-fiftyfive" || nid != list[0].ID {
|
||||
t.Fatalf("Incongruent resource found: %v", list[0])
|
||||
}
|
||||
|
||||
// Get network by id
|
||||
req, err = http.NewRequest("GET", "/networks/"+nid, nil)
|
||||
if err != nil {
|
||||
|
@ -1373,6 +1433,29 @@ func TestEndToEnd(t *testing.T) {
|
|||
t.Fatalf("Incongruent resource found: %v", epList[0])
|
||||
}
|
||||
|
||||
// Query endpoint by partial id
|
||||
chars = []byte(eid)
|
||||
partial = string(chars[0 : len(chars)/2])
|
||||
req, err = http.NewRequest("GET", "/networks/"+nid+"/endpoints?partial-id="+partial, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handleRequest(rsp, req)
|
||||
if rsp.statusCode != http.StatusOK {
|
||||
t.Fatalf("Unexpectded failure: (%d): %s", rsp.statusCode, rsp.body)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rsp.body, &epList)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(epList) == 0 {
|
||||
t.Fatalf("Empty response body")
|
||||
}
|
||||
if epList[0].Name != "ep-TwentyTwo" || eid != epList[0].ID {
|
||||
t.Fatalf("Incongruent resource found: %v", epList[0])
|
||||
}
|
||||
|
||||
// Get endpoint by id
|
||||
req, err = http.NewRequest("GET", "/networks/"+nid+"/endpoints/"+eid, nil)
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Reference in a new issue