mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #13424 from mavenugo/vendorin
Vendoring in libnetwork 67438080724b17b641b411322822c00d0d3c3201
This commit is contained in:
commit
f83073d3eb
57 changed files with 3369 additions and 1093 deletions
|
@ -30,8 +30,8 @@ import (
|
|||
"github.com/docker/libcontainer/devices"
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
@ -495,7 +495,7 @@ func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork
|
|||
return networkSettings, nil
|
||||
}
|
||||
|
||||
if portMapping, ok := mapData.([]netutils.PortBinding); ok {
|
||||
if portMapping, ok := mapData.([]types.PortBinding); ok {
|
||||
networkSettings.Ports = nat.PortMap{}
|
||||
for _, pp := range portMapping {
|
||||
natPort := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
|
||||
|
@ -634,8 +634,8 @@ func (container *Container) buildCreateEndpointOptions() ([]libnetwork.EndpointO
|
|||
var (
|
||||
portSpecs = make(nat.PortSet)
|
||||
bindings = make(nat.PortMap)
|
||||
pbList []netutils.PortBinding
|
||||
exposeList []netutils.TransportPort
|
||||
pbList []types.PortBinding
|
||||
exposeList []types.TransportPort
|
||||
createOptions []libnetwork.EndpointOption
|
||||
)
|
||||
|
||||
|
@ -675,12 +675,12 @@ func (container *Container) buildCreateEndpointOptions() ([]libnetwork.EndpointO
|
|||
}
|
||||
nat.SortPortMap(ports, bindings)
|
||||
for _, port := range ports {
|
||||
expose := netutils.TransportPort{}
|
||||
expose.Proto = netutils.ParseProtocol(port.Proto())
|
||||
expose := types.TransportPort{}
|
||||
expose.Proto = types.ParseProtocol(port.Proto())
|
||||
expose.Port = uint16(port.Int())
|
||||
exposeList = append(exposeList, expose)
|
||||
|
||||
pb := netutils.PortBinding{Port: expose.Port, Proto: expose.Proto}
|
||||
pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
|
||||
binding := bindings[port]
|
||||
for i := 0; i < len(binding); i++ {
|
||||
pbCopy := pb.GetCopy()
|
||||
|
|
|
@ -55,7 +55,7 @@ clone hg code.google.com/p/go.net 84a4013f96e0
|
|||
clone hg code.google.com/p/gosqlite 74691fb6f837
|
||||
|
||||
#get libnetwork packages
|
||||
clone git github.com/docker/libnetwork b39597744b0978fe4aeb9f3a099ba42f7b6c4a1f
|
||||
clone git github.com/docker/libnetwork 67438080724b17b641b411322822c00d0d3c3201
|
||||
clone git github.com/vishvananda/netns 008d17ae001344769b031375bdb38a86219154c6
|
||||
clone git github.com/vishvananda/netlink 8eb64238879fed52fd51c5b30ad20b928fb4c36c
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ build: ${build_image}.created
|
|||
${docker} make build-local
|
||||
|
||||
build-local:
|
||||
$(shell which godep) go build ./...
|
||||
$(shell which godep) go build -tags experimental ./...
|
||||
|
||||
check: ${build_image}.created
|
||||
${docker} make check-local
|
||||
|
|
184
vendor/src/github.com/docker/libnetwork/api/api.go
vendored
184
vendor/src/github.com/docker/libnetwork/api/api.go
vendored
|
@ -5,8 +5,10 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
|
@ -14,13 +16,28 @@ 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 (
|
||||
urlNwName = "name"
|
||||
urlNwID = "id"
|
||||
// Resource name regex
|
||||
regex = "[a-zA-Z_0-9-]+"
|
||||
// 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"
|
||||
)
|
||||
|
||||
|
@ -59,42 +76,41 @@ func (h *httpHandler) handleRequest(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
func (h *httpHandler) initRouter() {
|
||||
m := map[string]map[string]processor{
|
||||
m := map[string][]struct {
|
||||
url string
|
||||
qrs []string
|
||||
fct processor
|
||||
}{
|
||||
"GET": {
|
||||
"/networks": procGetNetworks,
|
||||
"/networks/name/{" + urlNwName + ":.*}": procGetNetwork,
|
||||
"/networks/id/{" + urlNwID + ":.*}": procGetNetwork,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoints/": procGetEndpoints,
|
||||
"/networks/id/{" + urlNwID + ":.*}/endpoints/": procGetEndpoints,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoints/name/{" + urlEpName + ":.*}": procGetEndpoint,
|
||||
"/networks/id/{" + urlNwID + ":.*}/endpoints/name/{" + urlEpName + ":.*}": procGetEndpoint,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoints/id/{" + urlEpID + ":.*}": procGetEndpoint,
|
||||
"/networks/id/{" + urlNwID + ":.*}/endpoints/id/{" + urlEpID + ":.*}": procGetEndpoint,
|
||||
// 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", nil, procGetEndpoints},
|
||||
{"/networks/" + nwID + "/endpoints/" + epID, nil, procGetEndpoint},
|
||||
},
|
||||
"POST": {
|
||||
"/networks/name/{" + urlNwName + ":.*}": procCreateNetwork,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoint/name/{" + urlEpName + ":.*}": procCreateEndpoint,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoint/name/{" + urlEpName + ":.*}/container/{" + urlCnID + ":.*}": procJoinEndpoint,
|
||||
{"/networks", nil, procCreateNetwork},
|
||||
{"/networks/" + nwID + "/endpoints", nil, procCreateEndpoint},
|
||||
{"/networks/" + nwID + "/endpoints/" + epID + "/containers", nil, procJoinEndpoint},
|
||||
},
|
||||
"DELETE": {
|
||||
"/networks/name/{" + urlNwName + ":.*}": procDeleteNetwork,
|
||||
"/networks/id/{" + urlNwID + ":.*}": procDeleteNetwork,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoints/name/{" + urlEpName + ":.*}": procDeleteEndpoint,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoints/id/{" + urlEpID + ":.*}": procDeleteEndpoint,
|
||||
"/networks/id/{" + urlNwID + ":.*}/endpoints/name/{" + urlEpName + ":.*}": procDeleteEndpoint,
|
||||
"/networks/id/{" + urlNwID + ":.*}/endpoints/id/{" + urlEpID + ":.*}": procDeleteEndpoint,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoint/name/{" + urlEpName + ":.*}/container/{" + urlCnID + ":.*}": procLeaveEndpoint,
|
||||
"/networks/name/{" + urlNwName + ":.*}/endpoint/id/{" + urlEpID + ":.*}/container/{" + urlCnID + ":.*}": procLeaveEndpoint,
|
||||
"/networks/id/{" + urlNwID + ":.*}/endpoint/name/{" + urlEpName + ":.*}/container/{" + urlCnID + ":.*}": procLeaveEndpoint,
|
||||
"/networks/id/{" + urlNwID + ":.*}/endpoint/id/{" + urlEpID + ":.*}/container/{" + urlCnID + ":.*}": procLeaveEndpoint,
|
||||
{"/networks/" + nwID, nil, procDeleteNetwork},
|
||||
{"/networks/" + nwID + "/endpoints/" + epID, nil, procDeleteEndpoint},
|
||||
{"/networks/id/" + nwID + "/endpoints/" + epID + "/containers/" + cnID, nil, procLeaveEndpoint},
|
||||
},
|
||||
}
|
||||
|
||||
h.r = mux.NewRouter()
|
||||
for method, routes := range m {
|
||||
for route, fct := range routes {
|
||||
f := makeHandler(h.c, fct)
|
||||
h.r.Path(route).Methods(method).HandlerFunc(f)
|
||||
for _, route := range routes {
|
||||
r := h.r.Path("/{.*}" + route.url).Methods(method).HandlerFunc(makeHandler(h.c, route.fct))
|
||||
if route.qrs != nil {
|
||||
r.Queries(route.qrs...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,12 +224,7 @@ func procCreateNetwork(c libnetwork.NetworkController, vars map[string]string, b
|
|||
return "", &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
|
||||
}
|
||||
|
||||
name := vars[urlNwName]
|
||||
if name != create.Name {
|
||||
return "", &mismatchResponse
|
||||
}
|
||||
|
||||
nw, err := c.NewNetwork(create.NetworkType, name, nil)
|
||||
nw, err := c.NewNetwork(create.NetworkType, create.Name, nil)
|
||||
if err != nil {
|
||||
return "", convertNetworkError(err)
|
||||
}
|
||||
|
@ -232,10 +243,33 @@ 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
|
||||
for _, nw := range c.Networks() {
|
||||
nwr := buildNetworkResource(nw)
|
||||
list = append(list, nwr)
|
||||
|
||||
// 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))
|
||||
}
|
||||
}
|
||||
|
||||
return list, &successResponse
|
||||
}
|
||||
|
||||
|
@ -250,21 +284,12 @@ func procCreateEndpoint(c libnetwork.NetworkController, vars map[string]string,
|
|||
return "", &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
|
||||
}
|
||||
|
||||
epn := vars[urlEpName]
|
||||
if ec.Name != epn {
|
||||
return "", &mismatchResponse
|
||||
}
|
||||
|
||||
nwT, nwBy := detectNetworkTarget(vars)
|
||||
n, errRsp := findNetwork(c, nwT, nwBy)
|
||||
if !errRsp.isOK() {
|
||||
return "", errRsp
|
||||
}
|
||||
|
||||
if ec.NetworkID != n.ID() {
|
||||
return "", &mismatchResponse
|
||||
}
|
||||
|
||||
var setFctList []libnetwork.EndpointOption
|
||||
if ec.ExposedPorts != nil {
|
||||
setFctList = append(setFctList, libnetwork.CreateOptionExposedPorts(ec.ExposedPorts))
|
||||
|
@ -273,7 +298,7 @@ func procCreateEndpoint(c libnetwork.NetworkController, vars map[string]string,
|
|||
setFctList = append(setFctList, libnetwork.CreateOptionPortMapping(ec.PortMapping))
|
||||
}
|
||||
|
||||
ep, err := n.CreateEndpoint(epn, setFctList...)
|
||||
ep, err := n.CreateEndpoint(ec.Name, setFctList...)
|
||||
if err != nil {
|
||||
return "", convertNetworkError(err)
|
||||
}
|
||||
|
@ -294,17 +319,40 @@ func procGetEndpoint(c libnetwork.NetworkController, vars map[string]string, bod
|
|||
}
|
||||
|
||||
func procGetEndpoints(c libnetwork.NetworkController, vars map[string]string, body []byte) (interface{}, *responseStatus) {
|
||||
target, by := detectNetworkTarget(vars)
|
||||
// Look for query filters and validate
|
||||
name, queryByName := vars[urlEpName]
|
||||
shortID, queryByPid := vars[urlEpPID]
|
||||
if queryByName && queryByPid {
|
||||
return nil, &badQueryresponse
|
||||
}
|
||||
|
||||
nw, errRsp := findNetwork(c, target, by)
|
||||
nwT, nwBy := detectNetworkTarget(vars)
|
||||
nw, errRsp := findNetwork(c, nwT, nwBy)
|
||||
if !errRsp.isOK() {
|
||||
return nil, errRsp
|
||||
}
|
||||
|
||||
var list []*endpointResource
|
||||
for _, ep := range nw.Endpoints() {
|
||||
epr := buildEndpointResource(ep)
|
||||
list = append(list, epr)
|
||||
|
||||
// If query parameter is specified, return a filtered collection
|
||||
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)
|
||||
list = append(list, epr)
|
||||
}
|
||||
}
|
||||
|
||||
return list, &successResponse
|
||||
|
@ -336,11 +384,6 @@ func procJoinEndpoint(c libnetwork.NetworkController, vars map[string]string, bo
|
|||
return nil, &responseStatus{Status: "Invalid body: " + err.Error(), StatusCode: http.StatusBadRequest}
|
||||
}
|
||||
|
||||
cid := vars[urlCnID]
|
||||
if ej.ContainerID != cid {
|
||||
return "", &mismatchResponse
|
||||
}
|
||||
|
||||
nwT, nwBy := detectNetworkTarget(vars)
|
||||
epT, epBy := detectEndpointTarget(vars)
|
||||
|
||||
|
@ -434,7 +477,7 @@ func findNetwork(c libnetwork.NetworkController, s string, by int) (libnetwork.N
|
|||
panic(fmt.Sprintf("unexpected selector for network search: %d", by))
|
||||
}
|
||||
if err != nil {
|
||||
if err == libnetwork.ErrNoSuchNetwork {
|
||||
if _, ok := err.(libnetwork.ErrNoSuchNetwork); ok {
|
||||
return nil, &responseStatus{Status: "Resource not found: Network", StatusCode: http.StatusNotFound}
|
||||
}
|
||||
return nil, &responseStatus{Status: err.Error(), StatusCode: http.StatusBadRequest}
|
||||
|
@ -460,7 +503,7 @@ func findEndpoint(c libnetwork.NetworkController, ns, es string, nwBy, epBy int)
|
|||
panic(fmt.Sprintf("unexpected selector for endpoint search: %d", epBy))
|
||||
}
|
||||
if err != nil {
|
||||
if err == libnetwork.ErrNoSuchEndpoint {
|
||||
if _, ok := err.(libnetwork.ErrNoSuchEndpoint); ok {
|
||||
return nil, &responseStatus{Status: "Resource not found: Endpoint", StatusCode: http.StatusNotFound}
|
||||
}
|
||||
return nil, &responseStatus{Status: err.Error(), StatusCode: http.StatusBadRequest}
|
||||
|
@ -469,9 +512,26 @@ func findEndpoint(c libnetwork.NetworkController, ns, es string, nwBy, epBy int)
|
|||
}
|
||||
|
||||
func convertNetworkError(err error) *responseStatus {
|
||||
// No real libnetwork error => http error code conversion for now.
|
||||
// Will came in later when new interface for libnetwork error is vailable
|
||||
return &responseStatus{Status: err.Error(), StatusCode: http.StatusBadRequest}
|
||||
var code int
|
||||
switch err.(type) {
|
||||
case types.BadRequestError:
|
||||
code = http.StatusBadRequest
|
||||
case types.ForbiddenError:
|
||||
code = http.StatusForbidden
|
||||
case types.NotFoundError:
|
||||
code = http.StatusNotFound
|
||||
case types.TimeoutError:
|
||||
code = http.StatusRequestTimeout
|
||||
case types.NotImplementedError:
|
||||
code = http.StatusNotImplemented
|
||||
case types.NoServiceError:
|
||||
code = http.StatusServiceUnavailable
|
||||
case types.InternalError:
|
||||
code = http.StatusInternalServerError
|
||||
default:
|
||||
code = http.StatusInternalServerError
|
||||
}
|
||||
return &responseStatus{Status: err.Error(), StatusCode: code}
|
||||
}
|
||||
|
||||
func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -111,7 +112,7 @@ func TestJoinOptionParser(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestJson(t *testing.T) {
|
||||
nc := networkCreate{Name: "mynet", NetworkType: bridgeNetType}
|
||||
nc := networkCreate{NetworkType: bridgeNetType}
|
||||
b, err := json.Marshal(nc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -123,26 +124,10 @@ func TestJson(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if nc.Name != ncp.Name || nc.NetworkType != ncp.NetworkType {
|
||||
if nc.NetworkType != ncp.NetworkType {
|
||||
t.Fatalf("Incorrect networkCreate after json encoding/deconding: %v", ncp)
|
||||
}
|
||||
|
||||
ec := endpointCreate{Name: "mioEp", NetworkID: "0xabcde"}
|
||||
b, err = json.Marshal(ec)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var ecp endpointCreate
|
||||
err = json.Unmarshal(b, &ecp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ec.Name != ecp.Name || ec.NetworkID != ecp.NetworkID {
|
||||
t.Fatalf("Incorrect endpointCreate after json encoding/deconding: %v", ecp)
|
||||
}
|
||||
|
||||
jl := endpointJoin{ContainerID: "abcdef456789"}
|
||||
b, err = json.Marshal(jl)
|
||||
if err != nil {
|
||||
|
@ -156,7 +141,7 @@ func TestJson(t *testing.T) {
|
|||
}
|
||||
|
||||
if jl.ContainerID != jld.ContainerID {
|
||||
t.Fatalf("Incorrect endpointJoin after json encoding/deconding: %v", ecp)
|
||||
t.Fatalf("Incorrect endpointJoin after json encoding/deconding: %v", jld)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,68 +162,55 @@ func TestCreateDeleteNetwork(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
goodVars := map[string]string{urlNwName: "myNet"}
|
||||
_, errRsp := procCreateNetwork(c, goodVars, badBody)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
|
||||
incompleteBody, err := json.Marshal(networkCreate{Name: "myNet"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, errRsp = procCreateNetwork(c, goodVars, incompleteBody)
|
||||
vars := make(map[string]string)
|
||||
_, errRsp := procCreateNetwork(c, nil, badBody)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
if errRsp.StatusCode != http.StatusBadRequest {
|
||||
t.Fatalf("Expected StatusBadRequest status code, got: %v", errRsp.StatusCode)
|
||||
t.Fatalf("Expected StatusBadRequest status code, got: %v", errRsp)
|
||||
}
|
||||
|
||||
incompleteBody, err := json.Marshal(networkCreate{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, errRsp = procCreateNetwork(c, vars, incompleteBody)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
if errRsp.StatusCode != http.StatusBadRequest {
|
||||
t.Fatalf("Expected StatusBadRequest status code, got: %v", errRsp)
|
||||
}
|
||||
|
||||
ops := make(map[string]interface{})
|
||||
ops[netlabel.GenericData] = options.Generic{}
|
||||
nc := networkCreate{Name: "myNet", NetworkType: bridgeNetType, Options: ops}
|
||||
nc := networkCreate{Name: "network_1", NetworkType: bridgeNetType, Options: ops}
|
||||
goodBody, err := json.Marshal(nc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
badVars := map[string]string{urlNwName: ""}
|
||||
_, errRsp = procCreateNetwork(c, badVars, goodBody)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
if errRsp.StatusCode != http.StatusBadRequest {
|
||||
t.Fatalf("Expected StatusBadRequest status code, got: %v", errRsp.StatusCode)
|
||||
}
|
||||
|
||||
badVars[urlNwName] = "badNetworkName"
|
||||
_, errRsp = procCreateNetwork(c, badVars, goodBody)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
if errRsp.StatusCode != http.StatusBadRequest {
|
||||
t.Fatalf("Expected StatusBadRequest status code, got: %v", errRsp.StatusCode)
|
||||
}
|
||||
|
||||
_, errRsp = procCreateNetwork(c, goodVars, goodBody)
|
||||
_, errRsp = procCreateNetwork(c, vars, goodBody)
|
||||
if errRsp != &createdResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
}
|
||||
|
||||
_, errRsp = procDeleteNetwork(c, badVars, nil)
|
||||
vars[urlNwName] = ""
|
||||
_, errRsp = procDeleteNetwork(c, vars, nil)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
|
||||
badVars[urlNwName] = ""
|
||||
_, errRsp = procDeleteNetwork(c, badVars, nil)
|
||||
vars[urlNwName] = "abc"
|
||||
_, errRsp = procDeleteNetwork(c, vars, nil)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
|
||||
_, errRsp = procDeleteNetwork(c, goodVars, nil)
|
||||
vars[urlNwName] = "network_1"
|
||||
_, errRsp = procDeleteNetwork(c, vars, nil)
|
||||
if errRsp != &successResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
}
|
||||
|
@ -262,7 +234,7 @@ func TestGetNetworksAndEndpoints(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vars := map[string]string{urlNwName: "sh"}
|
||||
vars := make(map[string]string)
|
||||
inid, errRsp := procCreateNetwork(c, vars, body)
|
||||
if errRsp != &createdResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
|
@ -273,29 +245,29 @@ func TestGetNetworksAndEndpoints(t *testing.T) {
|
|||
}
|
||||
|
||||
ec1 := endpointCreate{
|
||||
Name: "ep1",
|
||||
NetworkID: string(nid),
|
||||
ExposedPorts: []netutils.TransportPort{
|
||||
netutils.TransportPort{Proto: netutils.TCP, Port: uint16(5000)},
|
||||
netutils.TransportPort{Proto: netutils.UDP, Port: uint16(400)},
|
||||
netutils.TransportPort{Proto: netutils.TCP, Port: uint16(600)},
|
||||
Name: "ep1",
|
||||
ExposedPorts: []types.TransportPort{
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(5000)},
|
||||
types.TransportPort{Proto: types.UDP, Port: uint16(400)},
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(600)},
|
||||
},
|
||||
PortMapping: []netutils.PortBinding{
|
||||
netutils.PortBinding{Proto: netutils.TCP, Port: uint16(230), HostPort: uint16(23000)},
|
||||
netutils.PortBinding{Proto: netutils.UDP, Port: uint16(200), HostPort: uint16(22000)},
|
||||
netutils.PortBinding{Proto: netutils.TCP, Port: uint16(120), HostPort: uint16(12000)},
|
||||
PortMapping: []types.PortBinding{
|
||||
types.PortBinding{Proto: types.TCP, Port: uint16(230), HostPort: uint16(23000)},
|
||||
types.PortBinding{Proto: types.UDP, Port: uint16(200), HostPort: uint16(22000)},
|
||||
types.PortBinding{Proto: types.TCP, Port: uint16(120), HostPort: uint16(12000)},
|
||||
},
|
||||
}
|
||||
b1, err := json.Marshal(ec1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ec2 := endpointCreate{Name: "ep2", NetworkID: nid}
|
||||
ec2 := endpointCreate{Name: "ep2"}
|
||||
b2, err := json.Marshal(ec2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vars[urlNwName] = "sh"
|
||||
vars[urlEpName] = "ep1"
|
||||
ieid1, errRsp := procCreateEndpoint(c, vars, b1)
|
||||
if errRsp != &createdResponse {
|
||||
|
@ -471,6 +443,7 @@ func TestGetNetworksAndEndpoints(t *testing.T) {
|
|||
if errRsp != &successResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
}
|
||||
delete(vars, urlEpName)
|
||||
iepList, errRsp = procGetEndpoints(c, vars, nil)
|
||||
if errRsp != &successResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
|
@ -509,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)()
|
||||
|
||||
|
@ -603,85 +613,46 @@ func TestCreateDeleteEndpoints(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vars := map[string]string{urlNwName: "firstNet"}
|
||||
vars := make(map[string]string)
|
||||
i, errRsp := procCreateNetwork(c, vars, body)
|
||||
if errRsp != &createdResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
}
|
||||
nid := i2s(i)
|
||||
|
||||
vbad, err := json.Marshal("bad endppint create data")
|
||||
vbad, err := json.Marshal("bad endppoint create data")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vars[urlEpName] = "ep1"
|
||||
vars[urlNwName] = "firstNet"
|
||||
_, errRsp = procCreateEndpoint(c, vars, vbad)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
|
||||
bad, err := json.Marshal(endpointCreate{Name: "ep1", NetworkID: "123456"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, errRsp = procCreateEndpoint(c, vars, bad)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
|
||||
soso, err := json.Marshal(endpointCreate{Name: "ep11", NetworkID: nid})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, errRsp = procCreateEndpoint(c, vars, soso)
|
||||
if errRsp != &mismatchResponse {
|
||||
t.Fatalf("Expected to fail with \"mismatchResponse\", but got: %v", errRsp)
|
||||
}
|
||||
|
||||
bla, err := json.Marshal(endpointCreate{Name: "", NetworkID: nid})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
vars[urlNwName] = "firstNet"
|
||||
vars[urlEpName] = ""
|
||||
_, errRsp = procCreateEndpoint(c, vars, bla)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded: %v", errRsp)
|
||||
}
|
||||
|
||||
b, err := json.Marshal(endpointCreate{Name: "firstEp", NetworkID: nid})
|
||||
b, err := json.Marshal(endpointCreate{Name: ""})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vars[urlNwName] = "secondNet"
|
||||
vars[urlEpName] = "firstEp"
|
||||
_, errRsp = procCreateEndpoint(c, vars, b)
|
||||
if errRsp == &createdResponse {
|
||||
t.Fatalf("Expected to fail but succeeded")
|
||||
}
|
||||
|
||||
vars[urlNwName] = "firstNet"
|
||||
vars[urlEpName] = "ep1"
|
||||
_, errRsp = procCreateEndpoint(c, vars, b)
|
||||
if errRsp != &mismatchResponse {
|
||||
t.Fatalf("Expected to fail with \"mismatchResponse\", but got: %v", errRsp)
|
||||
}
|
||||
|
||||
vars = make(map[string]string)
|
||||
_, errRsp = procCreateEndpoint(c, vars, b)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected failure but succeeded: %v", errRsp)
|
||||
}
|
||||
|
||||
vars[urlNwName] = "firstNet"
|
||||
_, errRsp = procCreateEndpoint(c, vars, b)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected failure but succeeded: %v", errRsp)
|
||||
b, err = json.Marshal(endpointCreate{Name: "firstEp"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
vars[urlEpName] = "firstEp"
|
||||
i, errRsp = procCreateEndpoint(c, vars, b)
|
||||
if errRsp != &createdResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
|
@ -713,8 +684,8 @@ func TestCreateDeleteEndpoints(t *testing.T) {
|
|||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
}
|
||||
|
||||
if ep0 != ep1 || ep0 != ep2 || ep0 != ep3 {
|
||||
t.Fatalf("Diffenrent queries returned different endpoints")
|
||||
if ep0.ID() != ep1.ID() || ep0.ID() != ep2.ID() || ep0.ID() != ep3.ID() {
|
||||
t.Fatalf("Diffenrent queries returned different endpoints: \nep0: %v\nep1: %v\nep2: %v\nep3: %v", ep0, ep1, ep2, ep3)
|
||||
}
|
||||
|
||||
vars = make(map[string]string)
|
||||
|
@ -766,18 +737,17 @@ func TestJoinLeave(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
vars := map[string]string{urlNwName: "network"}
|
||||
i, errRsp := procCreateNetwork(c, vars, nb)
|
||||
vars := make(map[string]string)
|
||||
_, errRsp := procCreateNetwork(c, vars, nb)
|
||||
if errRsp != &createdResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
}
|
||||
nid := i2s(i)
|
||||
|
||||
vars[urlEpName] = "epoint"
|
||||
eb, err := json.Marshal(endpointCreate{Name: "epoint", NetworkID: nid})
|
||||
eb, err := json.Marshal(endpointCreate{Name: "endpoint"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
vars[urlNwName] = "network"
|
||||
_, errRsp = procCreateEndpoint(c, vars, eb)
|
||||
if errRsp != &createdResponse {
|
||||
t.Fatalf("Unexepected failure: %v", errRsp)
|
||||
|
@ -792,6 +762,7 @@ func TestJoinLeave(t *testing.T) {
|
|||
t.Fatalf("Expected failure, got: %v", errRsp)
|
||||
}
|
||||
|
||||
vars[urlEpName] = "endpoint"
|
||||
bad, err := json.Marshal(endpointJoin{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -811,44 +782,30 @@ func TestJoinLeave(t *testing.T) {
|
|||
vars = make(map[string]string)
|
||||
vars[urlNwName] = ""
|
||||
vars[urlEpName] = ""
|
||||
vars[urlCnID] = cid
|
||||
_, errRsp = procJoinEndpoint(c, vars, jlb)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected failure, got: %v", errRsp)
|
||||
}
|
||||
|
||||
vars[urlNwName] = "network1"
|
||||
vars[urlEpName] = ""
|
||||
_, errRsp = procJoinEndpoint(c, vars, jlb)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected failure, got: %v", errRsp)
|
||||
}
|
||||
|
||||
vars[urlNwName] = "network"
|
||||
vars[urlEpName] = "endpoint"
|
||||
vars[urlEpName] = ""
|
||||
_, errRsp = procJoinEndpoint(c, vars, jlb)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected failure, got: %v", errRsp)
|
||||
}
|
||||
|
||||
vars[urlEpName] = "epoint"
|
||||
delete(vars, urlCnID)
|
||||
_, errRsp = procJoinEndpoint(c, vars, jlb)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected failure, got: %v", errRsp)
|
||||
}
|
||||
|
||||
vars[urlCnID] = "who?"
|
||||
_, errRsp = procJoinEndpoint(c, vars, jlb)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected failure, got: %v", errRsp)
|
||||
}
|
||||
|
||||
vars[urlCnID] = cid
|
||||
vars[urlEpName] = "endpoint"
|
||||
cdi, errRsp := procJoinEndpoint(c, vars, jlb)
|
||||
if errRsp != &successResponse {
|
||||
t.Fatalf("Unexpected failure, got: %v", errRsp)
|
||||
t.Fatalf("Expected failure, got: %v", errRsp)
|
||||
}
|
||||
|
||||
cd := i2c(cdi)
|
||||
if cd.SandboxKey == "" {
|
||||
t.Fatalf("Empty sandbox key")
|
||||
|
@ -897,6 +854,7 @@ func TestJoinLeave(t *testing.T) {
|
|||
}
|
||||
|
||||
delete(vars, urlCnID)
|
||||
vars[urlEpName] = "endpoint"
|
||||
_, errRsp = procLeaveEndpoint(c, vars, jlb)
|
||||
if errRsp == &successResponse {
|
||||
t.Fatalf("Expected failure, got: %v", errRsp)
|
||||
|
@ -1178,7 +1136,7 @@ func TestHttpHandlerUninit(t *testing.T) {
|
|||
}
|
||||
|
||||
rsp := newWriter()
|
||||
req, err := http.NewRequest("GET", "/networks", nil)
|
||||
req, err := http.NewRequest("GET", "/v1.19/networks", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1193,15 +1151,24 @@ func TestHttpHandlerUninit(t *testing.T) {
|
|||
|
||||
handleRequest(rsp, req)
|
||||
if rsp.statusCode != http.StatusOK {
|
||||
t.Fatalf("Unexpectded failure: (%d): %s", rsp.statusCode, rsp.body)
|
||||
t.Fatalf("Expected (%d). Got: (%d): %s", http.StatusOK, rsp.statusCode, rsp.body)
|
||||
}
|
||||
|
||||
n, err := c.NewNetwork(bridgeNetType, "onenet", nil)
|
||||
var list []*networkResource
|
||||
err = json.Unmarshal(rsp.body, &list)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(list) != 0 {
|
||||
t.Fatalf("Expected empty list. Got %v", list)
|
||||
}
|
||||
|
||||
n, err := c.NewNetwork(bridgeNetType, "didietro", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
nwr := buildNetworkResource(n)
|
||||
expected, err := json.Marshal([]networkResource{*nwr})
|
||||
expected, err := json.Marshal([]*networkResource{nwr})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1229,7 +1196,7 @@ func TestHttpHandlerBadBody(t *testing.T) {
|
|||
}
|
||||
handleRequest := NewHTTPHandler(c)
|
||||
|
||||
req, err := http.NewRequest("POST", "/networks/name/zero-network", &localReader{beBad: true})
|
||||
req, err := http.NewRequest("POST", "/v1.19/networks", &localReader{beBad: true})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1240,7 +1207,7 @@ func TestHttpHandlerBadBody(t *testing.T) {
|
|||
|
||||
body := []byte{}
|
||||
lr := newLocalReader(body)
|
||||
req, err = http.NewRequest("POST", "/networks/name/zero-network", lr)
|
||||
req, err = http.NewRequest("POST", "/v1.19/networks", lr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1250,7 +1217,7 @@ func TestHttpHandlerBadBody(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestHttpHandlerGood(t *testing.T) {
|
||||
func TestEndToEnd(t *testing.T) {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
|
||||
rsp := newWriter()
|
||||
|
@ -1261,14 +1228,14 @@ func TestHttpHandlerGood(t *testing.T) {
|
|||
}
|
||||
handleRequest := NewHTTPHandler(c)
|
||||
|
||||
nc := networkCreate{Name: "zero-network", NetworkType: bridgeNetType}
|
||||
// Create network
|
||||
nc := networkCreate{Name: "network-fiftyfive", NetworkType: bridgeNetType}
|
||||
body, err := json.Marshal(nc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
lr := newLocalReader(body)
|
||||
req, err := http.NewRequest("POST", "/networks/name/zero-network", lr)
|
||||
req, err := http.NewRequest("POST", "/v1.19/networks", lr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1280,13 +1247,102 @@ func TestHttpHandlerGood(t *testing.T) {
|
|||
t.Fatalf("Empty response body")
|
||||
}
|
||||
|
||||
var id string
|
||||
err = json.Unmarshal(rsp.body, &id)
|
||||
var nid string
|
||||
err = json.Unmarshal(rsp.body, &nid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
req, err = http.NewRequest("GET", "/networks/id/"+id, nil)
|
||||
// Query networks collection
|
||||
req, err = http.NewRequest("GET", "/v1.19/networks", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handleRequest(rsp, req)
|
||||
if rsp.statusCode != http.StatusOK {
|
||||
t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
|
||||
}
|
||||
|
||||
b0 := make([]byte, len(rsp.body))
|
||||
copy(b0, rsp.body)
|
||||
|
||||
req, err = http.NewRequest("GET", "/v1.19/networks?name=network-fiftyfive", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handleRequest(rsp, req)
|
||||
if rsp.statusCode != http.StatusOK {
|
||||
t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
|
||||
}
|
||||
|
||||
if !bytes.Equal(b0, rsp.body) {
|
||||
t.Fatalf("Expected same body from GET /networks and GET /networks?name=<nw> when only network <nw> exist.")
|
||||
}
|
||||
|
||||
// Query network by name
|
||||
req, err = http.NewRequest("GET", "/v1.19/networks?name=culo", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handleRequest(rsp, req)
|
||||
if rsp.statusCode != http.StatusOK {
|
||||
t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
|
||||
}
|
||||
|
||||
var list []*networkResource
|
||||
err = json.Unmarshal(rsp.body, &list)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(list) != 0 {
|
||||
t.Fatalf("Expected empty list. Got %v", list)
|
||||
}
|
||||
|
||||
req, err = http.NewRequest("GET", "/v1.19/networks?name=network-fiftyfive", 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])
|
||||
}
|
||||
|
||||
// Query network by partial id
|
||||
chars := []byte(nid)
|
||||
partial := string(chars[0 : len(chars)/2])
|
||||
req, err = http.NewRequest("GET", "/v1.19/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", "/v1.19/networks/"+nid, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -1300,7 +1356,211 @@ func TestHttpHandlerGood(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if nwr.Name != "zero-network" || id != nwr.ID {
|
||||
t.Fatalf("Incongruent resource found")
|
||||
if nwr.Name != "network-fiftyfive" || nid != nwr.ID {
|
||||
t.Fatalf("Incongruent resource found: %v", nwr)
|
||||
}
|
||||
|
||||
// Create endpoint
|
||||
eb, err := json.Marshal(endpointCreate{Name: "ep-TwentyTwo"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
lr = newLocalReader(eb)
|
||||
req, err = http.NewRequest("POST", "/v1.19/networks/"+nid+"/endpoints", lr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handleRequest(rsp, req)
|
||||
if rsp.statusCode != http.StatusCreated {
|
||||
t.Fatalf("Unexpectded status code. Expected (%d). Got (%d): %s.", http.StatusCreated, rsp.statusCode, string(rsp.body))
|
||||
}
|
||||
if len(rsp.body) == 0 {
|
||||
t.Fatalf("Empty response body")
|
||||
}
|
||||
|
||||
var eid string
|
||||
err = json.Unmarshal(rsp.body, &eid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Query endpoint(s)
|
||||
req, err = http.NewRequest("GET", "/v1.19/networks/"+nid+"/endpoints", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handleRequest(rsp, req)
|
||||
if rsp.statusCode != http.StatusOK {
|
||||
t.Fatalf("Expected StatusOK. Got (%d): %s", rsp.statusCode, rsp.body)
|
||||
}
|
||||
|
||||
req, err = http.NewRequest("GET", "/v1.19/networks/"+nid+"/endpoints?name=bla", 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)
|
||||
}
|
||||
var epList []*endpointResource
|
||||
err = json.Unmarshal(rsp.body, &epList)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(epList) != 0 {
|
||||
t.Fatalf("Expected empty list. Got %v", epList)
|
||||
}
|
||||
|
||||
// Query endpoint by name
|
||||
req, err = http.NewRequest("GET", "/v1.19/networks/"+nid+"/endpoints?name=ep-TwentyTwo", 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])
|
||||
}
|
||||
|
||||
// Query endpoint by partial id
|
||||
chars = []byte(eid)
|
||||
partial = string(chars[0 : len(chars)/2])
|
||||
req, err = http.NewRequest("GET", "/v1.19/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", "/v1.19/networks/"+nid+"/endpoints/"+eid, 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)
|
||||
}
|
||||
|
||||
var epr endpointResource
|
||||
err = json.Unmarshal(rsp.body, &epr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if epr.Name != "ep-TwentyTwo" || epr.ID != eid {
|
||||
t.Fatalf("Incongruent resource found: %v", epr)
|
||||
}
|
||||
}
|
||||
|
||||
type bre struct{}
|
||||
|
||||
func (b *bre) Error() string {
|
||||
return "I am a bad request error"
|
||||
}
|
||||
func (b *bre) BadRequest() {}
|
||||
|
||||
type nfe struct{}
|
||||
|
||||
func (n *nfe) Error() string {
|
||||
return "I am a not found error"
|
||||
}
|
||||
func (n *nfe) NotFound() {}
|
||||
|
||||
type forb struct{}
|
||||
|
||||
func (f *forb) Error() string {
|
||||
return "I am a bad request error"
|
||||
}
|
||||
func (f *forb) Forbidden() {}
|
||||
|
||||
type notimpl struct{}
|
||||
|
||||
func (nip *notimpl) Error() string {
|
||||
return "I am a not implemented error"
|
||||
}
|
||||
func (nip *notimpl) NotImplemented() {}
|
||||
|
||||
type inter struct{}
|
||||
|
||||
func (it *inter) Error() string {
|
||||
return "I am a internal error"
|
||||
}
|
||||
func (it *inter) Internal() {}
|
||||
|
||||
type tout struct{}
|
||||
|
||||
func (to *tout) Error() string {
|
||||
return "I am a timeout error"
|
||||
}
|
||||
func (to *tout) Timeout() {}
|
||||
|
||||
type noserv struct{}
|
||||
|
||||
func (nos *noserv) Error() string {
|
||||
return "I am a no service error"
|
||||
}
|
||||
func (nos *noserv) NoService() {}
|
||||
|
||||
type notclassified struct{}
|
||||
|
||||
func (noc *notclassified) Error() string {
|
||||
return "I am a non classified error"
|
||||
}
|
||||
|
||||
func TestErrorConversion(t *testing.T) {
|
||||
if convertNetworkError(new(bre)).StatusCode != http.StatusBadRequest {
|
||||
t.Fatalf("Failed to recognize BadRequest error")
|
||||
}
|
||||
|
||||
if convertNetworkError(new(nfe)).StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("Failed to recognize NotFound error")
|
||||
}
|
||||
|
||||
if convertNetworkError(new(forb)).StatusCode != http.StatusForbidden {
|
||||
t.Fatalf("Failed to recognize Forbidden error")
|
||||
}
|
||||
|
||||
if convertNetworkError(new(notimpl)).StatusCode != http.StatusNotImplemented {
|
||||
t.Fatalf("Failed to recognize NotImplemented error")
|
||||
}
|
||||
|
||||
if convertNetworkError(new(inter)).StatusCode != http.StatusInternalServerError {
|
||||
t.Fatalf("Failed to recognize Internal error")
|
||||
}
|
||||
|
||||
if convertNetworkError(new(tout)).StatusCode != http.StatusRequestTimeout {
|
||||
t.Fatalf("Failed to recognize Timeout error")
|
||||
}
|
||||
|
||||
if convertNetworkError(new(noserv)).StatusCode != http.StatusServiceUnavailable {
|
||||
t.Fatalf("Failed to recognize No Service error")
|
||||
}
|
||||
|
||||
if convertNetworkError(new(notclassified)).StatusCode != http.StatusInternalServerError {
|
||||
t.Fatalf("Failed to recognize not classified error as Internal error")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package api
|
||||
|
||||
import "github.com/docker/libnetwork/netutils"
|
||||
import "github.com/docker/libnetwork/types"
|
||||
|
||||
/***********
|
||||
Resources
|
||||
|
@ -35,9 +35,8 @@ type networkCreate struct {
|
|||
// endpointCreate represents the body of the "create endpoint" http request message
|
||||
type endpointCreate struct {
|
||||
Name string
|
||||
NetworkID string
|
||||
ExposedPorts []netutils.TransportPort
|
||||
PortMapping []netutils.PortBinding
|
||||
ExposedPorts []types.TransportPort
|
||||
PortMapping []types.PortBinding
|
||||
}
|
||||
|
||||
// endpointJoin represents the expected body of the "join endpoint" or "leave endpoint" http request messages
|
||||
|
|
|
@ -49,6 +49,12 @@ func (cli *NetworkCli) getMethod(args ...string) (func(string, ...string) error,
|
|||
// Cmd is borrowed from Docker UI and acts as the entry point for network UI commands.
|
||||
// network UI commands are designed to be invoked from multiple parent chains
|
||||
func (cli *NetworkCli) Cmd(chain string, args ...string) error {
|
||||
if len(args) > 2 {
|
||||
method, exists := cli.getMethod(args[:3]...)
|
||||
if exists {
|
||||
return method(chain+" "+args[0]+" "+args[1], args[3:]...)
|
||||
}
|
||||
}
|
||||
if len(args) > 1 {
|
||||
method, exists := cli.getMethod(args[:2]...)
|
||||
if exists {
|
||||
|
|
124
vendor/src/github.com/docker/libnetwork/client/client_experimental_test.go
vendored
Normal file
124
vendor/src/github.com/docker/libnetwork/client/client_experimental_test.go
vendored
Normal file
|
@ -0,0 +1,124 @@
|
|||
// +build experimental
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
_ "github.com/docker/libnetwork/netutils"
|
||||
)
|
||||
|
||||
func TestClientNetworkServiceInvalidCommand(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "service", "invalid")
|
||||
if err == nil {
|
||||
t.Fatalf("Passing invalid commands must fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientNetworkServiceCreate(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "service", "create", mockServiceName, mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientNetworkServiceRm(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "service", "rm", mockServiceName, mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientNetworkServiceLs(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "service", "ls", mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientNetworkServiceInfo(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "service", "info", mockServiceName, mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientNetworkServiceInfoById(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "service", "info", mockServiceID, mockNwID)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientNetworkServiceJoin(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "service", "join", mockContainerID, mockServiceName, mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientNetworkServiceLeave(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "service", "leave", mockContainerID, mockServiceName, mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Docker Flag processing in flag.go uses os.Exit() frequently, even for --help
|
||||
// TODO : Handle the --help test-case in the IT when CLI is available
|
||||
/*
|
||||
func TestClientNetworkServiceCreateHelp(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nil, 0, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "create", "--help")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Docker flag processing in flag.go uses os.Exit(1) for incorrect parameter case.
|
||||
// TODO : Handle the missing argument case in the IT when CLI is available
|
||||
/*
|
||||
func TestClientNetworkServiceCreateMissingArgument(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nil, 0, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "create")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -2,7 +2,11 @@ package client
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
_ "github.com/docker/libnetwork/netutils"
|
||||
|
@ -15,12 +19,82 @@ type nopCloser struct {
|
|||
|
||||
func (nopCloser) Close() error { return nil }
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
setupMockHTTPCallback()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
var callbackFunc func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error)
|
||||
var mockNwJSON, mockNwListJSON, mockServiceJSON, mockServiceListJSON []byte
|
||||
var mockNwName = "test"
|
||||
var mockNwID = "2a3456789"
|
||||
var mockServiceName = "testSrv"
|
||||
var mockServiceID = "2a3456789"
|
||||
var mockContainerID = "2a3456789"
|
||||
|
||||
func setupMockHTTPCallback() {
|
||||
var list []networkResource
|
||||
nw := networkResource{Name: mockNwName, ID: mockNwID}
|
||||
mockNwJSON, _ = json.Marshal(nw)
|
||||
list = append(list, nw)
|
||||
mockNwListJSON, _ = json.Marshal(list)
|
||||
|
||||
var srvList []endpointResource
|
||||
ep := endpointResource{Name: mockServiceName, ID: mockServiceID, Network: mockNwName}
|
||||
mockServiceJSON, _ = json.Marshal(ep)
|
||||
srvList = append(srvList, ep)
|
||||
mockServiceListJSON, _ = json.Marshal(srvList)
|
||||
|
||||
callbackFunc = func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
var rsp string
|
||||
switch method {
|
||||
case "GET":
|
||||
if strings.Contains(path, fmt.Sprintf("networks?name=%s", mockNwName)) {
|
||||
rsp = string(mockNwListJSON)
|
||||
} else if strings.Contains(path, "networks?name=") {
|
||||
rsp = "[]"
|
||||
} else if strings.Contains(path, fmt.Sprintf("networks?partial-id=%s", mockNwID)) {
|
||||
rsp = string(mockNwListJSON)
|
||||
} else if strings.Contains(path, "networks?partial-id=") {
|
||||
rsp = "[]"
|
||||
} else if strings.HasSuffix(path, "networks") {
|
||||
rsp = string(mockNwListJSON)
|
||||
} else if strings.HasSuffix(path, "networks/"+mockNwID) {
|
||||
rsp = string(mockNwJSON)
|
||||
} else if strings.Contains(path, fmt.Sprintf("endpoints?name=%s", mockServiceName)) {
|
||||
rsp = string(mockServiceListJSON)
|
||||
} else if strings.Contains(path, "endpoints?name=") {
|
||||
rsp = "[]"
|
||||
} else if strings.Contains(path, fmt.Sprintf("endpoints?partial-id=%s", mockServiceID)) {
|
||||
rsp = string(mockServiceListJSON)
|
||||
} else if strings.Contains(path, "endpoints?partial-id=") {
|
||||
rsp = "[]"
|
||||
} else if strings.HasSuffix(path, "endpoints") {
|
||||
rsp = string(mockServiceListJSON)
|
||||
} else if strings.HasSuffix(path, "endpoints/"+mockServiceID) {
|
||||
rsp = string(mockServiceJSON)
|
||||
}
|
||||
case "POST":
|
||||
var data []byte
|
||||
if strings.HasSuffix(path, "networks") {
|
||||
data, _ = json.Marshal(mockNwID)
|
||||
} else if strings.HasSuffix(path, "endpoints") {
|
||||
data, _ = json.Marshal(mockServiceID)
|
||||
} else if strings.HasSuffix(path, "containers") {
|
||||
data, _ = json.Marshal(mockContainerID)
|
||||
}
|
||||
rsp = string(data)
|
||||
case "PUT":
|
||||
case "DELETE":
|
||||
rsp = ""
|
||||
}
|
||||
return nopCloser{bytes.NewBufferString(rsp)}, 200, nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientDummyCommand(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nopCloser{bytes.NewBufferString("")}, 200, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "dummy")
|
||||
if err == nil {
|
||||
|
@ -30,10 +104,7 @@ func TestClientDummyCommand(t *testing.T) {
|
|||
|
||||
func TestClientNetworkInvalidCommand(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nopCloser{bytes.NewBufferString("")}, 200, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "invalid")
|
||||
if err == nil {
|
||||
|
@ -43,12 +114,9 @@ func TestClientNetworkInvalidCommand(t *testing.T) {
|
|||
|
||||
func TestClientNetworkCreate(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nopCloser{bytes.NewBufferString("")}, 200, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "create", "test")
|
||||
err := cli.Cmd("docker", "network", "create", mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
@ -56,17 +124,14 @@ func TestClientNetworkCreate(t *testing.T) {
|
|||
|
||||
func TestClientNetworkCreateWithDriver(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nopCloser{bytes.NewBufferString("")}, 200, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "create", "-f=dummy", "test")
|
||||
err := cli.Cmd("docker", "network", "create", "-f=dummy", mockNwName)
|
||||
if err == nil {
|
||||
t.Fatalf("Passing incorrect flags to the create command must fail")
|
||||
}
|
||||
|
||||
err = cli.Cmd("docker", "network", "create", "-d=dummy", "test")
|
||||
err = cli.Cmd("docker", "network", "create", "-d=dummy", mockNwName)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
@ -74,12 +139,9 @@ func TestClientNetworkCreateWithDriver(t *testing.T) {
|
|||
|
||||
func TestClientNetworkRm(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nopCloser{bytes.NewBufferString("")}, 200, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "rm", "test")
|
||||
err := cli.Cmd("docker", "network", "rm", mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
@ -87,47 +149,43 @@ func TestClientNetworkRm(t *testing.T) {
|
|||
|
||||
func TestClientNetworkLs(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
networks := "db,web,test"
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nopCloser{bytes.NewBufferString(networks)}, 200, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "ls")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
if out.String() != networks {
|
||||
t.Fatal("Network List command fail to return the intended list")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientNetworkInfo(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
info := "dummy info"
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nopCloser{bytes.NewBufferString(info)}, 200, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "info", "test")
|
||||
err := cli.Cmd("docker", "network", "info", mockNwName)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
if out.String() != info {
|
||||
t.Fatal("Network List command fail to return the intended list")
|
||||
}
|
||||
|
||||
func TestClientNetworkInfoById(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "info", mockNwID)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Docker Flag processing in flag.go uses os.Exit() frequently, even for --help
|
||||
// TODO : Handle the --help test-case in the IT when CLI is available
|
||||
/*
|
||||
func TestClientNetworkCreateHelp(t *testing.T) {
|
||||
func TestClientNetworkServiceCreateHelp(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nil, 0, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "create", "--help")
|
||||
if err != nil {
|
||||
|
@ -139,12 +197,12 @@ func TestClientNetworkCreateHelp(t *testing.T) {
|
|||
// Docker flag processing in flag.go uses os.Exit(1) for incorrect parameter case.
|
||||
// TODO : Handle the missing argument case in the IT when CLI is available
|
||||
/*
|
||||
func TestClientNetworkCreateMissingArgument(t *testing.T) {
|
||||
func TestClientNetworkServiceCreateMissingArgument(t *testing.T) {
|
||||
var out, errOut bytes.Buffer
|
||||
cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
|
||||
return nil, 0, nil
|
||||
}
|
||||
cli := NewNetworkCli(&out, &errOut, cFunc)
|
||||
cli := NewNetworkCli(&out, &errOut, callbackFunc)
|
||||
|
||||
err := cli.Cmd("docker", "network", "create")
|
||||
if err != nil {
|
||||
|
|
|
@ -2,10 +2,13 @@ package client
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"text/tabwriter"
|
||||
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -33,7 +36,7 @@ func (cli *NetworkCli) CmdNetwork(chain string, args ...string) error {
|
|||
err := cmd.ParseFlags(args, true)
|
||||
if err == nil {
|
||||
cmd.Usage()
|
||||
return fmt.Errorf("Invalid command : %v", args)
|
||||
return fmt.Errorf("invalid command : %v", args)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -53,31 +56,33 @@ func (cli *NetworkCli) CmdNetworkCreate(chain string, args ...string) error {
|
|||
|
||||
nc := networkCreate{Name: cmd.Arg(0), NetworkType: *flDriver}
|
||||
|
||||
obj, _, err := readBody(cli.call("POST", "/networks/name/"+cmd.Arg(0), nc, nil))
|
||||
obj, _, err := readBody(cli.call("POST", "/networks", nc, nil))
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.err, "%s", err.Error())
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
|
||||
var replyID string
|
||||
err = json.Unmarshal(obj, &replyID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(cli.out, "%s\n", replyID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdNetworkRm handles Network Delete UI
|
||||
func (cli *NetworkCli) CmdNetworkRm(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "rm", "NETWORK-NAME", "Deletes a network", false)
|
||||
cmd := cli.Subcmd(chain, "rm", "NETWORK", "Deletes a network", false)
|
||||
cmd.Require(flag.Min, 1)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
obj, _, err := readBody(cli.call("DELETE", "/networks/name/"+cmd.Arg(0), nil, nil))
|
||||
id, err := lookupNetworkID(cli, cmd.Arg(0))
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.err, "%s", err.Error())
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
|
||||
_, _, err = readBody(cli.call("DELETE", "/networks/"+id, nil, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -86,45 +91,149 @@ func (cli *NetworkCli) CmdNetworkRm(chain string, args ...string) error {
|
|||
// CmdNetworkLs handles Network List UI
|
||||
func (cli *NetworkCli) CmdNetworkLs(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "ls", "", "Lists all the networks created by the user", false)
|
||||
quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
|
||||
noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Do not truncate the output")
|
||||
nLatest := cmd.Bool([]string{"l", "-latest"}, false, "Show the latest network created")
|
||||
last := cmd.Int([]string{"n"}, -1, "Show n last created networks")
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
obj, _, err := readBody(cli.call("GET", "/networks", nil, nil))
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.err, "%s", err.Error())
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
|
||||
if *last == -1 && *nLatest {
|
||||
*last = 1
|
||||
}
|
||||
|
||||
var networkResources []networkResource
|
||||
err = json.Unmarshal(obj, &networkResources)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
|
||||
|
||||
// unless quiet (-q) is specified, print field titles
|
||||
if !*quiet {
|
||||
fmt.Fprintln(wr, "NETWORK ID\tNAME\tTYPE")
|
||||
}
|
||||
|
||||
for _, networkResource := range networkResources {
|
||||
ID := networkResource.ID
|
||||
netName := networkResource.Name
|
||||
if !*noTrunc {
|
||||
ID = stringid.TruncateID(ID)
|
||||
}
|
||||
if *quiet {
|
||||
fmt.Fprintln(wr, ID)
|
||||
continue
|
||||
}
|
||||
netType := networkResource.Type
|
||||
fmt.Fprintf(wr, "%s\t%s\t%s\t",
|
||||
ID,
|
||||
netName,
|
||||
netType)
|
||||
fmt.Fprint(wr, "\n")
|
||||
}
|
||||
wr.Flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdNetworkInfo handles Network Info UI
|
||||
func (cli *NetworkCli) CmdNetworkInfo(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "info", "NETWORK-NAME", "Displays detailed information on a network", false)
|
||||
cmd := cli.Subcmd(chain, "info", "NETWORK", "Displays detailed information on a network", false)
|
||||
cmd.Require(flag.Min, 1)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
obj, _, err := readBody(cli.call("GET", "/networks/name/"+cmd.Arg(0), nil, nil))
|
||||
|
||||
id, err := lookupNetworkID(cli, cmd.Arg(0))
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.err, "%s", err.Error())
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
|
||||
|
||||
obj, _, err := readBody(cli.call("GET", "/networks/"+id, nil, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
networkResource := &networkResource{}
|
||||
if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(cli.out, "Network Id: %s\n", networkResource.ID)
|
||||
fmt.Fprintf(cli.out, "Name: %s\n", networkResource.Name)
|
||||
fmt.Fprintf(cli.out, "Type: %s\n", networkResource.Type)
|
||||
if networkResource.Endpoints != nil {
|
||||
for _, endpointResource := range networkResource.Endpoints {
|
||||
fmt.Fprintf(cli.out, " Service Id: %s\n", endpointResource.ID)
|
||||
fmt.Fprintf(cli.out, "\tName: %s\n", endpointResource.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Helper function to predict if a string is a name or id or partial-id
|
||||
// This provides a best-effort mechanism to identify a id with the help of GET Filter APIs
|
||||
// Being a UI, its most likely that name will be used by the user, which is used to lookup
|
||||
// the corresponding ID. If ID is not found, this function will assume that the passed string
|
||||
// is an ID by itself.
|
||||
|
||||
func lookupNetworkID(cli *NetworkCli, nameID string) (string, error) {
|
||||
obj, statusCode, err := readBody(cli.call("GET", "/networks?name="+nameID, nil, nil))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if statusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("name query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj))
|
||||
}
|
||||
|
||||
var list []*networkResource
|
||||
err = json.Unmarshal(obj, &list)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(list) > 0 {
|
||||
// name query filter will always return a single-element collection
|
||||
return list[0].ID, nil
|
||||
}
|
||||
|
||||
// Check for Partial-id
|
||||
obj, statusCode, err = readBody(cli.call("GET", "/networks?partial-id="+nameID, nil, nil))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if statusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("partial-id match query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj))
|
||||
}
|
||||
|
||||
err = json.Unmarshal(obj, &list)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return "", fmt.Errorf("resource not found %s", nameID)
|
||||
}
|
||||
if len(list) > 1 {
|
||||
return "", fmt.Errorf("multiple Networks matching the partial identifier (%s). Please use full identifier", nameID)
|
||||
}
|
||||
return list[0].ID, nil
|
||||
}
|
||||
|
||||
func networkUsage(chain string) string {
|
||||
help := "Commands:\n"
|
||||
|
||||
for _, cmd := range networkCommands {
|
||||
help += fmt.Sprintf(" %-10.10s%s\n", cmd.name, cmd.description)
|
||||
help += fmt.Sprintf(" %-25.25s%s\n", cmd.name, cmd.description)
|
||||
}
|
||||
|
||||
for _, cmd := range serviceCommands {
|
||||
help += fmt.Sprintf(" %-25.25s%s\n", "service "+cmd.name, cmd.description)
|
||||
}
|
||||
|
||||
help += fmt.Sprintf("\nRun '%s network COMMAND --help' for more information on a command.", chain)
|
||||
|
|
7
vendor/src/github.com/docker/libnetwork/client/service.go
vendored
Normal file
7
vendor/src/github.com/docker/libnetwork/client/service.go
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
// +build !experimental
|
||||
|
||||
package client
|
||||
|
||||
var (
|
||||
serviceCommands = []command{}
|
||||
)
|
317
vendor/src/github.com/docker/libnetwork/client/service_experimental.go
vendored
Normal file
317
vendor/src/github.com/docker/libnetwork/client/service_experimental.go
vendored
Normal file
|
@ -0,0 +1,317 @@
|
|||
// +build experimental
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"text/tabwriter"
|
||||
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
)
|
||||
|
||||
var (
|
||||
serviceCommands = []command{
|
||||
{"create", "Create a service endpoint"},
|
||||
{"rm", "Remove a service endpoint"},
|
||||
{"join", "Join a container to a service endpoint"},
|
||||
{"leave", "Leave a container from a service endpoint"},
|
||||
{"ls", "Lists all service endpoints on a network"},
|
||||
{"info", "Display information of a service endpoint"},
|
||||
}
|
||||
)
|
||||
|
||||
func lookupServiceID(cli *NetworkCli, networkID string, nameID string) (string, error) {
|
||||
obj, statusCode, err := readBody(cli.call("GET", fmt.Sprintf("/networks/%s/endpoints?name=%s", networkID, nameID), nil, nil))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if statusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("name query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj))
|
||||
}
|
||||
|
||||
var list []*networkResource
|
||||
err = json.Unmarshal(obj, &list)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(list) > 0 {
|
||||
// name query filter will always return a single-element collection
|
||||
return list[0].ID, nil
|
||||
}
|
||||
|
||||
// Check for Partial-id
|
||||
obj, statusCode, err = readBody(cli.call("GET", fmt.Sprintf("/networks/%s/endpoints?partial-id=%s", networkID, nameID), nil, nil))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if statusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("partial-id match query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj))
|
||||
}
|
||||
|
||||
err = json.Unmarshal(obj, &list)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return "", fmt.Errorf("resource not found %s", nameID)
|
||||
}
|
||||
if len(list) > 1 {
|
||||
return "", fmt.Errorf("multiple services matching the partial identifier (%s). Please use full identifier", nameID)
|
||||
}
|
||||
return list[0].ID, nil
|
||||
}
|
||||
|
||||
func lookupContainerID(cli *NetworkCli, nameID string) (string, error) {
|
||||
// TODO : containerID to sandbox-key ?
|
||||
return nameID, nil
|
||||
}
|
||||
|
||||
// CmdNetworkService handles the network service UI
|
||||
func (cli *NetworkCli) CmdNetworkService(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "service", "COMMAND [OPTIONS] [arg...]", serviceUsage(chain), false)
|
||||
cmd.Require(flag.Min, 1)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err == nil {
|
||||
cmd.Usage()
|
||||
return fmt.Errorf("Invalid command : %v", args)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CmdNetworkServiceCreate handles service create UI
|
||||
func (cli *NetworkCli) CmdNetworkServiceCreate(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "create", "SERVICE NETWORK", "Creates a new service on a network", false)
|
||||
cmd.Require(flag.Min, 2)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
networkID, err := lookupNetworkID(cli, cmd.Arg(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ec := endpointCreate{Name: cmd.Arg(0), NetworkID: networkID}
|
||||
|
||||
obj, _, err := readBody(cli.call("POST", "/networks/"+networkID+"/endpoints", ec, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var replyID string
|
||||
err = json.Unmarshal(obj, &replyID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(cli.out, "%s\n", replyID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdNetworkServiceRm handles service delete UI
|
||||
func (cli *NetworkCli) CmdNetworkServiceRm(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "rm", "SERVICE NETWORK", "Deletes a service", false)
|
||||
cmd.Require(flag.Min, 2)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
networkID, err := lookupNetworkID(cli, cmd.Arg(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = readBody(cli.call("DELETE", "/networks/"+networkID+"/endpoints/"+serviceID, nil, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdNetworkServiceLs handles service list UI
|
||||
func (cli *NetworkCli) CmdNetworkServiceLs(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "ls", "NETWORK", "Lists all the services on a network", false)
|
||||
quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
|
||||
noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Do not truncate the output")
|
||||
nLatest := cmd.Bool([]string{"l", "-latest"}, false, "Show the latest network created")
|
||||
last := cmd.Int([]string{"n"}, -1, "Show n last created networks")
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Require(flag.Min, 1)
|
||||
|
||||
networkID, err := lookupNetworkID(cli, cmd.Arg(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obj, _, err := readBody(cli.call("GET", "/networks/"+networkID+"/endpoints", nil, nil))
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.err, "%s", err.Error())
|
||||
return err
|
||||
}
|
||||
if *last == -1 && *nLatest {
|
||||
*last = 1
|
||||
}
|
||||
|
||||
var endpointResources []endpointResource
|
||||
err = json.Unmarshal(obj, &endpointResources)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
|
||||
// unless quiet (-q) is specified, print field titles
|
||||
if !*quiet {
|
||||
fmt.Fprintln(wr, "NETWORK SERVICE ID\tNAME\tNETWORK")
|
||||
}
|
||||
|
||||
for _, networkResource := range endpointResources {
|
||||
ID := networkResource.ID
|
||||
netName := networkResource.Name
|
||||
if !*noTrunc {
|
||||
ID = stringid.TruncateID(ID)
|
||||
}
|
||||
if *quiet {
|
||||
fmt.Fprintln(wr, ID)
|
||||
continue
|
||||
}
|
||||
network := networkResource.Network
|
||||
fmt.Fprintf(wr, "%s\t%s\t%s",
|
||||
ID,
|
||||
netName,
|
||||
network)
|
||||
fmt.Fprint(wr, "\n")
|
||||
}
|
||||
wr.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdNetworkServiceInfo handles service info UI
|
||||
func (cli *NetworkCli) CmdNetworkServiceInfo(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "info", "SERVICE NETWORK", "Displays detailed information on a service", false)
|
||||
cmd.Require(flag.Min, 2)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
networkID, err := lookupNetworkID(cli, cmd.Arg(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obj, _, err := readBody(cli.call("GET", "/networks/"+networkID+"/endpoints/"+serviceID, nil, nil))
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.err, "%s", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
endpointResource := &endpointResource{}
|
||||
if err := json.NewDecoder(bytes.NewReader(obj)).Decode(endpointResource); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(cli.out, "Service Id: %s\n", endpointResource.ID)
|
||||
fmt.Fprintf(cli.out, "\tName: %s\n", endpointResource.Name)
|
||||
fmt.Fprintf(cli.out, "\tNetwork: %s\n", endpointResource.Network)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdNetworkServiceJoin handles service join UI
|
||||
func (cli *NetworkCli) CmdNetworkServiceJoin(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "join", "CONTAINER SERVICE NETWORK", "Sets a container as a service backend", false)
|
||||
cmd.Require(flag.Min, 3)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
containerID, err := lookupContainerID(cli, cmd.Arg(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
networkID, err := lookupNetworkID(cli, cmd.Arg(2))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nc := endpointJoin{ContainerID: containerID}
|
||||
|
||||
_, _, err = readBody(cli.call("POST", "/networks/"+networkID+"/endpoints/"+serviceID+"/containers", nc, nil))
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.err, "%s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdNetworkServiceLeave handles service leave UI
|
||||
func (cli *NetworkCli) CmdNetworkServiceLeave(chain string, args ...string) error {
|
||||
cmd := cli.Subcmd(chain, "leave", "CONTAINER SERVICE NETWORK", "Removes a container from service backend", false)
|
||||
cmd.Require(flag.Min, 3)
|
||||
err := cmd.ParseFlags(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
containerID, err := lookupContainerID(cli, cmd.Arg(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
networkID, err := lookupNetworkID(cli, cmd.Arg(2))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = readBody(cli.call("DELETE", "/networks/"+networkID+"/endpoints/"+serviceID+"/containers/"+containerID, nil, nil))
|
||||
if err != nil {
|
||||
fmt.Fprintf(cli.err, "%s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func serviceUsage(chain string) string {
|
||||
help := "Commands:\n"
|
||||
|
||||
for _, cmd := range serviceCommands {
|
||||
help += fmt.Sprintf(" %-10.10s%s\n", cmd, cmd.description)
|
||||
}
|
||||
|
||||
help += fmt.Sprintf("\nRun '%s service COMMAND --help' for more information on a command.", chain)
|
||||
return help
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package client
|
||||
|
||||
import "github.com/docker/libnetwork/sandbox"
|
||||
import "github.com/docker/libnetwork/types"
|
||||
|
||||
/***********
|
||||
Resources
|
||||
|
@ -19,7 +19,6 @@ type endpointResource struct {
|
|||
Name string
|
||||
ID string
|
||||
Network string
|
||||
Info sandbox.Info
|
||||
}
|
||||
|
||||
/***********
|
||||
|
@ -32,3 +31,38 @@ type networkCreate struct {
|
|||
NetworkType string
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
// endpointCreate represents the body of the "create endpoint" http request message
|
||||
type endpointCreate struct {
|
||||
Name string
|
||||
NetworkID string
|
||||
ExposedPorts []types.TransportPort
|
||||
PortMapping []types.PortBinding
|
||||
}
|
||||
|
||||
// endpointJoin represents the expected body of the "join endpoint" or "leave endpoint" http request messages
|
||||
type endpointJoin struct {
|
||||
ContainerID string
|
||||
HostName string
|
||||
DomainName string
|
||||
HostsPath string
|
||||
ResolvConfPath string
|
||||
DNS []string
|
||||
ExtraHosts []endpointExtraHost
|
||||
ParentUpdates []endpointParentUpdate
|
||||
UseDefaultSandbox bool
|
||||
}
|
||||
|
||||
// EndpointExtraHost represents the extra host object
|
||||
type endpointExtraHost struct {
|
||||
Name string
|
||||
Address string
|
||||
}
|
||||
|
||||
// EndpointParentUpdate is the object carrying the information about the
|
||||
// endpoint parent that needs to be updated
|
||||
type endpointParentUpdate struct {
|
||||
EndpointID string
|
||||
Name string
|
||||
Address string
|
||||
}
|
||||
|
|
|
@ -113,10 +113,8 @@ func (d *dnetConnection) dnetDaemon() error {
|
|||
}
|
||||
httpHandler := api.NewHTTPHandler(controller)
|
||||
r := mux.NewRouter().StrictSlash(false)
|
||||
post := r.PathPrefix("/networks").Subrouter()
|
||||
post.Methods("GET").HandlerFunc(httpHandler)
|
||||
post.Methods("PUT", "POST").HandlerFunc(httpHandler)
|
||||
post.Methods("DELETE").HandlerFunc(httpHandler)
|
||||
post := r.PathPrefix("/{.*}/networks").Subrouter()
|
||||
post.Methods("GET", "PUT", "POST", "DELETE").HandlerFunc(httpHandler)
|
||||
return http.ListenAndServe(d.addr, r)
|
||||
}
|
||||
|
||||
|
@ -143,7 +141,7 @@ func (d *dnetConnection) httpCall(method, path string, data interface{}, headers
|
|||
return nil, -1, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("%s", path), in)
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("/dnet%s", path), in)
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
|
@ -160,7 +158,7 @@ func (d *dnetConnection) httpCall(method, path string, data interface{}, headers
|
|||
statusCode = resp.StatusCode
|
||||
}
|
||||
if err != nil {
|
||||
return nil, statusCode, fmt.Errorf("An error occurred trying to connect: %v", err)
|
||||
return nil, statusCode, fmt.Errorf("error when trying to connect: %v", err)
|
||||
}
|
||||
|
||||
if statusCode < 200 || statusCode >= 400 {
|
||||
|
@ -168,7 +166,7 @@ func (d *dnetConnection) httpCall(method, path string, data interface{}, headers
|
|||
if err != nil {
|
||||
return nil, statusCode, err
|
||||
}
|
||||
return nil, statusCode, fmt.Errorf("Error response from daemon: %s", bytes.TrimSpace(body))
|
||||
return nil, statusCode, fmt.Errorf("error : %s", bytes.TrimSpace(body))
|
||||
}
|
||||
|
||||
return resp.Body, statusCode, nil
|
||||
|
|
|
@ -16,7 +16,7 @@ type byName []command
|
|||
|
||||
var (
|
||||
flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
|
||||
flHost = flag.String([]string{"H", "-Host"}, "", "Daemon socket to connect to")
|
||||
flHost = flag.String([]string{"H", "-host"}, "", "Daemon socket to connect to")
|
||||
flLogLevel = flag.String([]string{"l", "-log-level"}, "info", "Set the logging level")
|
||||
flDebug = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode")
|
||||
flHelp = flag.Bool([]string{"h", "-help"}, false, "Print usage")
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -58,7 +58,7 @@ func main() {
|
|||
epInfo, err := ep.DriverInfo()
|
||||
mapData, ok := epInfo[netlabel.PortMap]
|
||||
if ok {
|
||||
portMapping, ok := mapData.([]netutils.PortBinding)
|
||||
portMapping, ok := mapData.([]types.PortBinding)
|
||||
if ok {
|
||||
fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping)
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ func (c *controller) RegisterDriver(networkType string, driver driverapi.Driver)
|
|||
// are network specific and modeled in a generic way.
|
||||
func (c *controller) NewNetwork(networkType, name string, options ...NetworkOption) (Network, error) {
|
||||
if name == "" {
|
||||
return nil, ErrInvalidName
|
||||
return nil, ErrInvalidName(name)
|
||||
}
|
||||
// Check if a driver for the specified network type is available
|
||||
c.Lock()
|
||||
|
@ -203,7 +203,7 @@ func (c *controller) WalkNetworks(walker NetworkWalker) {
|
|||
|
||||
func (c *controller) NetworkByName(name string) (Network, error) {
|
||||
if name == "" {
|
||||
return nil, ErrInvalidName
|
||||
return nil, ErrInvalidName(name)
|
||||
}
|
||||
var n Network
|
||||
|
||||
|
@ -218,7 +218,7 @@ func (c *controller) NetworkByName(name string) (Network, error) {
|
|||
c.WalkNetworks(s)
|
||||
|
||||
if n == nil {
|
||||
return nil, ErrNoSuchNetwork
|
||||
return nil, ErrNoSuchNetwork(name)
|
||||
}
|
||||
|
||||
return n, nil
|
||||
|
@ -226,14 +226,14 @@ func (c *controller) NetworkByName(name string) (Network, error) {
|
|||
|
||||
func (c *controller) NetworkByID(id string) (Network, error) {
|
||||
if id == "" {
|
||||
return nil, ErrInvalidID
|
||||
return nil, ErrInvalidID(id)
|
||||
}
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
if n, ok := c.networks[types.UUID(id)]; ok {
|
||||
return n, nil
|
||||
}
|
||||
return nil, ErrNoSuchNetwork
|
||||
return nil, ErrNoSuchNetwork(id)
|
||||
}
|
||||
|
||||
func (c *controller) sandboxAdd(key string, create bool) (sandbox.Sandbox, error) {
|
||||
|
@ -286,13 +286,16 @@ func (c *controller) loadDriver(networkType string) (driverapi.Driver, error) {
|
|||
// As per the design, this Get call will result in remote driver discovery if there is a corresponding plugin available.
|
||||
_, err := plugins.Get(networkType, driverapi.NetworkPluginEndpointType)
|
||||
if err != nil {
|
||||
if err == plugins.ErrNotFound {
|
||||
return nil, types.NotFoundErrorf(err.Error())
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
d, ok := c.drivers[networkType]
|
||||
if !ok {
|
||||
return nil, ErrInvalidNetworkDriver
|
||||
return nil, ErrInvalidNetworkDriver(networkType)
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ This document describes how libnetwork has been designed in order to acheive thi
|
|||
Requirements for individual releases can be found on the [Project Page](https://github.com/docker/libnetwork/wiki)
|
||||
|
||||
Many of the design decisions are inspired by the learnings from the Docker networking design as of Docker v1.6.
|
||||
Please refer to this [Docker v1.6 Design](https://github.com/docker/libnetwork/blob/docs/legacy.md) document for more information on networking design as of Docker v1.6.
|
||||
Please refer to this [Docker v1.6 Design](legacy.md) document for more information on networking design as of Docker v1.6.
|
||||
|
||||
## Goal
|
||||
|
||||
|
|
|
@ -1,24 +1,11 @@
|
|||
package driverapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrEndpointExists is returned if more than one endpoint is added to the network
|
||||
ErrEndpointExists = errors.New("Endpoint already exists (Only one endpoint allowed)")
|
||||
// ErrNoNetwork is returned if no network with the specified id exists
|
||||
ErrNoNetwork = errors.New("No network exists")
|
||||
// ErrNoEndpoint is returned if no endpoint with the specified id exists
|
||||
ErrNoEndpoint = errors.New("No endpoint exists")
|
||||
// ErrNotImplemented is returned when a Driver has not implemented an API yet
|
||||
ErrNotImplemented = errors.New("The API is not implemented yet")
|
||||
)
|
||||
|
||||
// NetworkPluginEndpointType represents the Endpoint Type used by Plugin system
|
||||
const NetworkPluginEndpointType = "NetworkDriver"
|
||||
|
||||
|
@ -96,8 +83,8 @@ type InterfaceInfo interface {
|
|||
// InterfaceNameInfo provides a go interface for the drivers to assign names
|
||||
// to interfaces.
|
||||
type InterfaceNameInfo interface {
|
||||
// SetNames method assigns the srcName and dstName for the interface.
|
||||
SetNames(srcName, dstName string) error
|
||||
// SetNames method assigns the srcName and dstPrefix for the interface.
|
||||
SetNames(srcName, dstPrefix string) error
|
||||
|
||||
// ID returns the numerical id that was assigned to the interface by the driver
|
||||
// CreateEndpoint.
|
||||
|
@ -124,14 +111,6 @@ type JoinInfo interface {
|
|||
SetResolvConfPath(string) error
|
||||
}
|
||||
|
||||
// ErrActiveRegistration represents an error when a driver is registered to a networkType that is previously registered
|
||||
type ErrActiveRegistration string
|
||||
|
||||
// Error interface for ErrActiveRegistration
|
||||
func (ar ErrActiveRegistration) Error() string {
|
||||
return fmt.Sprintf("Driver already registered for type %q", string(ar))
|
||||
}
|
||||
|
||||
// DriverCallback provides a Callback interface for Drivers into LibNetwork
|
||||
type DriverCallback interface {
|
||||
// RegisterDriver provides a way for Remote drivers to dynamically register new NetworkType and associate with a driver instance
|
||||
|
|
56
vendor/src/github.com/docker/libnetwork/driverapi/errors.go
vendored
Normal file
56
vendor/src/github.com/docker/libnetwork/driverapi/errors.go
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
package driverapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ErrNoNetwork is returned if no network with the specified id exists
|
||||
type ErrNoNetwork string
|
||||
|
||||
func (enn ErrNoNetwork) Error() string {
|
||||
return fmt.Sprintf("No network (%s) exists", string(enn))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (enn ErrNoNetwork) NotFound() {}
|
||||
|
||||
// ErrEndpointExists is returned if more than one endpoint is added to the network
|
||||
type ErrEndpointExists string
|
||||
|
||||
func (ee ErrEndpointExists) Error() string {
|
||||
return fmt.Sprintf("Endpoint (%s) already exists (Only one endpoint allowed)", string(ee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ee ErrEndpointExists) Forbidden() {}
|
||||
|
||||
// ErrNotImplemented is returned when a Driver has not implemented an API yet
|
||||
type ErrNotImplemented struct{}
|
||||
|
||||
func (eni *ErrNotImplemented) Error() string {
|
||||
return "The API is not implemented yet"
|
||||
}
|
||||
|
||||
// NotImplemented denotes the type of this error
|
||||
func (eni *ErrNotImplemented) NotImplemented() {}
|
||||
|
||||
// ErrNoEndpoint is returned if no endpoint with the specified id exists
|
||||
type ErrNoEndpoint string
|
||||
|
||||
func (ene ErrNoEndpoint) Error() string {
|
||||
return fmt.Sprintf("No endpoint (%s) exists", string(ene))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (ene ErrNoEndpoint) NotFound() {}
|
||||
|
||||
// ErrActiveRegistration represents an error when a driver is registered to a networkType that is previously registered
|
||||
type ErrActiveRegistration string
|
||||
|
||||
// Error interface for ErrActiveRegistration
|
||||
func (ar ErrActiveRegistration) Error() string {
|
||||
return fmt.Sprintf("Driver already registered for type %q", string(ar))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ar ErrActiveRegistration) Forbidden() {}
|
|
@ -21,7 +21,7 @@ const (
|
|||
networkType = "bridge"
|
||||
vethPrefix = "veth"
|
||||
vethLen = 7
|
||||
containerVeth = "eth0"
|
||||
containerVethPrefix = "eth"
|
||||
maxAllocatePortAttempts = 10
|
||||
ifaceID = 1
|
||||
)
|
||||
|
@ -57,8 +57,8 @@ type NetworkConfiguration struct {
|
|||
// EndpointConfiguration represents the user specified configuration for the sandbox endpoint
|
||||
type EndpointConfiguration struct {
|
||||
MacAddress net.HardwareAddr
|
||||
PortBindings []netutils.PortBinding
|
||||
ExposedPorts []netutils.TransportPort
|
||||
PortBindings []types.PortBinding
|
||||
ExposedPorts []types.TransportPort
|
||||
}
|
||||
|
||||
// ContainerConfiguration represents the user specified configuration for a container
|
||||
|
@ -73,7 +73,7 @@ type bridgeEndpoint struct {
|
|||
macAddress net.HardwareAddr
|
||||
config *EndpointConfiguration // User specified parameters
|
||||
containerConfig *ContainerConfiguration
|
||||
portMapping []netutils.PortBinding // Operation port bindings
|
||||
portMapping []types.PortBinding // Operation port bindings
|
||||
}
|
||||
|
||||
type bridgeNetwork struct {
|
||||
|
@ -109,7 +109,7 @@ func Init(dc driverapi.DriverCallback) error {
|
|||
// Whatever can be assessed a priori before attempting any programming.
|
||||
func (c *NetworkConfiguration) Validate() error {
|
||||
if c.Mtu < 0 {
|
||||
return ErrInvalidMtu
|
||||
return ErrInvalidMtu(c.Mtu)
|
||||
}
|
||||
|
||||
// If bridge v4 subnet is specified
|
||||
|
@ -118,19 +118,19 @@ func (c *NetworkConfiguration) Validate() error {
|
|||
if c.FixedCIDR != nil {
|
||||
// Check Network address
|
||||
if !c.AddressIPv4.Contains(c.FixedCIDR.IP) {
|
||||
return ErrInvalidContainerSubnet
|
||||
return &ErrInvalidContainerSubnet{}
|
||||
}
|
||||
// Check it is effectively a subset
|
||||
brNetLen, _ := c.AddressIPv4.Mask.Size()
|
||||
cnNetLen, _ := c.FixedCIDR.Mask.Size()
|
||||
if brNetLen > cnNetLen {
|
||||
return ErrInvalidContainerSubnet
|
||||
return &ErrInvalidContainerSubnet{}
|
||||
}
|
||||
}
|
||||
// If default gw is specified, it must be part of bridge subnet
|
||||
if c.DefaultGatewayIPv4 != nil {
|
||||
if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) {
|
||||
return ErrInvalidGateway
|
||||
return &ErrInvalidGateway{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ func (c *NetworkConfiguration) Validate() error {
|
|||
// If default v6 gw is specified, FixedCIDRv6 must be specified and gw must belong to FixedCIDRv6 subnet
|
||||
if c.EnableIPv6 && c.DefaultGatewayIPv6 != nil {
|
||||
if c.FixedCIDRv6 == nil || !c.FixedCIDRv6.Contains(c.DefaultGatewayIPv6) {
|
||||
return ErrInvalidGateway
|
||||
return &ErrInvalidGateway{}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ func (d *driver) Config(option map[string]interface{}) error {
|
|||
defer d.Unlock()
|
||||
|
||||
if d.config != nil {
|
||||
return ErrConfigExists
|
||||
return &ErrConfigExists{}
|
||||
}
|
||||
|
||||
genericData, ok := option[netlabel.GenericData]
|
||||
|
@ -182,7 +182,7 @@ func (d *driver) Config(option map[string]interface{}) error {
|
|||
case *Configuration:
|
||||
config = opt
|
||||
default:
|
||||
return ErrInvalidDriverConfig
|
||||
return &ErrInvalidDriverConfig{}
|
||||
}
|
||||
|
||||
d.config = config
|
||||
|
@ -220,7 +220,7 @@ func parseNetworkOptions(option options.Generic) (*NetworkConfiguration, error)
|
|||
case *NetworkConfiguration:
|
||||
config = opt
|
||||
default:
|
||||
return nil, ErrInvalidNetworkConfig
|
||||
return nil, &ErrInvalidNetworkConfig{}
|
||||
}
|
||||
|
||||
if err := config.Validate(); err != nil {
|
||||
|
@ -247,7 +247,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
|
|||
// Sanity checks
|
||||
if d.network != nil {
|
||||
d.Unlock()
|
||||
return ErrNetworkExists
|
||||
return &ErrNetworkExists{}
|
||||
}
|
||||
|
||||
// Create and set network handler in driver
|
||||
|
@ -361,7 +361,7 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
|
|||
|
||||
// Sanity check
|
||||
if n == nil {
|
||||
err = driverapi.ErrNoNetwork
|
||||
err = driverapi.ErrNoNetwork(nid)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -397,7 +397,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
|||
config := n.config
|
||||
d.Unlock()
|
||||
if n == nil {
|
||||
return driverapi.ErrNoNetwork
|
||||
return driverapi.ErrNoNetwork(nid)
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
|
@ -416,7 +416,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
|||
|
||||
// Endpoint with that id exists either on desired or other sandbox
|
||||
if ep != nil {
|
||||
return driverapi.ErrEndpointExists
|
||||
return driverapi.ErrEndpointExists(eid)
|
||||
}
|
||||
|
||||
// Try to convert the options to endpoint configuration
|
||||
|
@ -545,7 +545,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
|||
// Create the sandbox side pipe interface
|
||||
intf := &sandbox.Interface{}
|
||||
intf.SrcName = name2
|
||||
intf.DstName = containerVeth
|
||||
intf.DstName = containerVethPrefix
|
||||
intf.Address = ipv4Addr
|
||||
|
||||
if config.EnableIPv6 {
|
||||
|
@ -578,7 +578,7 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
|
|||
config := n.config
|
||||
d.Unlock()
|
||||
if n == nil {
|
||||
return driverapi.ErrNoNetwork
|
||||
return driverapi.ErrNoNetwork(nid)
|
||||
}
|
||||
|
||||
// Sanity Check
|
||||
|
@ -648,7 +648,7 @@ func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{},
|
|||
n := d.network
|
||||
d.Unlock()
|
||||
if n == nil {
|
||||
return nil, driverapi.ErrNoNetwork
|
||||
return nil, driverapi.ErrNoNetwork(nid)
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
|
@ -665,14 +665,14 @@ func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{},
|
|||
return nil, err
|
||||
}
|
||||
if ep == nil {
|
||||
return nil, driverapi.ErrNoEndpoint
|
||||
return nil, driverapi.ErrNoEndpoint(eid)
|
||||
}
|
||||
|
||||
m := make(map[string]interface{})
|
||||
|
||||
if ep.portMapping != nil {
|
||||
// Return a copy of the operational data
|
||||
pmc := make([]netutils.PortBinding, 0, len(ep.portMapping))
|
||||
pmc := make([]types.PortBinding, 0, len(ep.portMapping))
|
||||
for _, pm := range ep.portMapping {
|
||||
pmc = append(pmc, pm.GetCopy())
|
||||
}
|
||||
|
@ -856,23 +856,23 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*EndpointConfigurat
|
|||
if mac, ok := opt.(net.HardwareAddr); ok {
|
||||
ec.MacAddress = mac
|
||||
} else {
|
||||
return nil, ErrInvalidEndpointConfig
|
||||
return nil, &ErrInvalidEndpointConfig{}
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||
if bs, ok := opt.([]netutils.PortBinding); ok {
|
||||
if bs, ok := opt.([]types.PortBinding); ok {
|
||||
ec.PortBindings = bs
|
||||
} else {
|
||||
return nil, ErrInvalidEndpointConfig
|
||||
return nil, &ErrInvalidEndpointConfig{}
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
||||
if ports, ok := opt.([]netutils.TransportPort); ok {
|
||||
if ports, ok := opt.([]types.TransportPort); ok {
|
||||
ec.ExposedPorts = ports
|
||||
} else {
|
||||
return nil, ErrInvalidEndpointConfig
|
||||
return nil, &ErrInvalidEndpointConfig{}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -924,5 +924,5 @@ func generateIfaceName() (string, error) {
|
|||
return "", err
|
||||
}
|
||||
}
|
||||
return "", ErrIfaceName
|
||||
return "", &ErrIfaceName{}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
|
@ -202,7 +203,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
|
|||
if !ok {
|
||||
t.Fatalf("Endpoint operational data does not contain port mapping data")
|
||||
}
|
||||
pm, ok := pmd.([]netutils.PortBinding)
|
||||
pm, ok := pmd.([]types.PortBinding)
|
||||
if !ok {
|
||||
t.Fatalf("Unexpected format for port mapping in endpoint operational data")
|
||||
}
|
||||
|
@ -261,19 +262,19 @@ func TestCreateLinkWithOptions(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func getExposedPorts() []netutils.TransportPort {
|
||||
return []netutils.TransportPort{
|
||||
netutils.TransportPort{Proto: netutils.TCP, Port: uint16(5000)},
|
||||
netutils.TransportPort{Proto: netutils.UDP, Port: uint16(400)},
|
||||
netutils.TransportPort{Proto: netutils.TCP, Port: uint16(600)},
|
||||
func getExposedPorts() []types.TransportPort {
|
||||
return []types.TransportPort{
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(5000)},
|
||||
types.TransportPort{Proto: types.UDP, Port: uint16(400)},
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(600)},
|
||||
}
|
||||
}
|
||||
|
||||
func getPortMapping() []netutils.PortBinding {
|
||||
return []netutils.PortBinding{
|
||||
netutils.PortBinding{Proto: netutils.TCP, Port: uint16(230), HostPort: uint16(23000)},
|
||||
netutils.PortBinding{Proto: netutils.UDP, Port: uint16(200), HostPort: uint16(22000)},
|
||||
netutils.PortBinding{Proto: netutils.TCP, Port: uint16(120), HostPort: uint16(12000)},
|
||||
func getPortMapping() []types.PortBinding {
|
||||
return []types.PortBinding{
|
||||
types.PortBinding{Proto: types.TCP, Port: uint16(230), HostPort: uint16(23000)},
|
||||
types.PortBinding{Proto: types.UDP, Port: uint16(200), HostPort: uint16(22000)},
|
||||
types.PortBinding{Proto: types.TCP, Port: uint16(120), HostPort: uint16(12000)},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrConfigExists error is returned when driver already has a config applied.
|
||||
ErrConfigExists = errors.New("configuration already exists, bridge configuration can be applied only once")
|
||||
|
||||
// ErrInvalidDriverConfig error is returned when Bridge Driver is passed an invalid config
|
||||
ErrInvalidDriverConfig = errors.New("Invalid configuration passed to Bridge Driver")
|
||||
|
||||
// ErrInvalidNetworkConfig error is returned when a network is created on a driver without valid config.
|
||||
ErrInvalidNetworkConfig = errors.New("trying to create a network on a driver without valid config")
|
||||
|
||||
// ErrInvalidContainerConfig error is returned when a endpoint create is attempted with an invalid configuration.
|
||||
ErrInvalidContainerConfig = errors.New("Error in joining a container due to invalid configuration")
|
||||
|
||||
// ErrInvalidEndpointConfig error is returned when a endpoint create is attempted with an invalid endpoint configuration.
|
||||
ErrInvalidEndpointConfig = errors.New("trying to create an endpoint with an invalid endpoint configuration")
|
||||
|
||||
// ErrNetworkExists error is returned when a network already exists and another network is created.
|
||||
ErrNetworkExists = errors.New("network already exists, bridge can only have one network")
|
||||
|
||||
// ErrIfaceName error is returned when a new name could not be generated.
|
||||
ErrIfaceName = errors.New("failed to find name for new interface")
|
||||
|
||||
// ErrNoIPAddr error is returned when bridge has no IPv4 address configured.
|
||||
ErrNoIPAddr = errors.New("bridge has no IPv4 address configured")
|
||||
|
||||
// ErrInvalidGateway is returned when the user provided default gateway (v4/v6) is not not valid.
|
||||
ErrInvalidGateway = errors.New("default gateway ip must be part of the network")
|
||||
|
||||
// ErrInvalidContainerSubnet is returned when the container subnet (FixedCIDR) is not valid.
|
||||
ErrInvalidContainerSubnet = errors.New("container subnet must be a subset of bridge network")
|
||||
|
||||
// ErrInvalidMtu is returned when the user provided MTU is not valid.
|
||||
ErrInvalidMtu = errors.New("invalid MTU number")
|
||||
|
||||
// ErrIPFwdCfg is returned when ip forwarding setup is invoked when the configuration
|
||||
// not enabled.
|
||||
ErrIPFwdCfg = errors.New("unexpected request to enable IP Forwarding")
|
||||
)
|
||||
|
||||
// ErrInvalidPort is returned when the container or host port specified in the port binding is not valid.
|
||||
type ErrInvalidPort string
|
||||
|
||||
func (ip ErrInvalidPort) Error() string {
|
||||
return fmt.Sprintf("invalid transport port: %s", string(ip))
|
||||
}
|
||||
|
||||
// ErrUnsupportedAddressType is returned when the specified address type is not supported.
|
||||
type ErrUnsupportedAddressType string
|
||||
|
||||
func (uat ErrUnsupportedAddressType) Error() string {
|
||||
return fmt.Sprintf("unsupported address type: %s", string(uat))
|
||||
}
|
||||
|
||||
// ErrInvalidAddressBinding is returned when the host address specified in the port binding is not valid.
|
||||
type ErrInvalidAddressBinding string
|
||||
|
||||
func (iab ErrInvalidAddressBinding) Error() string {
|
||||
return fmt.Sprintf("invalid host address in port binding: %s", string(iab))
|
||||
}
|
||||
|
||||
// ActiveEndpointsError is returned when there are
|
||||
// still active endpoints in the network being deleted.
|
||||
type ActiveEndpointsError string
|
||||
|
||||
func (aee ActiveEndpointsError) Error() string {
|
||||
return fmt.Sprintf("network %s has active endpoint", string(aee))
|
||||
}
|
||||
|
||||
// InvalidNetworkIDError is returned when the passed
|
||||
// network id for an existing network is not a known id.
|
||||
type InvalidNetworkIDError string
|
||||
|
||||
func (inie InvalidNetworkIDError) Error() string {
|
||||
return fmt.Sprintf("invalid network id %s", string(inie))
|
||||
}
|
||||
|
||||
// InvalidEndpointIDError is returned when the passed
|
||||
// endpoint id is not valid.
|
||||
type InvalidEndpointIDError string
|
||||
|
||||
func (ieie InvalidEndpointIDError) Error() string {
|
||||
return fmt.Sprintf("invalid endpoint id: %s", string(ieie))
|
||||
}
|
||||
|
||||
// InvalidSandboxIDError is returned when the passed
|
||||
// sandbox id valid.
|
||||
type InvalidSandboxIDError string
|
||||
|
||||
func (isie InvalidSandboxIDError) Error() string {
|
||||
return fmt.Sprintf("invalid sanbox id: %s", string(isie))
|
||||
}
|
||||
|
||||
// EndpointNotFoundError is returned when the no endpoint
|
||||
// with the passed endpoint id is found.
|
||||
type EndpointNotFoundError string
|
||||
|
||||
func (enfe EndpointNotFoundError) Error() string {
|
||||
return fmt.Sprintf("endpoint not found: %s", string(enfe))
|
||||
}
|
||||
|
||||
// NonDefaultBridgeExistError is returned when a non-default
|
||||
// bridge config is passed but it does not already exist.
|
||||
type NonDefaultBridgeExistError string
|
||||
|
||||
func (ndbee NonDefaultBridgeExistError) Error() string {
|
||||
return fmt.Sprintf("bridge device with non default name %s must be created manually", string(ndbee))
|
||||
}
|
||||
|
||||
// FixedCIDRv4Error is returned when fixed-cidrv4 configuration
|
||||
// failed.
|
||||
type FixedCIDRv4Error struct {
|
||||
net *net.IPNet
|
||||
subnet *net.IPNet
|
||||
err error
|
||||
}
|
||||
|
||||
func (fcv4 *FixedCIDRv4Error) Error() string {
|
||||
return fmt.Sprintf("setup FixedCIDRv4 failed for subnet %s in %s: %v", fcv4.subnet, fcv4.net, fcv4.err)
|
||||
}
|
||||
|
||||
// FixedCIDRv6Error is returned when fixed-cidrv6 configuration
|
||||
// failed.
|
||||
type FixedCIDRv6Error struct {
|
||||
net *net.IPNet
|
||||
err error
|
||||
}
|
||||
|
||||
func (fcv6 *FixedCIDRv6Error) Error() string {
|
||||
return fmt.Sprintf("setup FixedCIDRv6 failed for subnet %s in %s: %v", fcv6.net, fcv6.net, fcv6.err)
|
||||
}
|
||||
|
||||
type ipTableCfgError string
|
||||
|
||||
func (name ipTableCfgError) Error() string {
|
||||
return fmt.Sprintf("unexpected request to set IP tables for interface: %s", string(name))
|
||||
}
|
||||
|
||||
type invalidIPTablesCfgError string
|
||||
|
||||
func (action invalidIPTablesCfgError) Error() string {
|
||||
return fmt.Sprintf("Invalid IPTables action '%s'", string(action))
|
||||
}
|
||||
|
||||
// IPv4AddrRangeError is returned when a valid IP address range couldn't be found.
|
||||
type IPv4AddrRangeError string
|
||||
|
||||
func (name IPv4AddrRangeError) Error() string {
|
||||
return fmt.Sprintf("can't find an address range for interface %q", string(name))
|
||||
}
|
||||
|
||||
// IPv4AddrAddError is returned when IPv4 address could not be added to the bridge.
|
||||
type IPv4AddrAddError struct {
|
||||
ip *net.IPNet
|
||||
err error
|
||||
}
|
||||
|
||||
func (ipv4 *IPv4AddrAddError) Error() string {
|
||||
return fmt.Sprintf("failed to add IPv4 address %s to bridge: %v", ipv4.ip, ipv4.err)
|
||||
}
|
||||
|
||||
// IPv6AddrAddError is returned when IPv6 address could not be added to the bridge.
|
||||
type IPv6AddrAddError struct {
|
||||
ip *net.IPNet
|
||||
err error
|
||||
}
|
||||
|
||||
func (ipv6 *IPv6AddrAddError) Error() string {
|
||||
return fmt.Sprintf("failed to add IPv6 address %s to bridge: %v", ipv6.ip, ipv6.err)
|
||||
}
|
||||
|
||||
// IPv4AddrNoMatchError is returned when the bridge's IPv4 address does not match configured.
|
||||
type IPv4AddrNoMatchError struct {
|
||||
ip net.IP
|
||||
cfgIP net.IP
|
||||
}
|
||||
|
||||
func (ipv4 *IPv4AddrNoMatchError) Error() string {
|
||||
return fmt.Sprintf("bridge IPv4 (%s) does not match requested configuration %s", ipv4.ip, ipv4.cfgIP)
|
||||
}
|
||||
|
||||
// IPv6AddrNoMatchError is returned when the bridge's IPv6 address does not match configured.
|
||||
type IPv6AddrNoMatchError net.IPNet
|
||||
|
||||
func (ipv6 *IPv6AddrNoMatchError) Error() string {
|
||||
return fmt.Sprintf("bridge IPv6 addresses do not match the expected bridge configuration %s", (*net.IPNet)(ipv6).String())
|
||||
}
|
||||
|
||||
// InvalidLinkIPAddrError is returned when a link is configured to a container with an invalid ip address
|
||||
type InvalidLinkIPAddrError string
|
||||
|
||||
func (address InvalidLinkIPAddrError) Error() string {
|
||||
return fmt.Sprintf("Cannot link to a container with Invalid IP Address '%s'", string(address))
|
||||
}
|
341
vendor/src/github.com/docker/libnetwork/drivers/bridge/errors.go
vendored
Normal file
341
vendor/src/github.com/docker/libnetwork/drivers/bridge/errors.go
vendored
Normal file
|
@ -0,0 +1,341 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// ErrConfigExists error is returned when driver already has a config applied.
|
||||
type ErrConfigExists struct{}
|
||||
|
||||
func (ece *ErrConfigExists) Error() string {
|
||||
return "configuration already exists, bridge configuration can be applied only once"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ece *ErrConfigExists) Forbidden() {}
|
||||
|
||||
// ErrInvalidDriverConfig error is returned when Bridge Driver is passed an invalid config
|
||||
type ErrInvalidDriverConfig struct{}
|
||||
|
||||
func (eidc *ErrInvalidDriverConfig) Error() string {
|
||||
return "Invalid configuration passed to Bridge Driver"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eidc *ErrInvalidDriverConfig) BadRequest() {}
|
||||
|
||||
// ErrInvalidNetworkConfig error is returned when a network is created on a driver without valid config.
|
||||
type ErrInvalidNetworkConfig struct{}
|
||||
|
||||
func (einc *ErrInvalidNetworkConfig) Error() string {
|
||||
return "trying to create a network on a driver without valid config"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (einc *ErrInvalidNetworkConfig) Forbidden() {}
|
||||
|
||||
// ErrInvalidContainerConfig error is returned when a endpoint create is attempted with an invalid configuration.
|
||||
type ErrInvalidContainerConfig struct{}
|
||||
|
||||
func (eicc *ErrInvalidContainerConfig) Error() string {
|
||||
return "Error in joining a container due to invalid configuration"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eicc *ErrInvalidContainerConfig) BadRequest() {}
|
||||
|
||||
// ErrInvalidEndpointConfig error is returned when a endpoint create is attempted with an invalid endpoint configuration.
|
||||
type ErrInvalidEndpointConfig struct{}
|
||||
|
||||
func (eiec *ErrInvalidEndpointConfig) Error() string {
|
||||
return "trying to create an endpoint with an invalid endpoint configuration"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eiec *ErrInvalidEndpointConfig) BadRequest() {}
|
||||
|
||||
// ErrNetworkExists error is returned when a network already exists and another network is created.
|
||||
type ErrNetworkExists struct{}
|
||||
|
||||
func (ene *ErrNetworkExists) Error() string {
|
||||
return "network already exists, bridge can only have one network"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ene *ErrNetworkExists) Forbidden() {}
|
||||
|
||||
// ErrIfaceName error is returned when a new name could not be generated.
|
||||
type ErrIfaceName struct{}
|
||||
|
||||
func (ein *ErrIfaceName) Error() string {
|
||||
return "failed to find name for new interface"
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ein *ErrIfaceName) InternalError() {}
|
||||
|
||||
// ErrNoIPAddr error is returned when bridge has no IPv4 address configured.
|
||||
type ErrNoIPAddr struct{}
|
||||
|
||||
func (enip *ErrNoIPAddr) Error() string {
|
||||
return "bridge has no IPv4 address configured"
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (enip *ErrNoIPAddr) InternalError() {}
|
||||
|
||||
// ErrInvalidGateway is returned when the user provided default gateway (v4/v6) is not not valid.
|
||||
type ErrInvalidGateway struct{}
|
||||
|
||||
func (eig *ErrInvalidGateway) Error() string {
|
||||
return "default gateway ip must be part of the network"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eig *ErrInvalidGateway) BadRequest() {}
|
||||
|
||||
// ErrInvalidContainerSubnet is returned when the container subnet (FixedCIDR) is not valid.
|
||||
type ErrInvalidContainerSubnet struct{}
|
||||
|
||||
func (eis *ErrInvalidContainerSubnet) Error() string {
|
||||
return "container subnet must be a subset of bridge network"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eis *ErrInvalidContainerSubnet) BadRequest() {}
|
||||
|
||||
// ErrInvalidMtu is returned when the user provided MTU is not valid.
|
||||
type ErrInvalidMtu int
|
||||
|
||||
func (eim ErrInvalidMtu) Error() string {
|
||||
return fmt.Sprintf("invalid MTU number: %d", int(eim))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eim ErrInvalidMtu) BadRequest() {}
|
||||
|
||||
// ErrIPFwdCfg is returned when ip forwarding setup is invoked when the configuration
|
||||
// not enabled.
|
||||
type ErrIPFwdCfg struct{}
|
||||
|
||||
func (eipf *ErrIPFwdCfg) Error() string {
|
||||
return "unexpected request to enable IP Forwarding"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eipf *ErrIPFwdCfg) BadRequest() {}
|
||||
|
||||
// ErrInvalidPort is returned when the container or host port specified in the port binding is not valid.
|
||||
type ErrInvalidPort string
|
||||
|
||||
func (ip ErrInvalidPort) Error() string {
|
||||
return fmt.Sprintf("invalid transport port: %s", string(ip))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ip ErrInvalidPort) BadRequest() {}
|
||||
|
||||
// ErrUnsupportedAddressType is returned when the specified address type is not supported.
|
||||
type ErrUnsupportedAddressType string
|
||||
|
||||
func (uat ErrUnsupportedAddressType) Error() string {
|
||||
return fmt.Sprintf("unsupported address type: %s", string(uat))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (uat ErrUnsupportedAddressType) BadRequest() {}
|
||||
|
||||
// ErrInvalidAddressBinding is returned when the host address specified in the port binding is not valid.
|
||||
type ErrInvalidAddressBinding string
|
||||
|
||||
func (iab ErrInvalidAddressBinding) Error() string {
|
||||
return fmt.Sprintf("invalid host address in port binding: %s", string(iab))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (iab ErrInvalidAddressBinding) BadRequest() {}
|
||||
|
||||
// ActiveEndpointsError is returned when there are
|
||||
// still active endpoints in the network being deleted.
|
||||
type ActiveEndpointsError string
|
||||
|
||||
func (aee ActiveEndpointsError) Error() string {
|
||||
return fmt.Sprintf("network %s has active endpoint", string(aee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (aee ActiveEndpointsError) Forbidden() {}
|
||||
|
||||
// InvalidNetworkIDError is returned when the passed
|
||||
// network id for an existing network is not a known id.
|
||||
type InvalidNetworkIDError string
|
||||
|
||||
func (inie InvalidNetworkIDError) Error() string {
|
||||
return fmt.Sprintf("invalid network id %s", string(inie))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (inie InvalidNetworkIDError) NotFound() {}
|
||||
|
||||
// InvalidEndpointIDError is returned when the passed
|
||||
// endpoint id is not valid.
|
||||
type InvalidEndpointIDError string
|
||||
|
||||
func (ieie InvalidEndpointIDError) Error() string {
|
||||
return fmt.Sprintf("invalid endpoint id: %s", string(ieie))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ieie InvalidEndpointIDError) BadRequest() {}
|
||||
|
||||
// InvalidSandboxIDError is returned when the passed
|
||||
// sandbox id is not valid.
|
||||
type InvalidSandboxIDError string
|
||||
|
||||
func (isie InvalidSandboxIDError) Error() string {
|
||||
return fmt.Sprintf("invalid sanbox id: %s", string(isie))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (isie InvalidSandboxIDError) BadRequest() {}
|
||||
|
||||
// EndpointNotFoundError is returned when the no endpoint
|
||||
// with the passed endpoint id is found.
|
||||
type EndpointNotFoundError string
|
||||
|
||||
func (enfe EndpointNotFoundError) Error() string {
|
||||
return fmt.Sprintf("endpoint not found: %s", string(enfe))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (enfe EndpointNotFoundError) NotFound() {}
|
||||
|
||||
// NonDefaultBridgeExistError is returned when a non-default
|
||||
// bridge config is passed but it does not already exist.
|
||||
type NonDefaultBridgeExistError string
|
||||
|
||||
func (ndbee NonDefaultBridgeExistError) Error() string {
|
||||
return fmt.Sprintf("bridge device with non default name %s must be created manually", string(ndbee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ndbee NonDefaultBridgeExistError) Forbidden() {}
|
||||
|
||||
// FixedCIDRv4Error is returned when fixed-cidrv4 configuration
|
||||
// failed.
|
||||
type FixedCIDRv4Error struct {
|
||||
Net *net.IPNet
|
||||
Subnet *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fcv4 *FixedCIDRv4Error) Error() string {
|
||||
return fmt.Sprintf("setup FixedCIDRv4 failed for subnet %s in %s: %v", fcv4.Subnet, fcv4.Net, fcv4.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (fcv4 *FixedCIDRv4Error) InternalError() {}
|
||||
|
||||
// FixedCIDRv6Error is returned when fixed-cidrv6 configuration
|
||||
// failed.
|
||||
type FixedCIDRv6Error struct {
|
||||
Net *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fcv6 *FixedCIDRv6Error) Error() string {
|
||||
return fmt.Sprintf("setup FixedCIDRv6 failed for subnet %s in %s: %v", fcv6.Net, fcv6.Net, fcv6.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (fcv6 *FixedCIDRv6Error) InternalError() {}
|
||||
|
||||
// IPTableCfgError is returned when an unexpected ip tables configuration is entered
|
||||
type IPTableCfgError string
|
||||
|
||||
func (name IPTableCfgError) Error() string {
|
||||
return fmt.Sprintf("unexpected request to set IP tables for interface: %s", string(name))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (name IPTableCfgError) BadRequest() {}
|
||||
|
||||
// InvalidIPTablesCfgError is returned when an invalid ip tables configuration is entered
|
||||
type InvalidIPTablesCfgError string
|
||||
|
||||
func (action InvalidIPTablesCfgError) Error() string {
|
||||
return fmt.Sprintf("Invalid IPTables action '%s'", string(action))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (action InvalidIPTablesCfgError) BadRequest() {}
|
||||
|
||||
// IPv4AddrRangeError is returned when a valid IP address range couldn't be found.
|
||||
type IPv4AddrRangeError string
|
||||
|
||||
func (name IPv4AddrRangeError) Error() string {
|
||||
return fmt.Sprintf("can't find an address range for interface %q", string(name))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (name IPv4AddrRangeError) BadRequest() {}
|
||||
|
||||
// IPv4AddrAddError is returned when IPv4 address could not be added to the bridge.
|
||||
type IPv4AddrAddError struct {
|
||||
IP *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (ipv4 *IPv4AddrAddError) Error() string {
|
||||
return fmt.Sprintf("failed to add IPv4 address %s to bridge: %v", ipv4.IP, ipv4.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ipv4 *IPv4AddrAddError) InternalError() {}
|
||||
|
||||
// IPv6AddrAddError is returned when IPv6 address could not be added to the bridge.
|
||||
type IPv6AddrAddError struct {
|
||||
IP *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (ipv6 *IPv6AddrAddError) Error() string {
|
||||
return fmt.Sprintf("failed to add IPv6 address %s to bridge: %v", ipv6.IP, ipv6.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ipv6 *IPv6AddrAddError) InternalError() {}
|
||||
|
||||
// IPv4AddrNoMatchError is returned when the bridge's IPv4 address does not match configured.
|
||||
type IPv4AddrNoMatchError struct {
|
||||
IP net.IP
|
||||
CfgIP net.IP
|
||||
}
|
||||
|
||||
func (ipv4 *IPv4AddrNoMatchError) Error() string {
|
||||
return fmt.Sprintf("bridge IPv4 (%s) does not match requested configuration %s", ipv4.IP, ipv4.CfgIP)
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ipv4 *IPv4AddrNoMatchError) BadRequest() {}
|
||||
|
||||
// IPv6AddrNoMatchError is returned when the bridge's IPv6 address does not match configured.
|
||||
type IPv6AddrNoMatchError net.IPNet
|
||||
|
||||
func (ipv6 *IPv6AddrNoMatchError) Error() string {
|
||||
return fmt.Sprintf("bridge IPv6 addresses do not match the expected bridge configuration %s", (*net.IPNet)(ipv6).String())
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ipv6 *IPv6AddrNoMatchError) BadRequest() {}
|
||||
|
||||
// InvalidLinkIPAddrError is returned when a link is configured to a container with an invalid ip address
|
||||
type InvalidLinkIPAddrError string
|
||||
|
||||
func (address InvalidLinkIPAddrError) Error() string {
|
||||
return fmt.Sprintf("Cannot link to a container with Invalid IP Address '%s'", string(address))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (address InvalidLinkIPAddrError) BadRequest() {}
|
|
@ -6,13 +6,13 @@ import (
|
|||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
type link struct {
|
||||
parentIP string
|
||||
childIP string
|
||||
ports []netutils.TransportPort
|
||||
ports []types.TransportPort
|
||||
bridge string
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ func (l *link) String() string {
|
|||
return fmt.Sprintf("%s <-> %s [%v] on %s", l.parentIP, l.childIP, l.ports, l.bridge)
|
||||
}
|
||||
|
||||
func newLink(parentIP, childIP string, ports []netutils.TransportPort, bridge string) *link {
|
||||
func newLink(parentIP, childIP string, ports []types.TransportPort, bridge string) *link {
|
||||
return &link{
|
||||
childIP: childIP,
|
||||
parentIP: parentIP,
|
||||
|
@ -45,7 +45,7 @@ func (l *link) Disable() {
|
|||
// that returns typed errors
|
||||
}
|
||||
|
||||
func linkContainers(action, parentIP, childIP string, ports []netutils.TransportPort, bridge string,
|
||||
func linkContainers(action, parentIP, childIP string, ports []types.TransportPort, bridge string,
|
||||
ignoreErrors bool) error {
|
||||
var nfAction iptables.Action
|
||||
|
||||
|
@ -57,7 +57,7 @@ func linkContainers(action, parentIP, childIP string, ports []netutils.Transport
|
|||
case "-D":
|
||||
nfAction = iptables.Delete
|
||||
default:
|
||||
return invalidIPTablesCfgError(action)
|
||||
return InvalidIPTablesCfgError(action)
|
||||
}
|
||||
|
||||
ip1 := net.ParseIP(parentIP)
|
||||
|
|
|
@ -3,14 +3,14 @@ package bridge
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
func getPorts() []netutils.TransportPort {
|
||||
return []netutils.TransportPort{
|
||||
netutils.TransportPort{Proto: netutils.TCP, Port: uint16(5000)},
|
||||
netutils.TransportPort{Proto: netutils.UDP, Port: uint16(400)},
|
||||
netutils.TransportPort{Proto: netutils.TCP, Port: uint16(600)},
|
||||
func getPorts() []types.TransportPort {
|
||||
return []types.TransportPort{
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(5000)},
|
||||
types.TransportPort{Proto: types.UDP, Port: uint16(400)},
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(600)},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,8 +125,8 @@ func TestLinkCreateTwo(t *testing.T) {
|
|||
te2 := &testEndpoint{ifaces: []*testInterface{}}
|
||||
err = d.CreateEndpoint("dummy", "ep", te2, nil)
|
||||
if err != nil {
|
||||
if err != driverapi.ErrEndpointExists {
|
||||
t.Fatalf("Failed with a wrong error :%s", err.Error())
|
||||
if _, ok := err.(driverapi.ErrEndpointExists); !ok {
|
||||
t.Fatalf("Failed with a wrong error: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Expected to fail while trying to add same endpoint twice")
|
||||
|
|
|
@ -7,15 +7,15 @@ import (
|
|||
"net"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/sandbox"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultBindingIP = net.IPv4(0, 0, 0, 0)
|
||||
)
|
||||
|
||||
func allocatePorts(epConfig *EndpointConfiguration, intf *sandbox.Interface, reqDefBindIP net.IP, ulPxyEnabled bool) ([]netutils.PortBinding, error) {
|
||||
func allocatePorts(epConfig *EndpointConfiguration, intf *sandbox.Interface, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
if epConfig == nil || epConfig.PortBindings == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ func allocatePorts(epConfig *EndpointConfiguration, intf *sandbox.Interface, req
|
|||
return allocatePortsInternal(epConfig.PortBindings, intf.Address.IP, defHostIP, ulPxyEnabled)
|
||||
}
|
||||
|
||||
func allocatePortsInternal(bindings []netutils.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]netutils.PortBinding, error) {
|
||||
bs := make([]netutils.PortBinding, 0, len(bindings))
|
||||
func allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
bs := make([]types.PortBinding, 0, len(bindings))
|
||||
for _, c := range bindings {
|
||||
b := c.GetCopy()
|
||||
if err := allocatePort(&b, containerIP, defHostIP, ulPxyEnabled); err != nil {
|
||||
|
@ -44,7 +44,7 @@ func allocatePortsInternal(bindings []netutils.PortBinding, containerIP, defHost
|
|||
return bs, nil
|
||||
}
|
||||
|
||||
func allocatePort(bnd *netutils.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) error {
|
||||
func allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) error {
|
||||
var (
|
||||
host net.Addr
|
||||
err error
|
||||
|
@ -98,7 +98,7 @@ func releasePorts(ep *bridgeEndpoint) error {
|
|||
return releasePortsInternal(ep.portMapping)
|
||||
}
|
||||
|
||||
func releasePortsInternal(bindings []netutils.PortBinding) error {
|
||||
func releasePortsInternal(bindings []types.PortBinding) error {
|
||||
var errorBuf bytes.Buffer
|
||||
|
||||
// Attempt to release all port bindings, do not stop on failure
|
||||
|
@ -114,7 +114,7 @@ func releasePortsInternal(bindings []netutils.PortBinding) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func releasePort(bnd netutils.PortBinding) error {
|
||||
func releasePort(bnd types.PortBinding) error {
|
||||
// Construct the host side transport address
|
||||
host, err := bnd.HostAddr()
|
||||
if err != nil {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -20,9 +21,9 @@ func TestPortMappingConfig(t *testing.T) {
|
|||
defer netutils.SetupTestNetNS(t)()
|
||||
d := newDriver()
|
||||
|
||||
binding1 := netutils.PortBinding{Proto: netutils.UDP, Port: uint16(400), HostPort: uint16(54000)}
|
||||
binding2 := netutils.PortBinding{Proto: netutils.TCP, Port: uint16(500), HostPort: uint16(65000)}
|
||||
portBindings := []netutils.PortBinding{binding1, binding2}
|
||||
binding1 := types.PortBinding{Proto: types.UDP, Port: uint16(400), HostPort: uint16(54000)}
|
||||
binding2 := types.PortBinding{Proto: types.TCP, Port: uint16(500), HostPort: uint16(65000)}
|
||||
portBindings := []types.PortBinding{binding1, binding2}
|
||||
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.PortMap] = portBindings
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package bridge
|
||||
|
||||
import log "github.com/Sirupsen/logrus"
|
||||
import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
func setupFixedCIDRv4(config *NetworkConfiguration, i *bridgeInterface) error {
|
||||
addrv4, _, err := i.addresses()
|
||||
|
@ -10,7 +12,7 @@ func setupFixedCIDRv4(config *NetworkConfiguration, i *bridgeInterface) error {
|
|||
|
||||
log.Debugf("Using IPv4 subnet: %v", config.FixedCIDR)
|
||||
if err := ipAllocator.RegisterSubnet(addrv4.IPNet, config.FixedCIDR); err != nil {
|
||||
return &FixedCIDRv4Error{subnet: config.FixedCIDR, net: addrv4.IPNet, err: err}
|
||||
return &FixedCIDRv4Error{Subnet: config.FixedCIDR, Net: addrv4.IPNet, Err: err}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package bridge
|
||||
|
||||
import log "github.com/Sirupsen/logrus"
|
||||
import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
func setupFixedCIDRv6(config *NetworkConfiguration, i *bridgeInterface) error {
|
||||
log.Debugf("Using IPv6 subnet: %v", config.FixedCIDRv6)
|
||||
if err := ipAllocator.RegisterSubnet(config.FixedCIDRv6, config.FixedCIDRv6); err != nil {
|
||||
return &FixedCIDRv6Error{net: config.FixedCIDRv6, err: err}
|
||||
return &FixedCIDRv6Error{Net: config.FixedCIDRv6, Err: err}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -13,7 +13,7 @@ const (
|
|||
func setupIPForwarding(config *Configuration) error {
|
||||
// Sanity Check
|
||||
if config.EnableIPForwarding == false {
|
||||
return ErrIPFwdCfg
|
||||
return &ErrIPFwdCfg{}
|
||||
}
|
||||
|
||||
// Enable IPv4 forwarding
|
||||
|
|
|
@ -47,7 +47,7 @@ func TestUnexpectedSetupIPForwarding(t *testing.T) {
|
|||
t.Fatal("Setup IP forwarding was expected to fail")
|
||||
}
|
||||
|
||||
if err != ErrIPFwdCfg {
|
||||
if _, ok := err.(*ErrIPFwdCfg); !ok {
|
||||
t.Fatalf("Setup IP forwarding failed with unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ const (
|
|||
func setupIPTables(config *NetworkConfiguration, i *bridgeInterface) error {
|
||||
// Sanity check.
|
||||
if config.EnableIPTables == false {
|
||||
return ipTableCfgError(config.BridgeName)
|
||||
return IPTableCfgError(config.BridgeName)
|
||||
}
|
||||
|
||||
hairpinMode := !config.EnableUserlandProxy
|
||||
|
|
|
@ -71,7 +71,7 @@ func setupBridgeIPv4(config *NetworkConfiguration, i *bridgeInterface) error {
|
|||
|
||||
log.Debugf("Creating bridge interface %q with network %s", config.BridgeName, bridgeIPv4)
|
||||
if err := netlink.AddrAdd(i.Link, &netlink.Addr{IPNet: bridgeIPv4}); err != nil {
|
||||
return &IPv4AddrAddError{ip: bridgeIPv4, err: err}
|
||||
return &IPv4AddrAddError{IP: bridgeIPv4, Err: err}
|
||||
}
|
||||
|
||||
// Store bridge network and default gateway
|
||||
|
@ -114,7 +114,7 @@ func electBridgeIPv4(config *NetworkConfiguration) (*net.IPNet, error) {
|
|||
|
||||
func setupGatewayIPv4(config *NetworkConfiguration, i *bridgeInterface) error {
|
||||
if !i.bridgeIPv4.Contains(config.DefaultGatewayIPv4) {
|
||||
return ErrInvalidGateway
|
||||
return &ErrInvalidGateway{}
|
||||
}
|
||||
if _, err := ipAllocator.RequestIP(i.bridgeIPv4, config.DefaultGatewayIPv4); err != nil {
|
||||
return err
|
||||
|
|
|
@ -37,7 +37,7 @@ func setupBridgeIPv6(config *NetworkConfiguration, i *bridgeInterface) error {
|
|||
// Add the default link local ipv6 address if it doesn't exist
|
||||
if !findIPv6Address(netlink.Addr{IPNet: bridgeIPv6}, addrsv6) {
|
||||
if err := netlink.AddrAdd(i.Link, &netlink.Addr{IPNet: bridgeIPv6}); err != nil {
|
||||
return &IPv6AddrAddError{ip: bridgeIPv6, err: err}
|
||||
return &IPv6AddrAddError{IP: bridgeIPv6, Err: err}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,10 +50,10 @@ func setupBridgeIPv6(config *NetworkConfiguration, i *bridgeInterface) error {
|
|||
|
||||
func setupGatewayIPv6(config *NetworkConfiguration, i *bridgeInterface) error {
|
||||
if config.FixedCIDRv6 == nil {
|
||||
return ErrInvalidContainerSubnet
|
||||
return &ErrInvalidContainerSubnet{}
|
||||
}
|
||||
if !config.FixedCIDRv6.Contains(config.DefaultGatewayIPv6) {
|
||||
return ErrInvalidGateway
|
||||
return &ErrInvalidGateway{}
|
||||
}
|
||||
if _, err := ipAllocator.RequestIP(config.FixedCIDRv6, config.DefaultGatewayIPv6); err != nil {
|
||||
return err
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package bridge
|
||||
|
||||
import "github.com/vishvananda/netlink"
|
||||
import (
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func setupVerifyAndReconcile(config *NetworkConfiguration, i *bridgeInterface) error {
|
||||
// Fetch a single IPv4 and a slice of IPv6 addresses from the bridge.
|
||||
|
@ -11,12 +13,12 @@ func setupVerifyAndReconcile(config *NetworkConfiguration, i *bridgeInterface) e
|
|||
|
||||
// Verify that the bridge does have an IPv4 address.
|
||||
if addrv4.IPNet == nil {
|
||||
return ErrNoIPAddr
|
||||
return &ErrNoIPAddr{}
|
||||
}
|
||||
|
||||
// Verify that the bridge IPv4 address matches the requested configuration.
|
||||
if config.AddressIPv4 != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) {
|
||||
return &IPv4AddrNoMatchError{ip: addrv4.IP, cfgIP: config.AddressIPv4.IP}
|
||||
return &IPv4AddrNoMatchError{IP: addrv4.IP, CfgIP: config.AddressIPv4.IP}
|
||||
}
|
||||
|
||||
// Verify that one of the bridge IPv6 addresses matches the requested
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package remote
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
|
@ -9,59 +10,202 @@ import (
|
|||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
var errNoCallback = errors.New("No Callback handler registered with Driver")
|
||||
|
||||
type driver struct {
|
||||
endpoint *plugins.Client
|
||||
networkType string
|
||||
}
|
||||
|
||||
// Init does the necessary work to register remote drivers
|
||||
func newDriver(name string, client *plugins.Client) driverapi.Driver {
|
||||
return &driver{networkType: name, endpoint: client}
|
||||
}
|
||||
|
||||
// Init makes sure a remote driver is registered when a network driver
|
||||
// plugin is activated.
|
||||
func Init(dc driverapi.DriverCallback) error {
|
||||
plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
|
||||
|
||||
// TODO : Handhake with the Remote Plugin goes here
|
||||
|
||||
newDriver := &driver{networkType: name, endpoint: client}
|
||||
if err := dc.RegisterDriver(name, newDriver); err != nil {
|
||||
log.Errorf("Error registering Driver for %s due to %v", name, err)
|
||||
if err := dc.RegisterDriver(name, newDriver(name, client)); err != nil {
|
||||
log.Errorf("error registering driver for %s due to %v", name, err)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Config is not implemented for remote drivers, since it is assumed
|
||||
// to be supplied to the remote process out-of-band (e.g., as command
|
||||
// line arguments).
|
||||
func (d *driver) Config(option map[string]interface{}) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
return &driverapi.ErrNotImplemented{}
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
func (d *driver) call(methodName string, arg interface{}, retVal maybeError) error {
|
||||
method := driverapi.NetworkPluginEndpointType + "." + methodName
|
||||
err := d.endpoint.Call(method, arg, retVal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if e := retVal.getError(); e != "" {
|
||||
return fmt.Errorf("remote: %s", e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id types.UUID, options map[string]interface{}) error {
|
||||
create := &createNetworkRequest{
|
||||
NetworkID: string(id),
|
||||
Options: options,
|
||||
}
|
||||
return d.call("CreateNetwork", create, &createNetworkResponse{})
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid types.UUID) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
delete := &deleteNetworkRequest{NetworkID: string(nid)}
|
||||
return d.call("DeleteNetwork", delete, &deleteNetworkResponse{})
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
if epInfo == nil {
|
||||
return fmt.Errorf("must not be called with nil EndpointInfo")
|
||||
}
|
||||
|
||||
reqIfaces := make([]*endpointInterface, len(epInfo.Interfaces()))
|
||||
for i, iface := range epInfo.Interfaces() {
|
||||
addr4 := iface.Address()
|
||||
addr6 := iface.AddressIPv6()
|
||||
reqIfaces[i] = &endpointInterface{
|
||||
ID: iface.ID(),
|
||||
Address: addr4.String(),
|
||||
AddressIPv6: addr6.String(),
|
||||
MacAddress: iface.MacAddress().String(),
|
||||
}
|
||||
}
|
||||
create := &createEndpointRequest{
|
||||
NetworkID: string(nid),
|
||||
EndpointID: string(eid),
|
||||
Interfaces: reqIfaces,
|
||||
Options: epOptions,
|
||||
}
|
||||
var res createEndpointResponse
|
||||
if err := d.call("CreateEndpoint", create, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ifaces, err := res.parseInterfaces()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(reqIfaces) > 0 && len(ifaces) > 0 {
|
||||
// We're not supposed to add interfaces if there already are
|
||||
// some. Attempt to roll back
|
||||
return errorWithRollback("driver attempted to add more interfaces", d.DeleteEndpoint(nid, eid))
|
||||
}
|
||||
for _, iface := range ifaces {
|
||||
var addr4, addr6 net.IPNet
|
||||
if iface.Address != nil {
|
||||
addr4 = *(iface.Address)
|
||||
}
|
||||
if iface.AddressIPv6 != nil {
|
||||
addr6 = *(iface.AddressIPv6)
|
||||
}
|
||||
if err := epInfo.AddInterface(iface.ID, iface.MacAddress, addr4, addr6); err != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to AddInterface %v: %s", iface, err), d.DeleteEndpoint(nid, eid))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func errorWithRollback(msg string, err error) error {
|
||||
rollback := "rolled back"
|
||||
if err != nil {
|
||||
rollback = "failed to roll back: " + err.Error()
|
||||
}
|
||||
return fmt.Errorf("%s; %s", msg, rollback)
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
delete := &deleteEndpointRequest{
|
||||
NetworkID: string(nid),
|
||||
EndpointID: string(eid),
|
||||
}
|
||||
return d.call("DeleteEndpoint", delete, &deleteEndpointResponse{})
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{}, error) {
|
||||
return nil, driverapi.ErrNotImplemented
|
||||
info := &endpointInfoRequest{
|
||||
NetworkID: string(nid),
|
||||
EndpointID: string(eid),
|
||||
}
|
||||
var res endpointInfoResponse
|
||||
if err := d.call("EndpointOperInfo", info, &res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Value, nil
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
join := &joinRequest{
|
||||
NetworkID: string(nid),
|
||||
EndpointID: string(eid),
|
||||
SandboxKey: sboxKey,
|
||||
Options: options,
|
||||
}
|
||||
var (
|
||||
res joinResponse
|
||||
err error
|
||||
)
|
||||
if err = d.call("Join", join, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Expect each interface ID given by CreateEndpoint to have an
|
||||
// entry at that index in the names supplied here. In other words,
|
||||
// if you supply 0..n interfaces with IDs 0..n above, you should
|
||||
// supply the names in the same order.
|
||||
ifaceNames := res.InterfaceNames
|
||||
for _, iface := range jinfo.InterfaceNames() {
|
||||
i := iface.ID()
|
||||
if i >= len(ifaceNames) || i < 0 {
|
||||
return fmt.Errorf("no correlating interface %d in supplied interface names", i)
|
||||
}
|
||||
supplied := ifaceNames[i]
|
||||
if err := iface.SetNames(supplied.SrcName, supplied.DstName); err != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set interface name: %s", err), d.Leave(nid, eid))
|
||||
}
|
||||
}
|
||||
|
||||
var addr net.IP
|
||||
if res.Gateway != "" {
|
||||
if addr = net.ParseIP(res.Gateway); addr == nil {
|
||||
return fmt.Errorf(`unable to parse Gateway "%s"`, res.Gateway)
|
||||
}
|
||||
if jinfo.SetGateway(addr) != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set gateway: %v", addr), d.Leave(nid, eid))
|
||||
}
|
||||
}
|
||||
if res.GatewayIPv6 != "" {
|
||||
if addr = net.ParseIP(res.GatewayIPv6); addr == nil {
|
||||
return fmt.Errorf(`unable to parse GatewayIPv6 "%s"`, res.GatewayIPv6)
|
||||
}
|
||||
if jinfo.SetGatewayIPv6(addr) != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set gateway IPv6: %v", addr), d.Leave(nid, eid))
|
||||
}
|
||||
}
|
||||
if jinfo.SetHostsPath(res.HostsPath) != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set hosts path: %s", res.HostsPath), d.Leave(nid, eid))
|
||||
}
|
||||
if jinfo.SetResolvConfPath(res.ResolvConfPath) != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set resolv.conf path: %s", res.ResolvConfPath), d.Leave(nid, eid))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid types.UUID) error {
|
||||
return driverapi.ErrNotImplemented
|
||||
leave := &leaveRequest{
|
||||
NetworkID: string(nid),
|
||||
EndpointID: string(eid),
|
||||
}
|
||||
return d.call("Leave", leave, &leaveResponse{})
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
|
|
397
vendor/src/github.com/docker/libnetwork/drivers/remote/driver_test.go
vendored
Normal file
397
vendor/src/github.com/docker/libnetwork/drivers/remote/driver_test.go
vendored
Normal file
|
@ -0,0 +1,397 @@
|
|||
package remote
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
_ "github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
func decodeToMap(r *http.Request) (res map[string]interface{}, err error) {
|
||||
err = json.NewDecoder(r.Body).Decode(&res)
|
||||
return
|
||||
}
|
||||
|
||||
func handle(t *testing.T, mux *http.ServeMux, method string, h func(map[string]interface{}) interface{}) {
|
||||
mux.HandleFunc(fmt.Sprintf("/%s.%s", driverapi.NetworkPluginEndpointType, method), func(w http.ResponseWriter, r *http.Request) {
|
||||
ask, err := decodeToMap(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
answer := h(ask)
|
||||
err = json.NewEncoder(w).Encode(&answer)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func setupPlugin(t *testing.T, name string, mux *http.ServeMux) func() {
|
||||
if err := os.MkdirAll("/usr/share/docker/plugins", 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
listener, err := net.Listen("unix", fmt.Sprintf("/usr/share/docker/plugins/%s.sock", name))
|
||||
if err != nil {
|
||||
t.Fatal("Could not listen to the plugin socket")
|
||||
}
|
||||
|
||||
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, `{"Implements": ["%s"]}`, driverapi.NetworkPluginEndpointType)
|
||||
})
|
||||
|
||||
go http.Serve(listener, mux)
|
||||
|
||||
return func() {
|
||||
listener.Close()
|
||||
if err := os.RemoveAll("/usr/share/docker/plugins"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type testEndpoint struct {
|
||||
t *testing.T
|
||||
id int
|
||||
src string
|
||||
dst string
|
||||
address string
|
||||
addressIPv6 string
|
||||
macAddress string
|
||||
gateway string
|
||||
gatewayIPv6 string
|
||||
resolvConfPath string
|
||||
hostsPath string
|
||||
}
|
||||
|
||||
func (test *testEndpoint) Interfaces() []driverapi.InterfaceInfo {
|
||||
// return an empty one so we don't trip the check for existing
|
||||
// interfaces; we don't care about this after that
|
||||
return []driverapi.InterfaceInfo{}
|
||||
}
|
||||
|
||||
func (test *testEndpoint) AddInterface(ID int, mac net.HardwareAddr, ipv4 net.IPNet, ipv6 net.IPNet) error {
|
||||
if ID != test.id {
|
||||
test.t.Fatalf("Wrong ID passed to AddInterface: %d", ID)
|
||||
}
|
||||
ip4, net4, _ := net.ParseCIDR(test.address)
|
||||
ip6, net6, _ := net.ParseCIDR(test.addressIPv6)
|
||||
if ip4 != nil {
|
||||
net4.IP = ip4
|
||||
if !types.CompareIPNet(net4, &ipv4) {
|
||||
test.t.Fatalf("Wrong address given %+v", ipv4)
|
||||
}
|
||||
}
|
||||
if ip6 != nil {
|
||||
net6.IP = ip6
|
||||
if !types.CompareIPNet(net6, &ipv6) {
|
||||
test.t.Fatalf("Wrong address (IPv6) given %+v", ipv6)
|
||||
}
|
||||
}
|
||||
if test.macAddress != "" && mac.String() != test.macAddress {
|
||||
test.t.Fatalf("Wrong MAC address given %v", mac)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (test *testEndpoint) InterfaceNames() []driverapi.InterfaceNameInfo {
|
||||
return []driverapi.InterfaceNameInfo{test}
|
||||
}
|
||||
|
||||
func compareIPs(t *testing.T, kind string, shouldBe string, supplied net.IP) {
|
||||
ip := net.ParseIP(shouldBe)
|
||||
if ip == nil {
|
||||
t.Fatalf(`Invalid IP to test against: "%s"`, shouldBe)
|
||||
}
|
||||
if !ip.Equal(supplied) {
|
||||
t.Fatalf(`%s IPs are not equal: expected "%s", got %v`, kind, shouldBe, supplied)
|
||||
}
|
||||
}
|
||||
|
||||
func (test *testEndpoint) SetGateway(ipv4 net.IP) error {
|
||||
compareIPs(test.t, "Gateway", test.gateway, ipv4)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (test *testEndpoint) SetGatewayIPv6(ipv6 net.IP) error {
|
||||
compareIPs(test.t, "GatewayIPv6", test.gatewayIPv6, ipv6)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (test *testEndpoint) SetHostsPath(p string) error {
|
||||
if p != test.hostsPath {
|
||||
test.t.Fatalf(`Wrong HostsPath; expected "%s", got "%s"`, test.hostsPath, p)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (test *testEndpoint) SetResolvConfPath(p string) error {
|
||||
if p != test.resolvConfPath {
|
||||
test.t.Fatalf(`Wrong ResolvConfPath; expected "%s", got "%s"`, test.resolvConfPath, p)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (test *testEndpoint) SetNames(src string, dst string) error {
|
||||
if test.src != src {
|
||||
test.t.Fatalf(`Wrong SrcName; expected "%s", got "%s"`, test.src, src)
|
||||
}
|
||||
if test.dst != dst {
|
||||
test.t.Fatalf(`Wrong DstName; expected "%s", got "%s"`, test.dst, dst)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (test *testEndpoint) ID() int {
|
||||
return test.id
|
||||
}
|
||||
|
||||
func TestRemoteDriver(t *testing.T) {
|
||||
var plugin = "test-net-driver"
|
||||
|
||||
ep := &testEndpoint{
|
||||
t: t,
|
||||
src: "vethsrc",
|
||||
dst: "vethdst",
|
||||
address: "192.168.5.7/16",
|
||||
addressIPv6: "2001:DB8::5:7/48",
|
||||
macAddress: "7a:56:78:34:12:da",
|
||||
gateway: "192.168.0.1",
|
||||
gatewayIPv6: "2001:DB8::1",
|
||||
hostsPath: "/here/comes/the/host/path",
|
||||
resolvConfPath: "/there/goes/the/resolv/conf",
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
defer setupPlugin(t, plugin, mux)()
|
||||
|
||||
var networkID string
|
||||
|
||||
handle(t, mux, "CreateNetwork", func(msg map[string]interface{}) interface{} {
|
||||
nid := msg["NetworkID"]
|
||||
var ok bool
|
||||
if networkID, ok = nid.(string); !ok {
|
||||
t.Fatal("RPC did not include network ID string")
|
||||
}
|
||||
return map[string]interface{}{}
|
||||
})
|
||||
handle(t, mux, "DeleteNetwork", func(msg map[string]interface{}) interface{} {
|
||||
if nid, ok := msg["NetworkID"]; !ok || nid != networkID {
|
||||
t.Fatal("Network ID missing or does not match that created")
|
||||
}
|
||||
return map[string]interface{}{}
|
||||
})
|
||||
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
||||
iface := map[string]interface{}{
|
||||
"ID": ep.id,
|
||||
"Address": ep.address,
|
||||
"AddressIPv6": ep.addressIPv6,
|
||||
"MacAddress": ep.macAddress,
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"Interfaces": []interface{}{iface},
|
||||
}
|
||||
})
|
||||
handle(t, mux, "Join", func(msg map[string]interface{}) interface{} {
|
||||
options := msg["Options"].(map[string]interface{})
|
||||
foo, ok := options["foo"].(string)
|
||||
if !ok || foo != "fooValue" {
|
||||
t.Fatalf("Did not receive expected foo string in request options: %+v", msg)
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"Gateway": ep.gateway,
|
||||
"GatewayIPv6": ep.gatewayIPv6,
|
||||
"HostsPath": ep.hostsPath,
|
||||
"ResolvConfPath": ep.resolvConfPath,
|
||||
"InterfaceNames": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"SrcName": ep.src,
|
||||
"DstName": ep.dst,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
handle(t, mux, "Leave", func(msg map[string]interface{}) interface{} {
|
||||
return map[string]string{}
|
||||
})
|
||||
handle(t, mux, "DeleteEndpoint", func(msg map[string]interface{}) interface{} {
|
||||
return map[string]interface{}{}
|
||||
})
|
||||
handle(t, mux, "EndpointOperInfo", func(msg map[string]interface{}) interface{} {
|
||||
return map[string]interface{}{
|
||||
"Value": map[string]string{
|
||||
"Arbitrary": "key",
|
||||
"Value": "pairs?",
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
driver := newDriver(plugin, p.Client)
|
||||
if driver.Type() != plugin {
|
||||
t.Fatal("Driver type does not match that given")
|
||||
}
|
||||
|
||||
netID := types.UUID("dummy-network")
|
||||
err = driver.CreateNetwork(netID, map[string]interface{}{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
endID := types.UUID("dummy-endpoint")
|
||||
err = driver.CreateEndpoint(netID, endID, ep, map[string]interface{}{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
joinOpts := map[string]interface{}{"foo": "fooValue"}
|
||||
err = driver.Join(netID, endID, "sandbox-key", ep, joinOpts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = driver.EndpointOperInfo(netID, endID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = driver.Leave(netID, endID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = driver.DeleteEndpoint(netID, endID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = driver.DeleteNetwork(netID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
type failEndpoint struct {
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
func (f *failEndpoint) Interfaces() []*driverapi.InterfaceInfo {
|
||||
f.t.Fatal("Unexpected call of Interfaces")
|
||||
return nil
|
||||
}
|
||||
func (f *failEndpoint) AddInterface(int, net.HardwareAddr, net.IPNet, net.IPNet) error {
|
||||
f.t.Fatal("Unexpected call of AddInterface")
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestDriverError(t *testing.T) {
|
||||
var plugin = "test-net-driver-error"
|
||||
|
||||
mux := http.NewServeMux()
|
||||
defer setupPlugin(t, plugin, mux)()
|
||||
|
||||
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
||||
return map[string]interface{}{
|
||||
"Err": "this should get raised as an error",
|
||||
}
|
||||
})
|
||||
|
||||
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
driver := newDriver(plugin, p.Client)
|
||||
|
||||
if err := driver.CreateEndpoint(types.UUID("dummy"), types.UUID("dummy"), &testEndpoint{t: t}, map[string]interface{}{}); err == nil {
|
||||
t.Fatalf("Expected error from driver")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingValues(t *testing.T) {
|
||||
var plugin = "test-net-driver-missing"
|
||||
|
||||
mux := http.NewServeMux()
|
||||
defer setupPlugin(t, plugin, mux)()
|
||||
|
||||
ep := &testEndpoint{
|
||||
t: t,
|
||||
id: 0,
|
||||
}
|
||||
|
||||
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
||||
iface := map[string]interface{}{
|
||||
"ID": ep.id,
|
||||
"Address": ep.address,
|
||||
"AddressIPv6": ep.addressIPv6,
|
||||
"MacAddress": ep.macAddress,
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"Interfaces": []interface{}{iface},
|
||||
}
|
||||
})
|
||||
|
||||
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
driver := newDriver(plugin, p.Client)
|
||||
|
||||
if err := driver.CreateEndpoint(types.UUID("dummy"), types.UUID("dummy"), ep, map[string]interface{}{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
type rollbackEndpoint struct {
|
||||
}
|
||||
|
||||
func (r *rollbackEndpoint) Interfaces() []driverapi.InterfaceInfo {
|
||||
return []driverapi.InterfaceInfo{}
|
||||
}
|
||||
|
||||
func (r *rollbackEndpoint) AddInterface(_ int, _ net.HardwareAddr, _ net.IPNet, _ net.IPNet) error {
|
||||
return fmt.Errorf("fail this to trigger a rollback")
|
||||
}
|
||||
|
||||
func TestRollback(t *testing.T) {
|
||||
var plugin = "test-net-driver-rollback"
|
||||
|
||||
mux := http.NewServeMux()
|
||||
defer setupPlugin(t, plugin, mux)()
|
||||
|
||||
rolledback := false
|
||||
|
||||
handle(t, mux, "CreateEndpoint", func(msg map[string]interface{}) interface{} {
|
||||
iface := map[string]interface{}{
|
||||
"ID": 0,
|
||||
"Address": "192.168.4.5/16",
|
||||
"AddressIPv6": "",
|
||||
"MacAddress": "7a:12:34:56:78:90",
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"Interfaces": []interface{}{iface},
|
||||
}
|
||||
})
|
||||
handle(t, mux, "DeleteEndpoint", func(msg map[string]interface{}) interface{} {
|
||||
rolledback = true
|
||||
return map[string]interface{}{}
|
||||
})
|
||||
|
||||
p, err := plugins.Get(plugin, driverapi.NetworkPluginEndpointType)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
driver := newDriver(plugin, p.Client)
|
||||
|
||||
ep := &rollbackEndpoint{}
|
||||
|
||||
if err := driver.CreateEndpoint(types.UUID("dummy"), types.UUID("dummy"), ep, map[string]interface{}{}); err == nil {
|
||||
t.Fatalf("Expected error from driver")
|
||||
}
|
||||
if !rolledback {
|
||||
t.Fatalf("Expected to have had DeleteEndpoint called")
|
||||
}
|
||||
}
|
143
vendor/src/github.com/docker/libnetwork/drivers/remote/messages.go
vendored
Normal file
143
vendor/src/github.com/docker/libnetwork/drivers/remote/messages.go
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
package remote
|
||||
|
||||
import "net"
|
||||
|
||||
type response struct {
|
||||
Err string
|
||||
}
|
||||
|
||||
type maybeError interface {
|
||||
getError() string
|
||||
}
|
||||
|
||||
func (r *response) getError() string {
|
||||
return r.Err
|
||||
}
|
||||
|
||||
type createNetworkRequest struct {
|
||||
NetworkID string
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
type createNetworkResponse struct {
|
||||
response
|
||||
}
|
||||
|
||||
type deleteNetworkRequest struct {
|
||||
NetworkID string
|
||||
}
|
||||
|
||||
type deleteNetworkResponse struct {
|
||||
response
|
||||
}
|
||||
|
||||
type createEndpointRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
Interfaces []*endpointInterface
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
type endpointInterface struct {
|
||||
ID int
|
||||
Address string
|
||||
AddressIPv6 string
|
||||
MacAddress string
|
||||
}
|
||||
|
||||
type createEndpointResponse struct {
|
||||
response
|
||||
Interfaces []*endpointInterface
|
||||
}
|
||||
|
||||
func toAddr(ipAddr string) (*net.IPNet, error) {
|
||||
ip, ipnet, err := net.ParseCIDR(ipAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipnet.IP = ip
|
||||
return ipnet, nil
|
||||
}
|
||||
|
||||
type iface struct {
|
||||
ID int
|
||||
Address *net.IPNet
|
||||
AddressIPv6 *net.IPNet
|
||||
MacAddress net.HardwareAddr
|
||||
}
|
||||
|
||||
func (r *createEndpointResponse) parseInterfaces() ([]*iface, error) {
|
||||
var (
|
||||
ifaces = make([]*iface, len(r.Interfaces))
|
||||
)
|
||||
for i, inIf := range r.Interfaces {
|
||||
var err error
|
||||
outIf := &iface{ID: inIf.ID}
|
||||
if inIf.Address != "" {
|
||||
if outIf.Address, err = toAddr(inIf.Address); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if inIf.AddressIPv6 != "" {
|
||||
if outIf.AddressIPv6, err = toAddr(inIf.AddressIPv6); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if inIf.MacAddress != "" {
|
||||
if outIf.MacAddress, err = net.ParseMAC(inIf.MacAddress); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ifaces[i] = outIf
|
||||
}
|
||||
return ifaces, nil
|
||||
}
|
||||
|
||||
type deleteEndpointRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
type deleteEndpointResponse struct {
|
||||
response
|
||||
}
|
||||
|
||||
type endpointInfoRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
type endpointInfoResponse struct {
|
||||
response
|
||||
Value map[string]interface{}
|
||||
}
|
||||
|
||||
type joinRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
SandboxKey string
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
type ifaceName struct {
|
||||
SrcName string
|
||||
DstName string
|
||||
}
|
||||
|
||||
type joinResponse struct {
|
||||
response
|
||||
InterfaceNames []*ifaceName
|
||||
Gateway string
|
||||
GatewayIPv6 string
|
||||
HostsPath string
|
||||
ResolvConfPath string
|
||||
}
|
||||
|
||||
type leaveRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
type leaveResponse struct {
|
||||
response
|
||||
}
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/libnetwork/etchosts"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/resolvconf"
|
||||
"github.com/docker/libnetwork/sandbox"
|
||||
"github.com/docker/libnetwork/types"
|
||||
|
@ -106,7 +105,7 @@ type endpoint struct {
|
|||
iFaces []*endpointInterface
|
||||
joinInfo *endpointJoinInfo
|
||||
container *containerInfo
|
||||
exposedPorts []netutils.TransportPort
|
||||
exposedPorts []types.TransportPort
|
||||
generic map[string]interface{}
|
||||
joinLeaveDone chan struct{}
|
||||
sync.Mutex
|
||||
|
@ -217,7 +216,7 @@ func (ep *endpoint) Join(containerID string, options ...EndpointOption) (*Contai
|
|||
ep.Lock()
|
||||
if ep.container != nil {
|
||||
ep.Unlock()
|
||||
return nil, ErrInvalidJoin
|
||||
return nil, ErrInvalidJoin{}
|
||||
}
|
||||
|
||||
ep.container = &containerInfo{
|
||||
|
@ -292,7 +291,7 @@ func (ep *endpoint) Join(containerID string, options ...EndpointOption) (*Contai
|
|||
for _, i := range ifaces {
|
||||
iface := &sandbox.Interface{
|
||||
SrcName: i.srcName,
|
||||
DstName: i.dstName,
|
||||
DstName: i.dstPrefix,
|
||||
Address: &i.addr,
|
||||
}
|
||||
if i.addrv6.IP.To16() != nil {
|
||||
|
@ -335,7 +334,7 @@ func (ep *endpoint) Leave(containerID string, options ...EndpointOption) error {
|
|||
if container == nil || container.id == "" ||
|
||||
containerID == "" || container.id != containerID {
|
||||
if container == nil {
|
||||
err = ErrNoContainer
|
||||
err = ErrNoContainer{}
|
||||
} else {
|
||||
err = InvalidContainerIDError(containerID)
|
||||
}
|
||||
|
@ -413,7 +412,7 @@ func (ep *endpoint) buildHostsFiles() error {
|
|||
ep.Unlock()
|
||||
|
||||
if container == nil {
|
||||
return ErrNoContainer
|
||||
return ErrNoContainer{}
|
||||
}
|
||||
|
||||
if container.config.hostsPath == "" {
|
||||
|
@ -463,7 +462,7 @@ func (ep *endpoint) updateParentHosts() error {
|
|||
ep.Unlock()
|
||||
|
||||
if container == nil {
|
||||
return ErrNoContainer
|
||||
return ErrNoContainer{}
|
||||
}
|
||||
|
||||
for _, update := range container.config.parentUpdates {
|
||||
|
@ -496,7 +495,7 @@ func (ep *endpoint) updateDNS(resolvConf []byte) error {
|
|||
ep.Unlock()
|
||||
|
||||
if container == nil {
|
||||
return ErrNoContainer
|
||||
return ErrNoContainer{}
|
||||
}
|
||||
|
||||
oldHash := []byte{}
|
||||
|
@ -574,7 +573,7 @@ func (ep *endpoint) setupDNS() error {
|
|||
ep.Unlock()
|
||||
|
||||
if container == nil {
|
||||
return ErrNoContainer
|
||||
return ErrNoContainer{}
|
||||
}
|
||||
|
||||
if container.config.resolvConfPath == "" {
|
||||
|
@ -697,10 +696,10 @@ func JoinOptionUseDefaultSandbox() EndpointOption {
|
|||
|
||||
// CreateOptionExposedPorts function returns an option setter for the container exposed
|
||||
// ports option to be passed to network.CreateEndpoint() method.
|
||||
func CreateOptionExposedPorts(exposedPorts []netutils.TransportPort) EndpointOption {
|
||||
func CreateOptionExposedPorts(exposedPorts []types.TransportPort) EndpointOption {
|
||||
return func(ep *endpoint) {
|
||||
// Defensive copy
|
||||
eps := make([]netutils.TransportPort, len(exposedPorts))
|
||||
eps := make([]types.TransportPort, len(exposedPorts))
|
||||
copy(eps, exposedPorts)
|
||||
// Store endpoint label and in generic because driver needs it
|
||||
ep.exposedPorts = eps
|
||||
|
@ -710,10 +709,10 @@ func CreateOptionExposedPorts(exposedPorts []netutils.TransportPort) EndpointOpt
|
|||
|
||||
// CreateOptionPortMapping function returns an option setter for the mapping
|
||||
// ports option to be passed to network.CreateEndpoint() method.
|
||||
func CreateOptionPortMapping(portBindings []netutils.PortBinding) EndpointOption {
|
||||
func CreateOptionPortMapping(portBindings []types.PortBinding) EndpointOption {
|
||||
return func(ep *endpoint) {
|
||||
// Store a copy of the bindings as generic data to pass to the driver
|
||||
pbs := make([]netutils.PortBinding, len(portBindings))
|
||||
pbs := make([]types.PortBinding, len(portBindings))
|
||||
copy(pbs, portBindings)
|
||||
ep.generic[netlabel.PortMap] = pbs
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
// EndpointInfo provides an interface to retrieve network resources bound to the endpoint.
|
||||
|
@ -40,12 +40,12 @@ type InterfaceInfo interface {
|
|||
}
|
||||
|
||||
type endpointInterface struct {
|
||||
id int
|
||||
mac net.HardwareAddr
|
||||
addr net.IPNet
|
||||
addrv6 net.IPNet
|
||||
srcName string
|
||||
dstName string
|
||||
id int
|
||||
mac net.HardwareAddr
|
||||
addr net.IPNet
|
||||
addrv6 net.IPNet
|
||||
srcName string
|
||||
dstPrefix string
|
||||
}
|
||||
|
||||
type endpointJoinInfo struct {
|
||||
|
@ -105,10 +105,10 @@ func (ep *endpoint) AddInterface(id int, mac net.HardwareAddr, ipv4 net.IPNet, i
|
|||
|
||||
iface := &endpointInterface{
|
||||
id: id,
|
||||
addr: *netutils.GetIPNetCopy(&ipv4),
|
||||
addrv6: *netutils.GetIPNetCopy(&ipv6),
|
||||
addr: *types.GetIPNetCopy(&ipv4),
|
||||
addrv6: *types.GetIPNetCopy(&ipv6),
|
||||
}
|
||||
iface.mac = netutils.GetMacCopy(mac)
|
||||
iface.mac = types.GetMacCopy(mac)
|
||||
|
||||
ep.iFaces = append(ep.iFaces, iface)
|
||||
return nil
|
||||
|
@ -119,20 +119,20 @@ func (i *endpointInterface) ID() int {
|
|||
}
|
||||
|
||||
func (i *endpointInterface) MacAddress() net.HardwareAddr {
|
||||
return netutils.GetMacCopy(i.mac)
|
||||
return types.GetMacCopy(i.mac)
|
||||
}
|
||||
|
||||
func (i *endpointInterface) Address() net.IPNet {
|
||||
return (*netutils.GetIPNetCopy(&i.addr))
|
||||
return (*types.GetIPNetCopy(&i.addr))
|
||||
}
|
||||
|
||||
func (i *endpointInterface) AddressIPv6() net.IPNet {
|
||||
return (*netutils.GetIPNetCopy(&i.addrv6))
|
||||
return (*types.GetIPNetCopy(&i.addrv6))
|
||||
}
|
||||
|
||||
func (i *endpointInterface) SetNames(srcName string, dstName string) error {
|
||||
func (i *endpointInterface) SetNames(srcName string, dstPrefix string) error {
|
||||
i.srcName = srcName
|
||||
i.dstName = dstName
|
||||
i.dstPrefix = dstPrefix
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ func (ep *endpoint) Gateway() net.IP {
|
|||
return net.IP{}
|
||||
}
|
||||
|
||||
return netutils.GetIPCopy(ep.joinInfo.gw)
|
||||
return types.GetIPCopy(ep.joinInfo.gw)
|
||||
}
|
||||
|
||||
func (ep *endpoint) GatewayIPv6() net.IP {
|
||||
|
@ -179,14 +179,14 @@ func (ep *endpoint) GatewayIPv6() net.IP {
|
|||
return net.IP{}
|
||||
}
|
||||
|
||||
return netutils.GetIPCopy(ep.joinInfo.gw6)
|
||||
return types.GetIPCopy(ep.joinInfo.gw6)
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetGateway(gw net.IP) error {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
ep.joinInfo.gw = netutils.GetIPCopy(gw)
|
||||
ep.joinInfo.gw = types.GetIPCopy(gw)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ func (ep *endpoint) SetGatewayIPv6(gw6 net.IP) error {
|
|||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
ep.joinInfo.gw6 = netutils.GetIPCopy(gw6)
|
||||
ep.joinInfo.gw6 = types.GetIPCopy(gw6)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
124
vendor/src/github.com/docker/libnetwork/error.go
vendored
124
vendor/src/github.com/docker/libnetwork/error.go
vendored
|
@ -1,34 +1,83 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoSuchNetwork is returned when a network query finds no result
|
||||
ErrNoSuchNetwork = errors.New("network not found")
|
||||
// ErrNoSuchEndpoint is returned when a endpoint query finds no result
|
||||
ErrNoSuchEndpoint = errors.New("endpoint not found")
|
||||
// ErrNilNetworkDriver is returned if a nil network driver
|
||||
// is passed to NewNetwork api.
|
||||
ErrNilNetworkDriver = errors.New("nil NetworkDriver instance")
|
||||
// ErrInvalidNetworkDriver is returned if an invalid driver
|
||||
// instance is passed.
|
||||
ErrInvalidNetworkDriver = errors.New("invalid driver bound to network")
|
||||
// ErrInvalidJoin is returned if a join is attempted on an endpoint
|
||||
// which already has a container joined.
|
||||
ErrInvalidJoin = errors.New("a container has already joined the endpoint")
|
||||
// ErrNoContainer is returned when the endpoint has no container
|
||||
// attached to it.
|
||||
ErrNoContainer = errors.New("no container attached to the endpoint")
|
||||
// ErrInvalidID is returned when a query-by-id method is being invoked
|
||||
// with an empty id parameter
|
||||
ErrInvalidID = errors.New("invalid ID")
|
||||
// ErrInvalidName is returned when a query-by-name or resource create method is
|
||||
// invoked with an empty name parameter
|
||||
ErrInvalidName = errors.New("invalid Name")
|
||||
)
|
||||
// ErrNoSuchNetwork is returned when a network query finds no result
|
||||
type ErrNoSuchNetwork string
|
||||
|
||||
func (nsn ErrNoSuchNetwork) Error() string {
|
||||
return fmt.Sprintf("network %s not found", string(nsn))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (nsn ErrNoSuchNetwork) BadRequest() {}
|
||||
|
||||
// ErrNoSuchEndpoint is returned when a endpoint query finds no result
|
||||
type ErrNoSuchEndpoint string
|
||||
|
||||
func (nse ErrNoSuchEndpoint) Error() string {
|
||||
return fmt.Sprintf("endpoint %s not found", string(nse))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (nse ErrNoSuchEndpoint) BadRequest() {}
|
||||
|
||||
// ErrInvalidNetworkDriver is returned if an invalid driver
|
||||
// name is passed.
|
||||
type ErrInvalidNetworkDriver string
|
||||
|
||||
func (ind ErrInvalidNetworkDriver) Error() string {
|
||||
return fmt.Sprintf("invalid driver bound to network: %s", string(ind))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ind ErrInvalidNetworkDriver) BadRequest() {}
|
||||
|
||||
// ErrInvalidJoin is returned if a join is attempted on an endpoint
|
||||
// which already has a container joined.
|
||||
type ErrInvalidJoin struct{}
|
||||
|
||||
func (ij ErrInvalidJoin) Error() string {
|
||||
return "a container has already joined the endpoint"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ij ErrInvalidJoin) BadRequest() {}
|
||||
|
||||
// ErrNoContainer is returned when the endpoint has no container
|
||||
// attached to it.
|
||||
type ErrNoContainer struct{}
|
||||
|
||||
func (nc ErrNoContainer) Error() string {
|
||||
return "a container has already joined the endpoint"
|
||||
}
|
||||
|
||||
// Maskable denotes the type of this error
|
||||
func (nc ErrNoContainer) Maskable() {}
|
||||
|
||||
// ErrInvalidID is returned when a query-by-id method is being invoked
|
||||
// with an empty id parameter
|
||||
type ErrInvalidID string
|
||||
|
||||
func (ii ErrInvalidID) Error() string {
|
||||
return fmt.Sprintf("invalid id: %s", string(ii))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ii ErrInvalidID) BadRequest() {}
|
||||
|
||||
// ErrInvalidName is returned when a query-by-name or resource create method is
|
||||
// invoked with an empty name parameter
|
||||
type ErrInvalidName string
|
||||
|
||||
func (in ErrInvalidName) Error() string {
|
||||
return fmt.Sprintf("invalid name: %s", string(in))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (in ErrInvalidName) BadRequest() {}
|
||||
|
||||
// NetworkTypeError type is returned when the network type string is not
|
||||
// known to libnetwork.
|
||||
|
@ -38,13 +87,19 @@ func (nt NetworkTypeError) Error() string {
|
|||
return fmt.Sprintf("unknown driver %q", string(nt))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (nt NetworkTypeError) NotFound() {}
|
||||
|
||||
// NetworkNameError is returned when a network with the same name already exists.
|
||||
type NetworkNameError string
|
||||
|
||||
func (name NetworkNameError) Error() string {
|
||||
return fmt.Sprintf("network with name %s already exists", string(name))
|
||||
func (nnr NetworkNameError) Error() string {
|
||||
return fmt.Sprintf("network with name %s already exists", string(nnr))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (nnr NetworkNameError) Forbidden() {}
|
||||
|
||||
// UnknownNetworkError is returned when libnetwork could not find in it's database
|
||||
// a network with the same name and id.
|
||||
type UnknownNetworkError struct {
|
||||
|
@ -56,6 +111,9 @@ func (une *UnknownNetworkError) Error() string {
|
|||
return fmt.Sprintf("unknown network %s id %s", une.name, une.id)
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (une *UnknownNetworkError) NotFound() {}
|
||||
|
||||
// ActiveEndpointsError is returned when a network is deleted which has active
|
||||
// endpoints in it.
|
||||
type ActiveEndpointsError struct {
|
||||
|
@ -67,6 +125,9 @@ func (aee *ActiveEndpointsError) Error() string {
|
|||
return fmt.Sprintf("network with name %s id %s has active endpoints", aee.name, aee.id)
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (aee *ActiveEndpointsError) Forbidden() {}
|
||||
|
||||
// UnknownEndpointError is returned when libnetwork could not find in it's database
|
||||
// an endpoint with the same name and id.
|
||||
type UnknownEndpointError struct {
|
||||
|
@ -78,6 +139,9 @@ func (uee *UnknownEndpointError) Error() string {
|
|||
return fmt.Sprintf("unknown endpoint %s id %s", uee.name, uee.id)
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (uee *UnknownEndpointError) NotFound() {}
|
||||
|
||||
// ActiveContainerError is returned when an endpoint is deleted which has active
|
||||
// containers attached to it.
|
||||
type ActiveContainerError struct {
|
||||
|
@ -89,6 +153,9 @@ func (ace *ActiveContainerError) Error() string {
|
|||
return fmt.Sprintf("endpoint with name %s id %s has active containers", ace.name, ace.id)
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ace *ActiveContainerError) Forbidden() {}
|
||||
|
||||
// InvalidContainerIDError is returned when an invalid container id is passed
|
||||
// in Join/Leave
|
||||
type InvalidContainerIDError string
|
||||
|
@ -96,3 +163,6 @@ type InvalidContainerIDError string
|
|||
func (id InvalidContainerIDError) Error() string {
|
||||
return fmt.Sprintf("invalid container id %s", string(id))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (id InvalidContainerIDError) BadRequest() {}
|
||||
|
|
51
vendor/src/github.com/docker/libnetwork/errors_test.go
vendored
Normal file
51
vendor/src/github.com/docker/libnetwork/errors_test.go
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
func TestErrorInterfaces(t *testing.T) {
|
||||
|
||||
badRequestErrorList := []error{ErrInvalidID(""), ErrInvalidName(""), ErrInvalidJoin{}, ErrInvalidNetworkDriver(""), InvalidContainerIDError(""), ErrNoSuchNetwork(""), ErrNoSuchEndpoint("")}
|
||||
for _, err := range badRequestErrorList {
|
||||
switch u := err.(type) {
|
||||
case types.BadRequestError:
|
||||
return
|
||||
default:
|
||||
t.Fatalf("Failed to detect err %v is of type BadRequestError. Got type: %T", err, u)
|
||||
}
|
||||
}
|
||||
|
||||
maskableErrorList := []error{ErrNoContainer{}}
|
||||
for _, err := range maskableErrorList {
|
||||
switch u := err.(type) {
|
||||
case types.MaskableError:
|
||||
return
|
||||
default:
|
||||
t.Fatalf("Failed to detect err %v is of type MaskableError. Got type: %T", err, u)
|
||||
}
|
||||
}
|
||||
|
||||
notFoundErrorList := []error{NetworkTypeError(""), &UnknownNetworkError{}, &UnknownEndpointError{}}
|
||||
for _, err := range notFoundErrorList {
|
||||
switch u := err.(type) {
|
||||
case types.NotFoundError:
|
||||
return
|
||||
default:
|
||||
t.Fatalf("Failed to detect err %v is of type NotFoundError. Got type: %T", err, u)
|
||||
}
|
||||
}
|
||||
|
||||
forbiddenErrorList := []error{NetworkTypeError(""), &UnknownNetworkError{}, &UnknownEndpointError{}}
|
||||
for _, err := range forbiddenErrorList {
|
||||
switch u := err.(type) {
|
||||
case types.ForbiddenError:
|
||||
return
|
||||
default:
|
||||
t.Fatalf("Failed to detect err %v is of type ForbiddenError. Got type: %T", err, u)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -11,7 +11,7 @@ import (
|
|||
_ "github.com/docker/libnetwork/netutils"
|
||||
)
|
||||
|
||||
const chainName = "DOCKER-TEST"
|
||||
const chainName = "DOCKEREST"
|
||||
|
||||
var natChain *Chain
|
||||
var filterChain *Chain
|
||||
|
|
|
@ -22,6 +22,8 @@ import (
|
|||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
|
@ -65,11 +67,11 @@ func getEmptyGenericOption() map[string]interface{} {
|
|||
return genericOption
|
||||
}
|
||||
|
||||
func getPortMapping() []netutils.PortBinding {
|
||||
return []netutils.PortBinding{
|
||||
netutils.PortBinding{Proto: netutils.TCP, Port: uint16(230), HostPort: uint16(23000)},
|
||||
netutils.PortBinding{Proto: netutils.UDP, Port: uint16(200), HostPort: uint16(22000)},
|
||||
netutils.PortBinding{Proto: netutils.TCP, Port: uint16(120), HostPort: uint16(12000)},
|
||||
func getPortMapping() []types.PortBinding {
|
||||
return []types.PortBinding{
|
||||
types.PortBinding{Proto: types.TCP, Port: uint16(230), HostPort: uint16(23000)},
|
||||
types.PortBinding{Proto: types.UDP, Port: uint16(200), HostPort: uint16(22000)},
|
||||
types.PortBinding{Proto: types.TCP, Port: uint16(120), HostPort: uint16(12000)},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +247,7 @@ func TestBridge(t *testing.T) {
|
|||
if !ok {
|
||||
t.Fatalf("Could not find expected info in endpoint data")
|
||||
}
|
||||
pm, ok := pmd.([]netutils.PortBinding)
|
||||
pm, ok := pmd.([]types.PortBinding)
|
||||
if !ok {
|
||||
t.Fatalf("Unexpected format for port mapping in endpoint operational data")
|
||||
}
|
||||
|
@ -289,7 +291,7 @@ func TestNilRemoteDriver(t *testing.T) {
|
|||
t.Fatal("Expected to fail. But instead succeeded")
|
||||
}
|
||||
|
||||
if err != plugins.ErrNotFound {
|
||||
if _, ok := err.(types.NotFoundError); !ok {
|
||||
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -337,8 +339,9 @@ func TestNetworkName(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatal("Expected to fail. But instead succeeded")
|
||||
}
|
||||
if err != libnetwork.ErrInvalidName {
|
||||
t.Fatal("Expected to fail with ErrInvalidName error")
|
||||
|
||||
if _, ok := err.(libnetwork.ErrInvalidName); !ok {
|
||||
t.Fatalf("Expected to fail with ErrInvalidName error. Got %v", err)
|
||||
}
|
||||
|
||||
networkName := "testnetwork"
|
||||
|
@ -474,8 +477,8 @@ func TestUnknownEndpoint(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatal("Expected to fail. But instead succeeded")
|
||||
}
|
||||
if err != libnetwork.ErrInvalidName {
|
||||
t.Fatal("Expected to fail with ErrInvalidName error")
|
||||
if _, ok := err.(libnetwork.ErrInvalidName); !ok {
|
||||
t.Fatalf("Expected to fail with ErrInvalidName error. Actual error: %v", err)
|
||||
}
|
||||
|
||||
ep, err := network.CreateEndpoint("testep")
|
||||
|
@ -612,15 +615,15 @@ func TestControllerQuery(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatalf("NetworkByName() succeeded with invalid target name")
|
||||
}
|
||||
if err != libnetwork.ErrInvalidName {
|
||||
t.Fatalf("NetworkByName() failed with unexpected error: %v", err)
|
||||
if _, ok := err.(libnetwork.ErrInvalidName); !ok {
|
||||
t.Fatalf("Expected NetworkByName() to fail with ErrInvalidName error. Got: %v", err)
|
||||
}
|
||||
|
||||
_, err = controller.NetworkByID("")
|
||||
if err == nil {
|
||||
t.Fatalf("NetworkByID() succeeded with invalid target id")
|
||||
}
|
||||
if err != libnetwork.ErrInvalidID {
|
||||
if _, ok := err.(libnetwork.ErrInvalidID); !ok {
|
||||
t.Fatalf("NetworkByID() failed with unexpected error: %v", err)
|
||||
}
|
||||
|
||||
|
@ -628,7 +631,7 @@ func TestControllerQuery(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatalf("Unexpected success for NetworkByID(): %v", g)
|
||||
}
|
||||
if err != libnetwork.ErrNoSuchNetwork {
|
||||
if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
|
||||
t.Fatalf("NetworkByID() failed with unexpected error: %v", err)
|
||||
}
|
||||
|
||||
|
@ -694,15 +697,15 @@ func TestNetworkQuery(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatalf("EndpointByName() succeeded with invalid target name")
|
||||
}
|
||||
if err != libnetwork.ErrInvalidName {
|
||||
t.Fatalf("EndpointByName() failed with unexpected error: %v", err)
|
||||
if _, ok := err.(libnetwork.ErrInvalidName); !ok {
|
||||
t.Fatalf("Expected EndpointByName() to fail with ErrInvalidName error. Got: %v", err)
|
||||
}
|
||||
|
||||
e, err = net1.EndpointByName("IamNotAnEndpoint")
|
||||
if err == nil {
|
||||
t.Fatalf("EndpointByName() succeeded with unknown target name")
|
||||
}
|
||||
if err != libnetwork.ErrNoSuchEndpoint {
|
||||
if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e != nil {
|
||||
|
@ -721,13 +724,42 @@ func TestNetworkQuery(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatalf("EndpointByID() succeeded with invalid target id")
|
||||
}
|
||||
if err != libnetwork.ErrInvalidID {
|
||||
if _, ok := err.(libnetwork.ErrInvalidID); !ok {
|
||||
t.Fatalf("EndpointByID() failed with unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
const containerID = "valid_container"
|
||||
|
||||
func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) {
|
||||
origns, err := netns.Get()
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get the current netns: %v", err)
|
||||
}
|
||||
defer origns.Close()
|
||||
|
||||
key := info.SandboxKey()
|
||||
f, err := os.OpenFile(key, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open network namespace path %q: %v", key, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
nsFD := f.Fd()
|
||||
if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
|
||||
t.Fatalf("Setting to the namespace pointed to by the sandbox %s failed: %v", key, err)
|
||||
}
|
||||
defer netns.Set(origns)
|
||||
|
||||
_, err = netlink.LinkByName("eth0")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not find the interface eth0 inside the sandbox: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEndpointJoin(t *testing.T) {
|
||||
if !netutils.IsRunningInContainer() {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
|
@ -784,6 +816,8 @@ func TestEndpointJoin(t *testing.T) {
|
|||
if info.SandboxKey() == "" {
|
||||
t.Fatalf("Expected an non-empty sandbox key for a joined endpoint. Instead found a empty sandbox key")
|
||||
}
|
||||
|
||||
checkSandbox(t, info)
|
||||
}
|
||||
|
||||
func TestEndpointJoinInvalidContainerId(t *testing.T) {
|
||||
|
@ -890,7 +924,7 @@ func TestEndpointMultipleJoins(t *testing.T) {
|
|||
t.Fatal("Expected to fail multiple joins for the same endpoint")
|
||||
}
|
||||
|
||||
if err != libnetwork.ErrInvalidJoin {
|
||||
if _, ok := err.(libnetwork.ErrInvalidJoin); !ok {
|
||||
t.Fatalf("Failed for unexpected reason: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -916,7 +950,7 @@ func TestEndpointInvalidLeave(t *testing.T) {
|
|||
}
|
||||
|
||||
if _, ok := err.(libnetwork.InvalidContainerIDError); !ok {
|
||||
if err != libnetwork.ErrNoContainer {
|
||||
if _, ok := err.(libnetwork.ErrNoContainer); !ok {
|
||||
t.Fatalf("Failed for unexpected reason: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -1275,6 +1309,10 @@ func TestValidRemoteDriver(t *testing.T) {
|
|||
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
|
||||
fmt.Fprintf(w, `{"Implements": ["%s"]}`, driverapi.NetworkPluginEndpointType)
|
||||
})
|
||||
mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
|
||||
fmt.Fprintf(w, "null")
|
||||
})
|
||||
|
||||
if err := os.MkdirAll("/usr/share/docker/plugins", 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -1296,7 +1334,7 @@ func TestValidRemoteDriver(t *testing.T) {
|
|||
|
||||
_, err = controller.NewNetwork("valid-network-driver", "dummy",
|
||||
libnetwork.NetworkOptionGeneric(getEmptyGenericOption()))
|
||||
if err != nil && err != driverapi.ErrNotImplemented {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -1370,8 +1408,10 @@ func parallelJoin(t *testing.T, ep libnetwork.Endpoint, thrNumber int) {
|
|||
_, err := ep.Join("racing_container")
|
||||
runtime.LockOSThread()
|
||||
if err != nil {
|
||||
if err != libnetwork.ErrNoContainer && err != libnetwork.ErrInvalidJoin {
|
||||
t.Fatal(err)
|
||||
if _, ok := err.(libnetwork.ErrNoContainer); !ok {
|
||||
if _, ok := err.(libnetwork.ErrInvalidJoin); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
debugf("JE%d(%v).", thrNumber, err)
|
||||
}
|
||||
|
@ -1383,8 +1423,10 @@ func parallelLeave(t *testing.T, ep libnetwork.Endpoint, thrNumber int) {
|
|||
err := ep.Leave("racing_container")
|
||||
runtime.LockOSThread()
|
||||
if err != nil {
|
||||
if err != libnetwork.ErrNoContainer && err != libnetwork.ErrInvalidJoin {
|
||||
t.Fatal(err)
|
||||
if _, ok := err.(libnetwork.ErrNoContainer); !ok {
|
||||
if _, ok := err.(libnetwork.ErrInvalidJoin); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
debugf("LE%d(%v).", thrNumber, err)
|
||||
}
|
||||
|
|
|
@ -3,14 +3,12 @@
|
|||
package netutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
@ -26,144 +24,6 @@ var (
|
|||
networkGetRoutesFct = netlink.RouteList
|
||||
)
|
||||
|
||||
// ErrInvalidProtocolBinding is returned when the port binding protocol is not valid.
|
||||
type ErrInvalidProtocolBinding string
|
||||
|
||||
func (ipb ErrInvalidProtocolBinding) Error() string {
|
||||
return fmt.Sprintf("invalid transport protocol: %s", string(ipb))
|
||||
}
|
||||
|
||||
// TransportPort represent a local Layer 4 endpoint
|
||||
type TransportPort struct {
|
||||
Proto Protocol
|
||||
Port uint16
|
||||
}
|
||||
|
||||
// GetCopy returns a copy of this TransportPort structure instance
|
||||
func (t *TransportPort) GetCopy() TransportPort {
|
||||
return TransportPort{Proto: t.Proto, Port: t.Port}
|
||||
}
|
||||
|
||||
// PortBinding represent a port binding between the container an the host
|
||||
type PortBinding struct {
|
||||
Proto Protocol
|
||||
IP net.IP
|
||||
Port uint16
|
||||
HostIP net.IP
|
||||
HostPort uint16
|
||||
}
|
||||
|
||||
// HostAddr returns the host side transport address
|
||||
func (p PortBinding) HostAddr() (net.Addr, error) {
|
||||
switch p.Proto {
|
||||
case UDP:
|
||||
return &net.UDPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
|
||||
case TCP:
|
||||
return &net.TCPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
|
||||
default:
|
||||
return nil, ErrInvalidProtocolBinding(p.Proto.String())
|
||||
}
|
||||
}
|
||||
|
||||
// ContainerAddr returns the container side transport address
|
||||
func (p PortBinding) ContainerAddr() (net.Addr, error) {
|
||||
switch p.Proto {
|
||||
case UDP:
|
||||
return &net.UDPAddr{IP: p.IP, Port: int(p.Port)}, nil
|
||||
case TCP:
|
||||
return &net.TCPAddr{IP: p.IP, Port: int(p.Port)}, nil
|
||||
default:
|
||||
return nil, ErrInvalidProtocolBinding(p.Proto.String())
|
||||
}
|
||||
}
|
||||
|
||||
// GetCopy returns a copy of this PortBinding structure instance
|
||||
func (p *PortBinding) GetCopy() PortBinding {
|
||||
return PortBinding{
|
||||
Proto: p.Proto,
|
||||
IP: GetIPCopy(p.IP),
|
||||
Port: p.Port,
|
||||
HostIP: GetIPCopy(p.HostIP),
|
||||
HostPort: p.HostPort,
|
||||
}
|
||||
}
|
||||
|
||||
// Equal checks if this instance of PortBinding is equal to the passed one
|
||||
func (p *PortBinding) Equal(o *PortBinding) bool {
|
||||
if p == o {
|
||||
return true
|
||||
}
|
||||
|
||||
if o == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.Proto != o.Proto || p.Port != o.Port || p.HostPort != o.HostPort {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.IP != nil {
|
||||
if !p.IP.Equal(o.IP) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if o.IP != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if p.HostIP != nil {
|
||||
if !p.HostIP.Equal(o.HostIP) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if o.HostIP != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const (
|
||||
// ICMP is for the ICMP ip protocol
|
||||
ICMP = 1
|
||||
// TCP is for the TCP ip protocol
|
||||
TCP = 6
|
||||
// UDP is for the UDP ip protocol
|
||||
UDP = 17
|
||||
)
|
||||
|
||||
// Protocol represents a IP protocol number
|
||||
type Protocol uint8
|
||||
|
||||
func (p Protocol) String() string {
|
||||
switch p {
|
||||
case ICMP:
|
||||
return "icmp"
|
||||
case TCP:
|
||||
return "tcp"
|
||||
case UDP:
|
||||
return "udp"
|
||||
default:
|
||||
return fmt.Sprintf("%d", p)
|
||||
}
|
||||
}
|
||||
|
||||
// ParseProtocol returns the respective Protocol type for the passed string
|
||||
func ParseProtocol(s string) Protocol {
|
||||
switch strings.ToLower(s) {
|
||||
case "icmp":
|
||||
return ICMP
|
||||
case "udp":
|
||||
return UDP
|
||||
case "tcp":
|
||||
return TCP
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// CheckNameserverOverlaps checks whether the passed network overlaps with any of the nameservers
|
||||
func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
|
||||
if len(nameservers) > 0 {
|
||||
|
@ -287,38 +147,3 @@ func GenerateRandomName(prefix string, size int) (string, error) {
|
|||
}
|
||||
return prefix + hex.EncodeToString(id)[:size], nil
|
||||
}
|
||||
|
||||
// GetMacCopy returns a copy of the passed MAC address
|
||||
func GetMacCopy(from net.HardwareAddr) net.HardwareAddr {
|
||||
to := make(net.HardwareAddr, len(from))
|
||||
copy(to, from)
|
||||
return to
|
||||
}
|
||||
|
||||
// GetIPCopy returns a copy of the passed IP address
|
||||
func GetIPCopy(from net.IP) net.IP {
|
||||
to := make(net.IP, len(from))
|
||||
copy(to, from)
|
||||
return to
|
||||
}
|
||||
|
||||
// GetIPNetCopy returns a copy of the passed IP Network
|
||||
func GetIPNetCopy(from *net.IPNet) *net.IPNet {
|
||||
if from == nil {
|
||||
return nil
|
||||
}
|
||||
bm := make(net.IPMask, len(from.Mask))
|
||||
copy(bm, from.Mask)
|
||||
return &net.IPNet{IP: GetIPCopy(from.IP), Mask: bm}
|
||||
}
|
||||
|
||||
// CompareIPNet returns equal if the two IP Networks are equal
|
||||
func CompareIPNet(a, b *net.IPNet) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
return a.IP.Equal(b.IP) && bytes.Equal(a.Mask, b.Mask)
|
||||
}
|
||||
|
|
|
@ -209,135 +209,3 @@ func TestUtilGenerateRandomMAC(t *testing.T) {
|
|||
t.Fatalf("mac1 %s should not equal mac2 %s", mac1, mac2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareIPNet(t *testing.T) {
|
||||
if CompareIPNet(nil, nil) == false {
|
||||
t.Fatalf("Failed to detect two nil net.IPNets are equal")
|
||||
}
|
||||
|
||||
_, net1, _ := net.ParseCIDR("192.168.30.22/24")
|
||||
if CompareIPNet(net1, net1) == false {
|
||||
t.Fatalf("Failed to detect same net.IPNet pointers equality")
|
||||
}
|
||||
|
||||
_, net2, _ := net.ParseCIDR("192.168.30.22/24")
|
||||
if CompareIPNet(net1, net2) == false {
|
||||
t.Fatalf("Failed to detect same net.IPNet object equality")
|
||||
}
|
||||
|
||||
_, net3, _ := net.ParseCIDR("192.168.30.33/24")
|
||||
if CompareIPNet(net1, net3) == false {
|
||||
t.Fatalf("Failed to detect semantically equivalent net.IPNets")
|
||||
}
|
||||
|
||||
_, net3, _ = net.ParseCIDR("192.168.31.33/24")
|
||||
if CompareIPNet(net2, net3) == true {
|
||||
t.Fatalf("Failed to detect different net.IPNets")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPCopyFunctions(t *testing.T) {
|
||||
ip := net.ParseIP("172.28.30.134")
|
||||
cp := GetIPCopy(ip)
|
||||
|
||||
if !ip.Equal(cp) {
|
||||
t.Fatalf("Failed to return a copy of net.IP")
|
||||
}
|
||||
|
||||
if &ip == &cp {
|
||||
t.Fatalf("Failed to return a true copy of net.IP")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetIPCopyFunctions(t *testing.T) {
|
||||
_, net, _ := net.ParseCIDR("192.168.30.23/24")
|
||||
cp := GetIPNetCopy(net)
|
||||
|
||||
if CompareIPNet(net, cp) == false {
|
||||
t.Fatalf("Failed to return a copy of net.IPNet")
|
||||
}
|
||||
|
||||
if net == cp {
|
||||
t.Fatalf("Failed to return a true copy of net.IPNet")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPortBindingEqual(t *testing.T) {
|
||||
pb1 := &PortBinding{
|
||||
Proto: TCP,
|
||||
IP: net.ParseIP("172.17.0.1"),
|
||||
Port: 80,
|
||||
HostIP: net.ParseIP("192.168.100.1"),
|
||||
HostPort: 8080,
|
||||
}
|
||||
|
||||
pb2 := &PortBinding{
|
||||
Proto: UDP,
|
||||
IP: net.ParseIP("172.17.0.1"),
|
||||
Port: 22,
|
||||
HostIP: net.ParseIP("192.168.100.1"),
|
||||
HostPort: 2222,
|
||||
}
|
||||
if !pb1.Equal(pb1) {
|
||||
t.Fatalf("PortBinding.Equal() returned false negative")
|
||||
}
|
||||
|
||||
if pb1.Equal(nil) {
|
||||
t.Fatalf("PortBinding.Equal() returned false negative")
|
||||
}
|
||||
|
||||
if pb1.Equal(pb2) {
|
||||
t.Fatalf("PortBinding.Equal() returned false positive")
|
||||
}
|
||||
|
||||
if pb1.Equal(pb2) != pb2.Equal(pb1) {
|
||||
t.Fatalf("PortBinding.Equal() failed commutative check")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPortBindingGetCopy(t *testing.T) {
|
||||
pb := &PortBinding{
|
||||
Proto: TCP,
|
||||
IP: net.ParseIP("172.17.0.1"),
|
||||
Port: 80,
|
||||
HostIP: net.ParseIP("192.168.100.1"),
|
||||
HostPort: 8080,
|
||||
}
|
||||
cp := pb.GetCopy()
|
||||
|
||||
if !pb.Equal(&cp) {
|
||||
t.Fatalf("Failed to return a copy of PortBinding")
|
||||
}
|
||||
|
||||
if pb == &cp {
|
||||
t.Fatalf("Failed to return a true copy of PortBinding")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPortBindingContainerAddr(t *testing.T) {
|
||||
pb := PortBinding{
|
||||
Proto: TCP,
|
||||
IP: net.ParseIP("172.17.0.1"),
|
||||
Port: 80,
|
||||
HostIP: net.ParseIP("192.168.100.1"),
|
||||
HostPort: 8080,
|
||||
}
|
||||
|
||||
container, err := pb.ContainerAddr()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
switch netAddr := container.(type) {
|
||||
case *net.TCPAddr:
|
||||
if !pb.IP.Equal(netAddr.IP) {
|
||||
t.Fatalf("PortBinding.ContainerAddr() Failed to return a ContainerAddr")
|
||||
}
|
||||
if int(pb.Port) != netAddr.Port {
|
||||
t.Fatalf("PortBinding.ContainerAddr() Failed to return a ContainerAddr")
|
||||
}
|
||||
case *net.UDPAddr:
|
||||
t.Fatalf("PortBinding.ContainerAddr() Failed to check correct proto")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ func (n *network) Delete() error {
|
|||
|
||||
func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) {
|
||||
if name == "" {
|
||||
return nil, ErrInvalidName
|
||||
return nil, ErrInvalidName(name)
|
||||
}
|
||||
ep := &endpoint{name: name, iFaces: []*endpointInterface{}, generic: make(map[string]interface{})}
|
||||
ep.id = types.UUID(stringid.GenerateRandomID())
|
||||
|
@ -173,7 +173,7 @@ func (n *network) WalkEndpoints(walker EndpointWalker) {
|
|||
|
||||
func (n *network) EndpointByName(name string) (Endpoint, error) {
|
||||
if name == "" {
|
||||
return nil, ErrInvalidName
|
||||
return nil, ErrInvalidName(name)
|
||||
}
|
||||
var e Endpoint
|
||||
|
||||
|
@ -188,7 +188,7 @@ func (n *network) EndpointByName(name string) (Endpoint, error) {
|
|||
n.WalkEndpoints(s)
|
||||
|
||||
if e == nil {
|
||||
return nil, ErrNoSuchEndpoint
|
||||
return nil, ErrNoSuchEndpoint(name)
|
||||
}
|
||||
|
||||
return e, nil
|
||||
|
@ -196,12 +196,12 @@ func (n *network) EndpointByName(name string) (Endpoint, error) {
|
|||
|
||||
func (n *network) EndpointByID(id string) (Endpoint, error) {
|
||||
if id == "" {
|
||||
return nil, ErrInvalidID
|
||||
return nil, ErrInvalidID(id)
|
||||
}
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
if e, ok := n.endpoints[types.UUID(id)]; ok {
|
||||
return e, nil
|
||||
}
|
||||
return nil, ErrNoSuchEndpoint
|
||||
return nil, ErrNoSuchEndpoint(id)
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@ func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int, usePr
|
|||
|
||||
if useProxy {
|
||||
m.userlandProxy = newProxy(proto, hostIP, allocatedHostPort, container.(*net.TCPAddr).IP, container.(*net.TCPAddr).Port)
|
||||
} else {
|
||||
m.userlandProxy = newDummyProxy(proto, hostIP, allocatedHostPort)
|
||||
}
|
||||
case *net.UDPAddr:
|
||||
proto = "udp"
|
||||
|
@ -99,6 +101,8 @@ func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int, usePr
|
|||
|
||||
if useProxy {
|
||||
m.userlandProxy = newProxy(proto, hostIP, allocatedHostPort, container.(*net.UDPAddr).IP, container.(*net.UDPAddr).Port)
|
||||
} else {
|
||||
m.userlandProxy = newDummyProxy(proto, hostIP, allocatedHostPort)
|
||||
}
|
||||
default:
|
||||
return nil, ErrUnknownBackendAddressType
|
||||
|
@ -123,9 +127,7 @@ func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int, usePr
|
|||
|
||||
cleanup := func() error {
|
||||
// need to undo the iptables rules before we return
|
||||
if m.userlandProxy != nil {
|
||||
m.userlandProxy.Stop()
|
||||
}
|
||||
m.userlandProxy.Stop()
|
||||
pm.forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
|
||||
if err := pm.Allocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
|
||||
return err
|
||||
|
@ -134,13 +136,11 @@ func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int, usePr
|
|||
return nil
|
||||
}
|
||||
|
||||
if m.userlandProxy != nil {
|
||||
if err := m.userlandProxy.Start(); err != nil {
|
||||
if err := cleanup(); err != nil {
|
||||
return nil, fmt.Errorf("Error during port allocation cleanup: %v", err)
|
||||
}
|
||||
return nil, err
|
||||
if err := m.userlandProxy.Start(); err != nil {
|
||||
if err := cleanup(); err != nil {
|
||||
return nil, fmt.Errorf("Error during port allocation cleanup: %v", err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pm.currentMappings[key] = m
|
||||
|
|
|
@ -2,20 +2,16 @@ package portmapper
|
|||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
_ "github.com/docker/libnetwork/netutils"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if reexec.Init() {
|
||||
return
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
func init() {
|
||||
// override this func to mock out the proxy server
|
||||
newProxy = newMockProxyCommand
|
||||
}
|
||||
|
||||
func TestSetIptablesChain(t *testing.T) {
|
||||
|
@ -37,7 +33,6 @@ func TestSetIptablesChain(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMapTCPPorts(t *testing.T) {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
pm := New()
|
||||
dstIP1 := net.ParseIP("192.168.0.1")
|
||||
dstIP2 := net.ParseIP("192.168.0.2")
|
||||
|
@ -117,7 +112,6 @@ func TestGetUDPIPAndPort(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMapUDPPorts(t *testing.T) {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
pm := New()
|
||||
dstIP1 := net.ParseIP("192.168.0.1")
|
||||
dstIP2 := net.ParseIP("192.168.0.2")
|
||||
|
@ -164,11 +158,6 @@ func TestMapUDPPorts(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMapAllPortsSingleInterface(t *testing.T) {
|
||||
newProxy = newMockProxyCommand
|
||||
defer func() {
|
||||
newProxy = newProxyCommand
|
||||
}()
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
pm := New()
|
||||
dstIP1 := net.ParseIP("0.0.0.0")
|
||||
srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")}
|
||||
|
@ -177,6 +166,12 @@ func TestMapAllPortsSingleInterface(t *testing.T) {
|
|||
var host net.Addr
|
||||
var err error
|
||||
|
||||
defer func() {
|
||||
for _, val := range hosts {
|
||||
pm.Unmap(val)
|
||||
}
|
||||
}()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
start, end := pm.Allocator.Begin, pm.Allocator.End
|
||||
for i := start; i < end; i++ {
|
||||
|
@ -201,27 +196,76 @@ func TestMapAllPortsSingleInterface(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestExecProxy(t *testing.T) {
|
||||
defer netutils.SetupTestNetNS(t)()
|
||||
args := []string{
|
||||
userlandProxyCommandName,
|
||||
"-proto", "tcp",
|
||||
"-host-ip", "0.0.0.0",
|
||||
"-host-port", "9999",
|
||||
"-container-ip", "172.168.1.1",
|
||||
"-container-port", "8888",
|
||||
}
|
||||
os.Args = args
|
||||
doneChan := make(chan bool)
|
||||
go func() {
|
||||
execProxy()
|
||||
doneChan <- true
|
||||
}()
|
||||
func TestMapTCPDummyListen(t *testing.T) {
|
||||
pm := New()
|
||||
dstIP := net.ParseIP("0.0.0.0")
|
||||
dstAddr := &net.TCPAddr{IP: dstIP, Port: 80}
|
||||
|
||||
select {
|
||||
case <-doneChan:
|
||||
t.Fatal("execProxy is not supposed to exit")
|
||||
case <-time.After(3 * time.Second):
|
||||
return
|
||||
// no-op for dummy
|
||||
srcAddr := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")}
|
||||
|
||||
addrEqual := func(addr1, addr2 net.Addr) bool {
|
||||
return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String())
|
||||
}
|
||||
|
||||
if host, err := pm.Map(srcAddr, dstIP, 80, false); err != nil {
|
||||
t.Fatalf("Failed to allocate port: %s", err)
|
||||
} else if !addrEqual(dstAddr, host) {
|
||||
t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s",
|
||||
dstAddr.String(), dstAddr.Network(), host.String(), host.Network())
|
||||
}
|
||||
if _, err := net.Listen("tcp", "0.0.0.0:80"); err == nil {
|
||||
t.Fatal("Listen on mapped port without proxy should fail")
|
||||
} else {
|
||||
if !strings.Contains(err.Error(), "address already in use") {
|
||||
t.Fatalf("Error should be about address already in use, got %v", err)
|
||||
}
|
||||
}
|
||||
if _, err := net.Listen("tcp", "0.0.0.0:81"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if host, err := pm.Map(srcAddr, dstIP, 81, false); err == nil {
|
||||
t.Fatalf("Bound port shouldn't be allocated, but it was on: %v", host)
|
||||
} else {
|
||||
if !strings.Contains(err.Error(), "address already in use") {
|
||||
t.Fatalf("Error should be about address already in use, got %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapUDPDummyListen(t *testing.T) {
|
||||
pm := New()
|
||||
dstIP := net.ParseIP("0.0.0.0")
|
||||
dstAddr := &net.UDPAddr{IP: dstIP, Port: 80}
|
||||
|
||||
// no-op for dummy
|
||||
srcAddr := &net.UDPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")}
|
||||
|
||||
addrEqual := func(addr1, addr2 net.Addr) bool {
|
||||
return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String())
|
||||
}
|
||||
|
||||
if host, err := pm.Map(srcAddr, dstIP, 80, false); err != nil {
|
||||
t.Fatalf("Failed to allocate port: %s", err)
|
||||
} else if !addrEqual(dstAddr, host) {
|
||||
t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s",
|
||||
dstAddr.String(), dstAddr.Network(), host.String(), host.Network())
|
||||
}
|
||||
if _, err := net.ListenUDP("udp", &net.UDPAddr{IP: dstIP, Port: 80}); err == nil {
|
||||
t.Fatal("Listen on mapped port without proxy should fail")
|
||||
} else {
|
||||
if !strings.Contains(err.Error(), "address already in use") {
|
||||
t.Fatalf("Error should be about address already in use, got %v", err)
|
||||
}
|
||||
}
|
||||
if _, err := net.ListenUDP("udp", &net.UDPAddr{IP: dstIP, Port: 81}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if host, err := pm.Map(srcAddr, dstIP, 81, false); err == nil {
|
||||
t.Fatalf("Bound port shouldn't be allocated, but it was on: %v", host)
|
||||
} else {
|
||||
if !strings.Contains(err.Error(), "address already in use") {
|
||||
t.Fatalf("Error should be about address already in use, got %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package portmapper
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
|
@ -159,3 +160,50 @@ func (p *proxyCommand) Stop() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// dummyProxy just listen on some port, it is needed to prevent accidental
|
||||
// port allocations on bound port, because without userland proxy we using
|
||||
// iptables rules and not net.Listen
|
||||
type dummyProxy struct {
|
||||
listener io.Closer
|
||||
addr net.Addr
|
||||
}
|
||||
|
||||
func newDummyProxy(proto string, hostIP net.IP, hostPort int) userlandProxy {
|
||||
switch proto {
|
||||
case "tcp":
|
||||
addr := &net.TCPAddr{IP: hostIP, Port: hostPort}
|
||||
return &dummyProxy{addr: addr}
|
||||
case "udp":
|
||||
addr := &net.UDPAddr{IP: hostIP, Port: hostPort}
|
||||
return &dummyProxy{addr: addr}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *dummyProxy) Start() error {
|
||||
switch addr := p.addr.(type) {
|
||||
case *net.TCPAddr:
|
||||
l, err := net.ListenTCP("tcp", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.listener = l
|
||||
case *net.UDPAddr:
|
||||
l, err := net.ListenUDP("udp", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.listener = l
|
||||
default:
|
||||
return fmt.Errorf("Unknown addr type: %T", p.addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *dummyProxy) Stop() error {
|
||||
if p.listener != nil {
|
||||
return p.listener.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -20,8 +20,10 @@ var once sync.Once
|
|||
// interface. It represents a linux network namespace, and moves an interface
|
||||
// into it when called on method AddInterface or sets the gateway etc.
|
||||
type networkNamespace struct {
|
||||
path string
|
||||
sinfo *Info
|
||||
path string
|
||||
sinfo *Info
|
||||
nextIfIndex int
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func createBasePath() {
|
||||
|
@ -167,6 +169,11 @@ func (n *networkNamespace) RemoveInterface(i *Interface) error {
|
|||
}
|
||||
|
||||
func (n *networkNamespace) AddInterface(i *Interface) error {
|
||||
n.Lock()
|
||||
i.DstName = fmt.Sprintf("%s%d", i.DstName, n.nextIfIndex)
|
||||
n.nextIfIndex++
|
||||
n.Unlock()
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
|
@ -214,7 +221,10 @@ func (n *networkNamespace) AddInterface(i *Interface) error {
|
|||
return err
|
||||
}
|
||||
|
||||
n.Lock()
|
||||
n.sinfo.Interfaces = append(n.sinfo.Interfaces, i)
|
||||
n.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package sandbox
|
|||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
// Sandbox represents a network sandbox, identified by a specific key. It
|
||||
|
@ -20,7 +20,9 @@ type Sandbox interface {
|
|||
|
||||
// Add an existing Interface to this sandbox. The operation will rename
|
||||
// from the Interface SrcName to DstName as it moves, and reconfigure the
|
||||
// interface according to the specified settings.
|
||||
// interface according to the specified settings. The caller is expected
|
||||
// to only provide a prefix for DstName. The AddInterface api will auto-generate
|
||||
// an appropriate suffix for the DstName to disambiguate.
|
||||
AddInterface(*Interface) error
|
||||
|
||||
// Remove an interface from the sandbox by renamin to original name
|
||||
|
@ -62,7 +64,9 @@ type Interface struct {
|
|||
SrcName string
|
||||
|
||||
// The name that will be assigned to the interface once moves inside a
|
||||
// network namespace.
|
||||
// network namespace. When the caller passes in a DstName, it is only
|
||||
// expected to pass a prefix. The name will modified with an appropriately
|
||||
// auto-generated suffix.
|
||||
DstName string
|
||||
|
||||
// IPv4 address for the interface.
|
||||
|
@ -77,8 +81,8 @@ func (i *Interface) GetCopy() *Interface {
|
|||
return &Interface{
|
||||
SrcName: i.SrcName,
|
||||
DstName: i.DstName,
|
||||
Address: netutils.GetIPNetCopy(i.Address),
|
||||
AddressIPv6: netutils.GetIPNetCopy(i.AddressIPv6),
|
||||
Address: types.GetIPNetCopy(i.Address),
|
||||
AddressIPv6: types.GetIPNetCopy(i.AddressIPv6),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,11 +100,11 @@ func (i *Interface) Equal(o *Interface) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if !netutils.CompareIPNet(i.Address, o.Address) {
|
||||
if !types.CompareIPNet(i.Address, o.Address) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !netutils.CompareIPNet(i.AddressIPv6, o.AddressIPv6) {
|
||||
if !types.CompareIPNet(i.AddressIPv6, o.AddressIPv6) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -113,8 +117,8 @@ func (s *Info) GetCopy() *Info {
|
|||
for i, iface := range s.Interfaces {
|
||||
list[i] = iface.GetCopy()
|
||||
}
|
||||
gw := netutils.GetIPCopy(s.Gateway)
|
||||
gw6 := netutils.GetIPCopy(s.GatewayIPv6)
|
||||
gw := types.GetIPCopy(s.Gateway)
|
||||
gw6 := types.GetIPCopy(s.GatewayIPv6)
|
||||
|
||||
return &Info{Interfaces: list, Gateway: gw, GatewayIPv6: gw6}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ import (
|
|||
const (
|
||||
vethName1 = "wierdlongname1"
|
||||
vethName2 = "wierdlongname2"
|
||||
vethName3 = "wierdlongname3"
|
||||
vethName4 = "wierdlongname4"
|
||||
sboxIfaceName = "containername"
|
||||
)
|
||||
|
||||
|
@ -36,33 +38,59 @@ func newInfo(t *testing.T) (*Info, error) {
|
|||
veth := &netlink.Veth{
|
||||
LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0},
|
||||
PeerName: vethName2}
|
||||
err := netlink.LinkAdd(veth)
|
||||
if err != nil {
|
||||
if err := netlink.LinkAdd(veth); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Store the sandbox side pipe interface
|
||||
// This is needed for cleanup on DeleteEndpoint()
|
||||
intf := &Interface{}
|
||||
intf.SrcName = vethName2
|
||||
intf.DstName = sboxIfaceName
|
||||
intf1 := &Interface{}
|
||||
intf1.SrcName = vethName2
|
||||
intf1.DstName = sboxIfaceName
|
||||
|
||||
ip4, addr, err := net.ParseCIDR("192.168.1.100/24")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
intf.Address = addr
|
||||
intf.Address.IP = ip4
|
||||
intf1.Address = addr
|
||||
intf1.Address.IP = ip4
|
||||
|
||||
// ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
|
||||
ip6, addrv6, err := net.ParseCIDR("fe80::2/64")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
intf.AddressIPv6 = addrv6
|
||||
intf.AddressIPv6.IP = ip6
|
||||
intf1.AddressIPv6 = addrv6
|
||||
intf1.AddressIPv6.IP = ip6
|
||||
|
||||
sinfo := &Info{Interfaces: []*Interface{intf}}
|
||||
veth = &netlink.Veth{
|
||||
LinkAttrs: netlink.LinkAttrs{Name: vethName3, TxQLen: 0},
|
||||
PeerName: vethName4}
|
||||
|
||||
if err := netlink.LinkAdd(veth); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
intf2 := &Interface{}
|
||||
intf2.SrcName = vethName4
|
||||
intf2.DstName = sboxIfaceName
|
||||
|
||||
ip4, addr, err = net.ParseCIDR("192.168.2.100/24")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
intf2.Address = addr
|
||||
intf2.Address.IP = ip4
|
||||
|
||||
// ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
|
||||
ip6, addrv6, err = net.ParseCIDR("fe80::3/64")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
intf2.AddressIPv6 = addrv6
|
||||
intf2.AddressIPv6.IP = ip6
|
||||
|
||||
sinfo := &Info{Interfaces: []*Interface{intf1, intf2}}
|
||||
sinfo.Gateway = net.ParseIP("192.168.1.1")
|
||||
// sinfo.GatewayIPv6 = net.ParseIP("2001:DB8::1")
|
||||
sinfo.GatewayIPv6 = net.ParseIP("fe80::1")
|
||||
|
@ -97,7 +125,13 @@ func verifySandbox(t *testing.T, s Sandbox) {
|
|||
}
|
||||
defer netns.Set(origns)
|
||||
|
||||
_, err = netlink.LinkByName(sboxIfaceName)
|
||||
_, err = netlink.LinkByName(sboxIfaceName + "0")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName,
|
||||
err)
|
||||
}
|
||||
|
||||
_, err = netlink.LinkByName(sboxIfaceName + "1")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName,
|
||||
err)
|
||||
|
|
|
@ -1,5 +1,345 @@
|
|||
// Package types contains types that are common across libnetwork project
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UUID represents a globally unique ID of various resources like network and endpoint
|
||||
type UUID string
|
||||
|
||||
// TransportPort represent a local Layer 4 endpoint
|
||||
type TransportPort struct {
|
||||
Proto Protocol
|
||||
Port uint16
|
||||
}
|
||||
|
||||
// GetCopy returns a copy of this TransportPort structure instance
|
||||
func (t *TransportPort) GetCopy() TransportPort {
|
||||
return TransportPort{Proto: t.Proto, Port: t.Port}
|
||||
}
|
||||
|
||||
// PortBinding represent a port binding between the container an the host
|
||||
type PortBinding struct {
|
||||
Proto Protocol
|
||||
IP net.IP
|
||||
Port uint16
|
||||
HostIP net.IP
|
||||
HostPort uint16
|
||||
}
|
||||
|
||||
// HostAddr returns the host side transport address
|
||||
func (p PortBinding) HostAddr() (net.Addr, error) {
|
||||
switch p.Proto {
|
||||
case UDP:
|
||||
return &net.UDPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
|
||||
case TCP:
|
||||
return &net.TCPAddr{IP: p.HostIP, Port: int(p.HostPort)}, nil
|
||||
default:
|
||||
return nil, ErrInvalidProtocolBinding(p.Proto.String())
|
||||
}
|
||||
}
|
||||
|
||||
// ContainerAddr returns the container side transport address
|
||||
func (p PortBinding) ContainerAddr() (net.Addr, error) {
|
||||
switch p.Proto {
|
||||
case UDP:
|
||||
return &net.UDPAddr{IP: p.IP, Port: int(p.Port)}, nil
|
||||
case TCP:
|
||||
return &net.TCPAddr{IP: p.IP, Port: int(p.Port)}, nil
|
||||
default:
|
||||
return nil, ErrInvalidProtocolBinding(p.Proto.String())
|
||||
}
|
||||
}
|
||||
|
||||
// GetCopy returns a copy of this PortBinding structure instance
|
||||
func (p *PortBinding) GetCopy() PortBinding {
|
||||
return PortBinding{
|
||||
Proto: p.Proto,
|
||||
IP: GetIPCopy(p.IP),
|
||||
Port: p.Port,
|
||||
HostIP: GetIPCopy(p.HostIP),
|
||||
HostPort: p.HostPort,
|
||||
}
|
||||
}
|
||||
|
||||
// Equal checks if this instance of PortBinding is equal to the passed one
|
||||
func (p *PortBinding) Equal(o *PortBinding) bool {
|
||||
if p == o {
|
||||
return true
|
||||
}
|
||||
|
||||
if o == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.Proto != o.Proto || p.Port != o.Port || p.HostPort != o.HostPort {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.IP != nil {
|
||||
if !p.IP.Equal(o.IP) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if o.IP != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if p.HostIP != nil {
|
||||
if !p.HostIP.Equal(o.HostIP) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if o.HostIP != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// ErrInvalidProtocolBinding is returned when the port binding protocol is not valid.
|
||||
type ErrInvalidProtocolBinding string
|
||||
|
||||
func (ipb ErrInvalidProtocolBinding) Error() string {
|
||||
return fmt.Sprintf("invalid transport protocol: %s", string(ipb))
|
||||
}
|
||||
|
||||
const (
|
||||
// ICMP is for the ICMP ip protocol
|
||||
ICMP = 1
|
||||
// TCP is for the TCP ip protocol
|
||||
TCP = 6
|
||||
// UDP is for the UDP ip protocol
|
||||
UDP = 17
|
||||
)
|
||||
|
||||
// Protocol represents a IP protocol number
|
||||
type Protocol uint8
|
||||
|
||||
func (p Protocol) String() string {
|
||||
switch p {
|
||||
case ICMP:
|
||||
return "icmp"
|
||||
case TCP:
|
||||
return "tcp"
|
||||
case UDP:
|
||||
return "udp"
|
||||
default:
|
||||
return fmt.Sprintf("%d", p)
|
||||
}
|
||||
}
|
||||
|
||||
// ParseProtocol returns the respective Protocol type for the passed string
|
||||
func ParseProtocol(s string) Protocol {
|
||||
switch strings.ToLower(s) {
|
||||
case "icmp":
|
||||
return ICMP
|
||||
case "udp":
|
||||
return UDP
|
||||
case "tcp":
|
||||
return TCP
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// GetMacCopy returns a copy of the passed MAC address
|
||||
func GetMacCopy(from net.HardwareAddr) net.HardwareAddr {
|
||||
to := make(net.HardwareAddr, len(from))
|
||||
copy(to, from)
|
||||
return to
|
||||
}
|
||||
|
||||
// GetIPCopy returns a copy of the passed IP address
|
||||
func GetIPCopy(from net.IP) net.IP {
|
||||
to := make(net.IP, len(from))
|
||||
copy(to, from)
|
||||
return to
|
||||
}
|
||||
|
||||
// GetIPNetCopy returns a copy of the passed IP Network
|
||||
func GetIPNetCopy(from *net.IPNet) *net.IPNet {
|
||||
if from == nil {
|
||||
return nil
|
||||
}
|
||||
bm := make(net.IPMask, len(from.Mask))
|
||||
copy(bm, from.Mask)
|
||||
return &net.IPNet{IP: GetIPCopy(from.IP), Mask: bm}
|
||||
}
|
||||
|
||||
// CompareIPNet returns equal if the two IP Networks are equal
|
||||
func CompareIPNet(a, b *net.IPNet) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
return a.IP.Equal(b.IP) && bytes.Equal(a.Mask, b.Mask)
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Well-known Error Interfaces
|
||||
******************************/
|
||||
|
||||
// MaskableError is an interface for errors which can be ignored by caller
|
||||
type MaskableError interface {
|
||||
// Maskable makes implementer into MaskableError type
|
||||
Maskable()
|
||||
}
|
||||
|
||||
// BadRequestError is an interface for errors originated by a bad request
|
||||
type BadRequestError interface {
|
||||
// BadRequest makes implementer into BadRequestError type
|
||||
BadRequest()
|
||||
}
|
||||
|
||||
// NotFoundError is an interface for errors raised because a needed resource is not available
|
||||
type NotFoundError interface {
|
||||
// NotFound makes implementer into NotFoundError type
|
||||
NotFound()
|
||||
}
|
||||
|
||||
// ForbiddenError is an interface for errors which denote an valid request that cannot be honored
|
||||
type ForbiddenError interface {
|
||||
// Forbidden makes implementer into ForbiddenError type
|
||||
Forbidden()
|
||||
}
|
||||
|
||||
// NoServiceError is an interface for errors returned when the required service is not available
|
||||
type NoServiceError interface {
|
||||
// NoService makes implementer into NoServiceError type
|
||||
NoService()
|
||||
}
|
||||
|
||||
// TimeoutError is an interface for errors raised because of timeout
|
||||
type TimeoutError interface {
|
||||
// Timeout makes implementer into TimeoutError type
|
||||
Timeout()
|
||||
}
|
||||
|
||||
// NotImplementedError is an interface for errors raised because of requested functionality is not yet implemented
|
||||
type NotImplementedError interface {
|
||||
// NotImplemented makes implementer into NotImplementedError type
|
||||
NotImplemented()
|
||||
}
|
||||
|
||||
// InternalError is an interface for errors raised because of an internal error
|
||||
type InternalError interface {
|
||||
// Internal makes implementer into InternalError type
|
||||
Internal()
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Weel-known Error Formatters
|
||||
******************************/
|
||||
|
||||
// BadRequestErrorf creates an instance of BadRequestError
|
||||
func BadRequestErrorf(format string, params ...interface{}) error {
|
||||
return badRequest(fmt.Sprintf(format, params...))
|
||||
}
|
||||
|
||||
// NotFoundErrorf creates an instance of NotFoundError
|
||||
func NotFoundErrorf(format string, params ...interface{}) error {
|
||||
return notFound(fmt.Sprintf(format, params...))
|
||||
}
|
||||
|
||||
// ForbiddenErrorf creates an instance of ForbiddenError
|
||||
func ForbiddenErrorf(format string, params ...interface{}) error {
|
||||
return forbidden(fmt.Sprintf(format, params...))
|
||||
}
|
||||
|
||||
// NoServiceErrorf creates an instance of NoServiceError
|
||||
func NoServiceErrorf(format string, params ...interface{}) error {
|
||||
return noService(fmt.Sprintf(format, params...))
|
||||
}
|
||||
|
||||
// NotImplementedErrorf creates an instance of NotImplementedError
|
||||
func NotImplementedErrorf(format string, params ...interface{}) error {
|
||||
return notImpl(fmt.Sprintf(format, params...))
|
||||
}
|
||||
|
||||
// TimeoutErrorf creates an instance of TimeoutError
|
||||
func TimeoutErrorf(format string, params ...interface{}) error {
|
||||
return timeout(fmt.Sprintf(format, params...))
|
||||
}
|
||||
|
||||
// InternalErrorf creates an instance of InternalError
|
||||
func InternalErrorf(format string, params ...interface{}) error {
|
||||
return internal(fmt.Sprintf(format, params...))
|
||||
}
|
||||
|
||||
// InternalMaskableErrorf creates an instance of InternalError and MaskableError
|
||||
func InternalMaskableErrorf(format string, params ...interface{}) error {
|
||||
return maskInternal(fmt.Sprintf(format, params...))
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Internal Error Types
|
||||
***********************/
|
||||
type badRequest string
|
||||
|
||||
func (br badRequest) Error() string {
|
||||
return string(br)
|
||||
}
|
||||
func (br badRequest) BadRequest() {}
|
||||
|
||||
type maskBadRequest string
|
||||
|
||||
type notFound string
|
||||
|
||||
func (nf notFound) Error() string {
|
||||
return string(nf)
|
||||
}
|
||||
func (nf notFound) NotFound() {}
|
||||
|
||||
type forbidden string
|
||||
|
||||
func (frb forbidden) Error() string {
|
||||
return string(frb)
|
||||
}
|
||||
func (frb forbidden) Forbidden() {}
|
||||
|
||||
type noService string
|
||||
|
||||
func (ns noService) Error() string {
|
||||
return string(ns)
|
||||
}
|
||||
func (ns noService) NoService() {}
|
||||
|
||||
type maskNoService string
|
||||
|
||||
type timeout string
|
||||
|
||||
func (to timeout) Error() string {
|
||||
return string(to)
|
||||
}
|
||||
func (to timeout) Timeout() {}
|
||||
|
||||
type notImpl string
|
||||
|
||||
func (ni notImpl) Error() string {
|
||||
return string(ni)
|
||||
}
|
||||
func (ni notImpl) NotImplemented() {}
|
||||
|
||||
type internal string
|
||||
|
||||
func (nt internal) Error() string {
|
||||
return string(nt)
|
||||
}
|
||||
func (nt internal) Internal() {}
|
||||
|
||||
type maskInternal string
|
||||
|
||||
func (mnt maskInternal) Error() string {
|
||||
return string(mnt)
|
||||
}
|
||||
func (mnt maskInternal) Internal() {}
|
||||
func (mnt maskInternal) Maskable() {}
|
||||
|
|
99
vendor/src/github.com/docker/libnetwork/types/types_test.go
vendored
Normal file
99
vendor/src/github.com/docker/libnetwork/types/types_test.go
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
_ "github.com/docker/libnetwork/netutils"
|
||||
)
|
||||
|
||||
func TestErrorConstructors(t *testing.T) {
|
||||
var err error
|
||||
|
||||
err = BadRequestErrorf("Io ho %d uccello", 1)
|
||||
if err.Error() != "Io ho 1 uccello" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(BadRequestError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(MaskableError); ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = NotFoundErrorf("Can't find the %s", "keys")
|
||||
if err.Error() != "Can't find the keys" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(NotFoundError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(MaskableError); ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ForbiddenErrorf("Can't open door %d", 2)
|
||||
if err.Error() != "Can't open door 2" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(ForbiddenError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(MaskableError); ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = NotImplementedErrorf("Functionality %s is not implemented", "x")
|
||||
if err.Error() != "Functionality x is not implemented" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(NotImplementedError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(MaskableError); ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = TimeoutErrorf("Process %s timed out", "abc")
|
||||
if err.Error() != "Process abc timed out" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(TimeoutError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(MaskableError); ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = NoServiceErrorf("Driver %s is not available", "mh")
|
||||
if err.Error() != "Driver mh is not available" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(NoServiceError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(MaskableError); ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = InternalErrorf("Not sure what happened")
|
||||
if err.Error() != "Not sure what happened" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(InternalError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(MaskableError); ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = InternalMaskableErrorf("Minor issue, it can be ignored")
|
||||
if err.Error() != "Minor issue, it can be ignored" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(InternalError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, ok := err.(MaskableError); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue