diff --git a/api/client/service.go b/api/client/service.go new file mode 100644 index 0000000000..d7308449e0 --- /dev/null +++ b/api/client/service.go @@ -0,0 +1,15 @@ +// +build experimental + +package client + +import ( + "os" + + nwclient "github.com/docker/libnetwork/client" +) + +func (cli *DockerCli) CmdService(args ...string) error { + nCli := nwclient.NewNetworkCli(cli.out, cli.err, nwclient.CallFunc(cli.call)) + args = append([]string{"service"}, args...) + return nCli.Cmd(os.Args[0], args...) +} diff --git a/api/server/server_experimental.go b/api/server/server_experimental.go index a93b58af1e..06f55013ed 100644 --- a/api/server/server_experimental.go +++ b/api/server/server_experimental.go @@ -9,4 +9,9 @@ func (s *Server) registerSubRouter() { subrouter.Methods("GET", "POST", "PUT", "DELETE").HandlerFunc(httpHandler) subrouter = s.router.PathPrefix("/networks").Subrouter() subrouter.Methods("GET", "POST", "PUT", "DELETE").HandlerFunc(httpHandler) + + subrouter = s.router.PathPrefix("/v{version:[0-9.]+}/services").Subrouter() + subrouter.Methods("GET", "POST", "PUT", "DELETE").HandlerFunc(httpHandler) + subrouter = s.router.PathPrefix("/services").Subrouter() + subrouter.Methods("GET", "POST", "PUT", "DELETE").HandlerFunc(httpHandler) } diff --git a/integration-cli/docker_api_service_test.go b/integration-cli/docker_api_service_test.go new file mode 100644 index 0000000000..df072197c7 --- /dev/null +++ b/integration-cli/docker_api_service_test.go @@ -0,0 +1,113 @@ +// +build experimental + +package main + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/go-check/check" +) + +func isServiceAvailable(c *check.C, name string, network string) bool { + status, body, err := sockRequest("GET", "/services", nil) + c.Assert(status, check.Equals, http.StatusOK) + c.Assert(err, check.IsNil) + + var inspectJSON []struct { + Name string + ID string + Network string + } + if err = json.Unmarshal(body, &inspectJSON); err != nil { + c.Fatalf("unable to unmarshal response body: %v", err) + } + for _, s := range inspectJSON { + if s.Name == name && s.Network == network { + return true + } + } + return false + +} + +func isServiceNetworkAvailable(c *check.C, name string) bool { + status, body, err := sockRequest("GET", "/networks", nil) + c.Assert(status, check.Equals, http.StatusOK) + c.Assert(err, check.IsNil) + + var inspectJSON []struct { + Name string + ID string + Type string + } + if err = json.Unmarshal(body, &inspectJSON); err != nil { + c.Fatalf("unable to unmarshal response body: %v", err) + } + for _, n := range inspectJSON { + if n.Name == name { + return true + } + } + return false + +} + +func (s *DockerSuite) TestServiceApiCreateDelete(c *check.C) { + name := "testnetwork" + config := map[string]interface{}{ + "name": name, + "network_type": "bridge", + } + + status, resp, err := sockRequest("POST", "/networks", config) + c.Assert(status, check.Equals, http.StatusCreated) + c.Assert(err, check.IsNil) + + if !isServiceNetworkAvailable(c, name) { + c.Fatalf("Network %s not found", name) + } + + var nid string + err = json.Unmarshal(resp, &nid) + if err != nil { + c.Fatal(err) + } + + sname := "service1" + sconfig := map[string]interface{}{ + "name": sname, + "network_name": name, + } + + status, resp, err = sockRequest("POST", "/services", sconfig) + c.Assert(status, check.Equals, http.StatusCreated) + c.Assert(err, check.IsNil) + + if !isServiceAvailable(c, sname, name) { + c.Fatalf("Service %s.%s not found", sname, name) + } + + var id string + err = json.Unmarshal(resp, &id) + if err != nil { + c.Fatal(err) + } + + status, _, err = sockRequest("DELETE", fmt.Sprintf("/services/%s", id), nil) + c.Assert(status, check.Equals, http.StatusOK) + c.Assert(err, check.IsNil) + + if isServiceAvailable(c, sname, name) { + c.Fatalf("Service %s.%s not deleted", sname, name) + } + + status, _, err = sockRequest("DELETE", fmt.Sprintf("/networks/%s", nid), nil) + c.Assert(status, check.Equals, http.StatusOK) + c.Assert(err, check.IsNil) + + if isNetworkAvailable(c, name) { + c.Fatalf("Network %s not deleted", name) + } +} diff --git a/integration-cli/docker_cli_service_test.go b/integration-cli/docker_cli_service_test.go new file mode 100644 index 0000000000..5b618b278b --- /dev/null +++ b/integration-cli/docker_cli_service_test.go @@ -0,0 +1,77 @@ +// +build experimental + +package main + +import ( + "os/exec" + "strings" + + "github.com/go-check/check" +) + +func isSrvAvailable(c *check.C, sname string, name string) bool { + runCmd := exec.Command(dockerBinary, "service", "ls") + out, _, _, err := runCommandWithStdoutStderr(runCmd) + if err != nil { + c.Fatal(out, err) + } + lines := strings.Split(out, "\n") + for i := 1; i < len(lines)-1; i++ { + if strings.Contains(lines[i], sname) && strings.Contains(lines[i], name) { + return true + } + } + return false +} +func isNwAvailable(c *check.C, name string) bool { + runCmd := exec.Command(dockerBinary, "network", "ls") + out, _, _, err := runCommandWithStdoutStderr(runCmd) + if err != nil { + c.Fatal(out, err) + } + lines := strings.Split(out, "\n") + for i := 1; i < len(lines)-1; i++ { + if strings.Contains(lines[i], name) { + return true + } + } + return false +} + +func (s *DockerSuite) TestDockerServiceCreateDelete(c *check.C) { + runCmd := exec.Command(dockerBinary, "network", "create", "test") + out, _, _, err := runCommandWithStdoutStderr(runCmd) + if err != nil { + c.Fatal(out, err) + } + if !isNwAvailable(c, "test") { + c.Fatalf("Network test not found") + } + + runCmd = exec.Command(dockerBinary, "service", "publish", "s1.test") + out, _, _, err = runCommandWithStdoutStderr(runCmd) + if err != nil { + c.Fatal(out, err) + } + if !isSrvAvailable(c, "s1", "test") { + c.Fatalf("service s1.test not found") + } + + runCmd = exec.Command(dockerBinary, "service", "unpublish", "s1.test") + out, _, _, err = runCommandWithStdoutStderr(runCmd) + if err != nil { + c.Fatal(out, err) + } + if isSrvAvailable(c, "s1", "test") { + c.Fatalf("service s1.test not removed") + } + + runCmd = exec.Command(dockerBinary, "network", "rm", "test") + out, _, _, err = runCommandWithStdoutStderr(runCmd) + if err != nil { + c.Fatal(out, err) + } + if isNetworkPresent(c, "test") { + c.Fatalf("Network test is not removed") + } +}