From b007cae8b20d5beb475265da69e340e38c5989e9 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Thu, 8 Oct 2015 16:20:07 -0700 Subject: [PATCH] Add docker network create Signed-off-by: Victor Vieux --- api/handlers.go | 19 +++++++++++++++++++ api/primary.go | 1 + cluster/cluster.go | 3 +++ cluster/engine.go | 9 +++++++++ cluster/mesos/cluster.go | 5 +++++ cluster/network.go | 4 ++-- cluster/swarm/cluster.go | 23 +++++++++++++++++++++++ test/integration/api/network.bats | 22 ++++++++++++---------- 8 files changed, 74 insertions(+), 12 deletions(-) diff --git a/api/handlers.go b/api/handlers.go index ffd5480adf..97a950e752 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -427,6 +427,25 @@ func deleteContainers(c *context, w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) } +// POST /networks/create +func postNetworksCreate(c *context, w http.ResponseWriter, r *http.Request) { + var request dockerclient.NetworkCreate + + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + httpError(w, err.Error(), http.StatusBadRequest) + return + } + + response, err := c.cluster.CreateNetwork(&request) + if err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(response) +} + // POST /volumes func postVolumes(c *context, w http.ResponseWriter, r *http.Request) { var request dockerclient.VolumeCreateRequest diff --git a/api/primary.go b/api/primary.go index 05b8eb52e9..2054bede66 100644 --- a/api/primary.go +++ b/api/primary.go @@ -75,6 +75,7 @@ var routes = map[string]map[string]handler{ "/containers/{name:.*}/exec": postContainersExec, "/exec/{execid:.*}/start": postExecStart, "/exec/{execid:.*}/resize": proxyContainer, + "/networks/create": postNetworksCreate, "/volumes": postVolumes, }, "PUT": { diff --git a/cluster/cluster.go b/cluster/cluster.go index a1ac4984ee..5adc49424b 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -35,6 +35,9 @@ type Cluster interface { // Return all networks Networks() Networks + // Create a network + CreateNetwork(request *dockerclient.NetworkCreate) (*dockerclient.NetworkCreateResponse, error) + // Create a volume CreateVolume(request *dockerclient.VolumeCreateRequest) (*Volume, error) diff --git a/cluster/engine.go b/cluster/engine.go index 5394f19672..a8aa3011d7 100644 --- a/cluster/engine.go +++ b/cluster/engine.go @@ -542,6 +542,15 @@ func (e *Engine) RemoveContainer(container *Container, force, volumes bool) erro return nil } +// CreateNetwork creates a network in the engine +func (e *Engine) CreateNetwork(request *dockerclient.NetworkCreate) (*dockerclient.NetworkCreateResponse, error) { + response, err := e.client.CreateNetwork(request) + + e.RefreshNetworks() + + return response, err +} + // CreateVolume creates a volume in the engine func (e *Engine) CreateVolume(request *dockerclient.VolumeCreateRequest) (*Volume, error) { volume, err := e.client.CreateVolume(request) diff --git a/cluster/mesos/cluster.go b/cluster/mesos/cluster.go index 4a962df511..85d5da1bdf 100644 --- a/cluster/mesos/cluster.go +++ b/cluster/mesos/cluster.go @@ -226,6 +226,11 @@ func (c *Cluster) RemoveImages(name string, force bool) ([]*dockerclient.ImageDe return nil, errNotSupported } +// CreateNetwork creates a network in the cluster +func (c *Cluster) CreateNetwork(request *dockerclient.NetworkCreate) (*dockerclient.NetworkCreateResponse, error) { + return nil, errNotSupported +} + // CreateVolume creates a volume in the cluster func (c *Cluster) CreateVolume(request *dockerclient.VolumeCreateRequest) (*cluster.Volume, error) { return nil, errNotSupported diff --git a/cluster/network.go b/cluster/network.go index f69bdc8f2e..9cede7a2e4 100644 --- a/cluster/network.go +++ b/cluster/network.go @@ -35,7 +35,7 @@ func (networks Networks) Get(IDOrName string) *Network { // Match name, /name or engine/name. for _, network := range networks { - if network.Engine.ID+"/"+network.Name == IDOrName || network.Engine.Name+"/"+network.Name == IDOrName { + if network.Name == IDOrName || network.Engine.ID+"/"+network.Name == IDOrName || network.Engine.Name+"/"+network.Name == IDOrName { candidates = append(candidates, network) } } @@ -48,7 +48,7 @@ func (networks Networks) Get(IDOrName string) *Network { // Match name, /name or engine/name. for _, network := range networks { - if network.Name == IDOrName || network.Name == "/"+IDOrName { + if network.Name == "/"+IDOrName { return network } } diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index bff328cfda..b267fd95d2 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -329,6 +329,29 @@ func (c *Cluster) RemoveImages(name string, force bool) ([]*dockerclient.ImageDe return out, err } +// CreateNetwork creates a network in the cluster +func (c *Cluster) CreateNetwork(request *dockerclient.NetworkCreate) (response *dockerclient.NetworkCreateResponse, err error) { + var ( + parts = strings.SplitN(request.Name, "/", 2) + config = &cluster.ContainerConfig{} + ) + + if len(parts) == 2 { + // a node was specified, create the container only on this node + request.Name = parts[1] + config = cluster.BuildContainerConfig(dockerclient.ContainerConfig{Env: []string{"constraint:node==" + parts[0]}}) + } + + n, err := c.scheduler.SelectNodeForContainer(c.listNodes(), config) + if err != nil { + return nil, err + } + if n != nil { + return c.engines[n.ID].CreateNetwork(request) + } + return nil, nil +} + // CreateVolume creates a volume in the cluster func (c *Cluster) CreateVolume(request *dockerclient.VolumeCreateRequest) (*cluster.Volume, error) { var ( diff --git a/test/integration/api/network.bats b/test/integration/api/network.bats index e1f73ae7cc..6e898daff2 100644 --- a/test/integration/api/network.bats +++ b/test/integration/api/network.bats @@ -29,21 +29,23 @@ function teardown() { [ "${#lines[@]}" -eq 13 ] } -@test "docker volume create" { -skip +@test "docker network create" { start_docker 2 swarm_manage - run docker_swarm volume ls - [ "${#lines[@]}" -eq 1 ] + run docker_swarm network ls + [ "${#lines[@]}" -eq 7 ] - docker_swarm volume create --name=test_volume - run docker_swarm volume - [ "${#lines[@]}" -eq 3 ] + docker_swarm network create -d bridge test1 + run docker_swarm network ls + [ "${#lines[@]}" -eq 8 ] - docker_swarm run -d -v=/tmp busybox true - run docker_swarm volume - [ "${#lines[@]}" -eq 4 ] + docker_swarm network create -d bridge node-1/test2 + run docker_swarm network ls + [ "${#lines[@]}" -eq 9 ] + + run docker_swarm network create -d bridge node-2/test3 + [ "$status" -ne 0 ] } @test "docker volume rm" {