Network remote APIs using new router, --net=<user-defined-network> changes
* Moving Network Remote APIs out of experimental * --net can now accept user created networks using network drivers/plugins * Removed the experimental services concept and --default-network option * Neccessary backend changes to accomodate multiple networks per container * Integration Tests Signed-off-by: David Calavera <david.calavera@gmail.com> Signed-off-by: Madhu Venugopal <madhu@docker.com> Upstream-commit: 2ab94e11a2a8499088a72ab27fd09e897d8c810a Component: engine
This commit is contained in:
@ -1,26 +1,41 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/api/server/router/local"
|
||||
"github.com/docker/docker/daemon"
|
||||
)
|
||||
|
||||
// networkRouter is a router to talk with the network controller
|
||||
type networkRouter struct {
|
||||
daemon *daemon.Daemon
|
||||
routes []router.Route
|
||||
}
|
||||
|
||||
// NewRouter initializes a new network router
|
||||
func NewRouter(d *daemon.Daemon) router.Router {
|
||||
r := &networkRouter{
|
||||
daemon: d,
|
||||
}
|
||||
r.initRoutes()
|
||||
return r
|
||||
}
|
||||
|
||||
// Routes returns the available routes to the network controller
|
||||
func (n networkRouter) Routes() []router.Route {
|
||||
return n.routes
|
||||
func (r *networkRouter) Routes() []router.Route {
|
||||
return r.routes
|
||||
}
|
||||
|
||||
type networkRoute struct {
|
||||
path string
|
||||
handler httputils.APIFunc
|
||||
}
|
||||
|
||||
// Handler returns the APIFunc to let the server wrap it in middlewares
|
||||
func (l networkRoute) Handler() httputils.APIFunc {
|
||||
return l.handler
|
||||
func (r *networkRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
// GET
|
||||
local.NewGetRoute("/networks", r.getNetworksList),
|
||||
local.NewGetRoute("/networks/{id:.*}", r.getNetwork),
|
||||
// POST
|
||||
local.NewPostRoute("/networks/create", r.postNetworkCreate),
|
||||
local.NewPostRoute("/networks/{id:.*}/connect", r.postNetworkConnect),
|
||||
local.NewPostRoute("/networks/{id:.*}/disconnect", r.postNetworkDisconnect),
|
||||
// DELETE
|
||||
local.NewDeleteRoute("/networks/{id:.*}", r.deleteNetwork),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
// +build experimental
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/libnetwork/api"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var httpMethods = []string{"GET", "POST", "PUT", "DELETE"}
|
||||
|
||||
// NewRouter initializes a new network router
|
||||
func NewRouter(d *daemon.Daemon) router.Router {
|
||||
c := d.NetworkController()
|
||||
if c == nil {
|
||||
return networkRouter{}
|
||||
}
|
||||
|
||||
var routes []router.Route
|
||||
netHandler := api.NewHTTPHandler(c)
|
||||
|
||||
// TODO: libnetwork should stop hijacking request/response.
|
||||
// It should define API functions to add normally to the router.
|
||||
handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
netHandler(w, r)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, path := range []string{"/networks", "/services", "/sandboxes"} {
|
||||
routes = append(routes, networkRoute{path, handler})
|
||||
}
|
||||
|
||||
return networkRouter{routes}
|
||||
}
|
||||
|
||||
// Register adds the filtered handler to the mux.
|
||||
func (n networkRoute) Register(m *mux.Router, handler http.Handler) {
|
||||
logrus.Debugf("Registering %s, %v", n.path, httpMethods)
|
||||
subrouter := m.PathPrefix(router.VersionMatcher + n.path).Subrouter()
|
||||
subrouter.Methods(httpMethods...).Handler(handler)
|
||||
|
||||
subrouter = m.PathPrefix(n.path).Subrouter()
|
||||
subrouter.Methods(httpMethods...).Handler(handler)
|
||||
}
|
||||
216
components/engine/api/server/router/network/network_routes.go
Normal file
216
components/engine/api/server/router/network/network_routes.go
Normal file
@ -0,0 +1,216 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/docker/pkg/parsers/filters"
|
||||
"github.com/docker/libnetwork"
|
||||
)
|
||||
|
||||
func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filter := r.Form.Get("filters")
|
||||
netFilters, err := filters.FromParam(filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
list := []*types.NetworkResource{}
|
||||
var nameFilter, idFilter bool
|
||||
var names, ids []string
|
||||
if names, nameFilter = netFilters["name"]; nameFilter {
|
||||
for _, name := range names {
|
||||
if nw, err := n.daemon.GetNetwork(name, daemon.NetworkByName); err == nil {
|
||||
list = append(list, buildNetworkResource(nw))
|
||||
} else {
|
||||
logrus.Errorf("failed to get network for filter=%s : %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ids, idFilter = netFilters["id"]; idFilter {
|
||||
for _, id := range ids {
|
||||
for _, nw := range n.daemon.GetNetworksByID(id) {
|
||||
list = append(list, buildNetworkResource(nw))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !nameFilter && !idFilter {
|
||||
nwList := n.daemon.GetNetworksByID("")
|
||||
for _, nw := range nwList {
|
||||
list = append(list, buildNetworkResource(nw))
|
||||
}
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, list)
|
||||
}
|
||||
|
||||
func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nw, err := n.daemon.FindNetwork(vars["id"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, buildNetworkResource(nw))
|
||||
}
|
||||
|
||||
func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
var create types.NetworkCreate
|
||||
var warning string
|
||||
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&create); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nw, err := n.daemon.GetNetwork(create.Name, daemon.NetworkByName)
|
||||
if _, ok := err.(libnetwork.ErrNoSuchNetwork); err != nil && !ok {
|
||||
return err
|
||||
}
|
||||
if nw != nil {
|
||||
if create.CheckDuplicate {
|
||||
return libnetwork.NetworkNameError(create.Name)
|
||||
}
|
||||
warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
|
||||
}
|
||||
|
||||
nw, err = n.daemon.CreateNetwork(create.Name, create.Driver, create.Options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return httputils.WriteJSON(w, http.StatusCreated, &types.NetworkCreateResponse{
|
||||
ID: nw.ID(),
|
||||
Warning: warning,
|
||||
})
|
||||
}
|
||||
|
||||
func (n *networkRouter) postNetworkConnect(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
var connect types.NetworkConnect
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&connect); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nw, err := n.daemon.FindNetwork(vars["id"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
container, err := n.daemon.Get(connect.Container)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid container %s : %v", container, err)
|
||||
}
|
||||
return container.ConnectToNetwork(nw.Name())
|
||||
}
|
||||
|
||||
func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
var disconnect types.NetworkDisconnect
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&disconnect); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nw, err := n.daemon.FindNetwork(vars["id"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
container, err := n.daemon.Get(disconnect.Container)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid container %s : %v", container, err)
|
||||
}
|
||||
return container.DisconnectFromNetwork(nw)
|
||||
}
|
||||
|
||||
func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nw, err := n.daemon.FindNetwork(vars["id"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nw.Delete()
|
||||
}
|
||||
|
||||
func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource {
|
||||
r := &types.NetworkResource{}
|
||||
if nw == nil {
|
||||
return r
|
||||
}
|
||||
|
||||
r.Name = nw.Name()
|
||||
r.ID = nw.ID()
|
||||
r.Driver = nw.Type()
|
||||
r.Containers = make(map[string]types.EndpointResource)
|
||||
epl := nw.Endpoints()
|
||||
for _, e := range epl {
|
||||
sb := e.Info().Sandbox()
|
||||
if sb == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
r.Containers[sb.ContainerID()] = buildEndpointResource(e)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func buildEndpointResource(e libnetwork.Endpoint) types.EndpointResource {
|
||||
er := types.EndpointResource{}
|
||||
if e == nil {
|
||||
return er
|
||||
}
|
||||
|
||||
er.EndpointID = e.ID()
|
||||
if iface := e.Info().Iface(); iface != nil {
|
||||
if mac := iface.MacAddress(); mac != nil {
|
||||
er.MacAddress = mac.String()
|
||||
}
|
||||
if ip := iface.Address(); len(ip.IP) > 0 {
|
||||
er.IPv4Address = (&ip).String()
|
||||
}
|
||||
|
||||
if ipv6 := iface.AddressIPv6(); len(ipv6.IP) > 0 {
|
||||
er.IPv6Address = (&ipv6).String()
|
||||
}
|
||||
}
|
||||
return er
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
// +build !experimental
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// NewRouter initializes a new network router
|
||||
func NewRouter(d *daemon.Daemon) router.Router {
|
||||
return networkRouter{}
|
||||
}
|
||||
|
||||
// Register adds the filtered handler to the mux.
|
||||
func (n networkRoute) Register(m *mux.Router, handler http.Handler) {
|
||||
}
|
||||
Reference in New Issue
Block a user