mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add simple integration test cases
- Enhance dnet to use codegansta/cli as the frontend - Add `container create/rm` commands only in dnet - With the above dnet enhancements add more integration tests Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
parent
59fd1a605a
commit
ea4cdf441e
10 changed files with 395 additions and 252 deletions
|
@ -47,8 +47,8 @@ func setupMockHTTPCallback() {
|
||||||
srvList = append(srvList, ep)
|
srvList = append(srvList, ep)
|
||||||
mockServiceListJSON, _ = json.Marshal(srvList)
|
mockServiceListJSON, _ = json.Marshal(srvList)
|
||||||
|
|
||||||
var sbxList []sandboxResource
|
var sbxList []SandboxResource
|
||||||
sb := sandboxResource{ID: mockSandboxID, ContainerID: mockContainerID}
|
sb := SandboxResource{ID: mockSandboxID, ContainerID: mockContainerID}
|
||||||
mockSbJSON, _ = json.Marshal(sb)
|
mockSbJSON, _ = json.Marshal(sb)
|
||||||
sbxList = append(sbxList, sb)
|
sbxList = append(sbxList, sb)
|
||||||
mockSbListJSON, _ = json.Marshal(sbxList)
|
mockSbListJSON, _ = json.Marshal(sbxList)
|
||||||
|
|
|
@ -120,7 +120,7 @@ func lookupSandboxID(cli *NetworkCli, containerID string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var sandboxList []sandboxResource
|
var sandboxList []SandboxResource
|
||||||
err = json.Unmarshal(obj, &sandboxList)
|
err = json.Unmarshal(obj, &sandboxList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -268,7 +268,7 @@ func getBackendID(cli *NetworkCli, servID string) (string, error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
if obj, _, err = readBody(cli.call("GET", "/services/"+servID+"/backend", nil, nil)); err == nil {
|
if obj, _, err = readBody(cli.call("GET", "/services/"+servID+"/backend", nil, nil)); err == nil {
|
||||||
var sr sandboxResource
|
var sr SandboxResource
|
||||||
if err := json.NewDecoder(bytes.NewReader(obj)).Decode(&sr); err == nil {
|
if err := json.NewDecoder(bytes.NewReader(obj)).Decode(&sr); err == nil {
|
||||||
bk = sr.ContainerID
|
bk = sr.ContainerID
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -21,8 +21,8 @@ type serviceResource struct {
|
||||||
Network string `json:"network"`
|
Network string `json:"network"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// sandboxResource is the body of "get service backend" response message
|
// SandboxResource is the body of "get service backend" response message
|
||||||
type sandboxResource struct {
|
type SandboxResource struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
ContainerID string `json:"container_id"`
|
ContainerID string `json:"container_id"`
|
||||||
|
@ -52,7 +52,8 @@ type serviceAttach struct {
|
||||||
SandboxID string `json:"sandbox_id"`
|
SandboxID string `json:"sandbox_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type sandboxCreate struct {
|
// SandboxCreate is the body of the "post /sandboxes" http request message
|
||||||
|
type SandboxCreate struct {
|
||||||
ContainerID string `json:"container_id"`
|
ContainerID string `json:"container_id"`
|
||||||
HostName string `json:"host_name"`
|
HostName string `json:"host_name"`
|
||||||
DomainName string `json:"domain_name"`
|
DomainName string `json:"domain_name"`
|
||||||
|
|
146
libnetwork/cmd/dnet/cmd.go
Normal file
146
libnetwork/cmd/dnet/cmd.go
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
"github.com/docker/docker/pkg/term"
|
||||||
|
"github.com/docker/libnetwork/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
containerCreateCommand = cli.Command{
|
||||||
|
Name: "create",
|
||||||
|
Usage: "Create a container",
|
||||||
|
Action: runContainerCreate,
|
||||||
|
}
|
||||||
|
|
||||||
|
containerRmCommand = cli.Command{
|
||||||
|
Name: "rm",
|
||||||
|
Usage: "Remove a container",
|
||||||
|
Action: runContainerRm,
|
||||||
|
}
|
||||||
|
|
||||||
|
containerCommands = []cli.Command{
|
||||||
|
containerCreateCommand,
|
||||||
|
containerRmCommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
dnetCommands = []cli.Command{
|
||||||
|
createDockerCommand("network"),
|
||||||
|
createDockerCommand("service"),
|
||||||
|
{
|
||||||
|
Name: "container",
|
||||||
|
Usage: "Container management commands",
|
||||||
|
Subcommands: containerCommands,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func runContainerCreate(c *cli.Context) {
|
||||||
|
if len(c.Args()) == 0 {
|
||||||
|
fmt.Printf("Please provide container id argument\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
sc := client.SandboxCreate{ContainerID: c.Args()[0]}
|
||||||
|
obj, _, err := readBody(epConn.httpCall("POST", "/sandboxes", sc, nil))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("POST failed during create container: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var replyID string
|
||||||
|
err = json.Unmarshal(obj, &replyID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unmarshall of response failed during create container: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s\n", replyID)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func runContainerRm(c *cli.Context) {
|
||||||
|
var sbList []*client.SandboxResource
|
||||||
|
|
||||||
|
if len(c.Args()) == 0 {
|
||||||
|
fmt.Printf("Please provide container id argument\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, _, err := readBody(epConn.httpCall("GET", "/sandboxes?partial-container-id="+c.Args()[0], nil, nil))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("GET failed during container id lookup: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(obj, &sbList)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unmarshall of container id lookup response failed: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sbList) == 0 {
|
||||||
|
fmt.Printf("No sandbox for container %s found\n", c.Args()[0])
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = readBody(epConn.httpCall("DELETE", "/sandboxes/"+sbList[0].ID, nil, nil))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("DELETE of sandbox id %s failed: %v", sbList[0].ID, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDockerCommand(c *cli.Context, cmd string) {
|
||||||
|
_, stdout, stderr := term.StdStreams()
|
||||||
|
oldcli := client.NewNetworkCli(stdout, stderr, epConn.httpCall)
|
||||||
|
var args []string
|
||||||
|
args = append(args, cmd)
|
||||||
|
if c.Bool("h") {
|
||||||
|
args = append(args, "--help")
|
||||||
|
} else {
|
||||||
|
args = append(args, c.Args()...)
|
||||||
|
}
|
||||||
|
if err := oldcli.Cmd("dnet", args...); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDockerCommand(cmd string) cli.Command {
|
||||||
|
return cli.Command{
|
||||||
|
Name: cmd,
|
||||||
|
Usage: fmt.Sprintf("%s management commands", cmd),
|
||||||
|
SkipFlagParsing: true,
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
runDockerCommand(c, cmd)
|
||||||
|
},
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
{
|
||||||
|
Name: "h, -help",
|
||||||
|
Usage: fmt.Sprintf("%s help", cmd),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) {
|
||||||
|
if stream != nil {
|
||||||
|
defer stream.Close()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, statusCode, err
|
||||||
|
}
|
||||||
|
body, err := ioutil.ReadAll(stream)
|
||||||
|
if err != nil {
|
||||||
|
return nil, -1, err
|
||||||
|
}
|
||||||
|
return body, statusCode, nil
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
flag "github.com/docker/docker/pkg/mflag"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/docker/docker/pkg/parsers"
|
"github.com/docker/docker/pkg/parsers"
|
||||||
"github.com/docker/docker/pkg/reexec"
|
"github.com/docker/docker/pkg/reexec"
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ import (
|
||||||
"github.com/docker/docker/pkg/term"
|
"github.com/docker/docker/pkg/term"
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
"github.com/docker/libnetwork/api"
|
"github.com/docker/libnetwork/api"
|
||||||
"github.com/docker/libnetwork/client"
|
|
||||||
"github.com/docker/libnetwork/config"
|
"github.com/docker/libnetwork/config"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
"github.com/docker/libnetwork/options"
|
"github.com/docker/libnetwork/options"
|
||||||
|
@ -36,6 +35,8 @@ const (
|
||||||
defaultCfgFile = "/etc/default/libnetwork.toml"
|
defaultCfgFile = "/etc/default/libnetwork.toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var epConn *dnetConnection
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if reexec.Init() {
|
if reexec.Init() {
|
||||||
return
|
return
|
||||||
|
@ -44,7 +45,7 @@ func main() {
|
||||||
_, stdout, stderr := term.StdStreams()
|
_, stdout, stderr := term.StdStreams()
|
||||||
logrus.SetOutput(stderr)
|
logrus.SetOutput(stderr)
|
||||||
|
|
||||||
err := dnetCommand(stdout, stderr)
|
err := dnetApp(stdout, stderr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
@ -89,61 +90,16 @@ func processConfig(cfg *config.Config) []config.Option {
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
func dnetCommand(stdout, stderr io.Writer) error {
|
func dnetApp(stdout, stderr io.Writer) error {
|
||||||
flag.Parse()
|
app := cli.NewApp()
|
||||||
|
|
||||||
if *flHelp {
|
app.Name = "dnet"
|
||||||
flag.Usage()
|
app.Usage = "A self-sufficient runtime for container networking."
|
||||||
return nil
|
app.Flags = dnetFlags
|
||||||
}
|
app.Before = processFlags
|
||||||
|
app.Commands = dnetCommands
|
||||||
|
|
||||||
if *flLogLevel != "" {
|
app.Run(os.Args)
|
||||||
lvl, err := logrus.ParseLevel(*flLogLevel)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(stderr, "Unable to parse logging level: %s\n", *flLogLevel)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
logrus.SetLevel(lvl)
|
|
||||||
} else {
|
|
||||||
logrus.SetLevel(logrus.InfoLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *flDebug {
|
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *flHost == "" {
|
|
||||||
defaultHost := os.Getenv("DNET_HOST")
|
|
||||||
if defaultHost == "" {
|
|
||||||
// TODO : Add UDS support
|
|
||||||
defaultHost = fmt.Sprintf("tcp://%s:%d", DefaultHTTPHost, DefaultHTTPPort)
|
|
||||||
}
|
|
||||||
*flHost = defaultHost
|
|
||||||
}
|
|
||||||
|
|
||||||
dc, err := newDnetConnection(*flHost)
|
|
||||||
if err != nil {
|
|
||||||
if *flDaemon {
|
|
||||||
logrus.Error(err)
|
|
||||||
} else {
|
|
||||||
fmt.Fprint(stderr, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if *flDaemon {
|
|
||||||
err := dc.dnetDaemon()
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("dnet Daemon exited with an error : %v", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cli := client.NewNetworkCli(stdout, stderr, dc.httpCall)
|
|
||||||
if err := cli.Cmd("dnet", flag.Args()...); err != nil {
|
|
||||||
fmt.Fprintln(stderr, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,8 +133,8 @@ type dnetConnection struct {
|
||||||
addr string
|
addr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dnetConnection) dnetDaemon() error {
|
func (d *dnetConnection) dnetDaemon(cfgFile string) error {
|
||||||
cfg, err := parseConfig(*flCfgFile)
|
cfg, err := parseConfig(cfgFile)
|
||||||
var cOptions []config.Option
|
var cOptions []config.Option
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cOptions = processConfig(cfg)
|
cOptions = processConfig(cfg)
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/docker/libnetwork/testutils"
|
|
||||||
)
|
|
||||||
|
|
||||||
const dnetCommandName = "dnet"
|
|
||||||
|
|
||||||
var origStdOut = os.Stdout
|
|
||||||
|
|
||||||
func TestDnetDaemonCustom(t *testing.T) {
|
|
||||||
if !testutils.IsRunningInContainer() {
|
|
||||||
t.Skip("This test must run inside a container ")
|
|
||||||
}
|
|
||||||
customPort := 4567
|
|
||||||
doneChan := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
args := []string{dnetCommandName, "-d", fmt.Sprintf("-H=:%d", customPort)}
|
|
||||||
executeDnetCommand(t, args, true)
|
|
||||||
doneChan <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-doneChan:
|
|
||||||
t.Fatal("dnet Daemon is not supposed to exit")
|
|
||||||
case <-time.After(3 * time.Second):
|
|
||||||
args := []string{dnetCommandName, "-d=false", fmt.Sprintf("-H=:%d", customPort), "-D", "network", "ls"}
|
|
||||||
executeDnetCommand(t, args, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDnetDaemonInvalidCustom(t *testing.T) {
|
|
||||||
if !testutils.IsRunningInContainer() {
|
|
||||||
t.Skip("This test must run inside a container ")
|
|
||||||
}
|
|
||||||
customPort := 4668
|
|
||||||
doneChan := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
args := []string{dnetCommandName, "-d=true", fmt.Sprintf("-H=:%d", customPort)}
|
|
||||||
executeDnetCommand(t, args, true)
|
|
||||||
doneChan <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-doneChan:
|
|
||||||
t.Fatal("dnet Daemon is not supposed to exit")
|
|
||||||
case <-time.After(3 * time.Second):
|
|
||||||
args := []string{dnetCommandName, "-d=false", "-H=:6669", "-D", "network", "ls"}
|
|
||||||
executeDnetCommand(t, args, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDnetDaemonInvalidParams(t *testing.T) {
|
|
||||||
if !testutils.IsRunningInContainer() {
|
|
||||||
t.Skip("This test must run inside a container ")
|
|
||||||
}
|
|
||||||
args := []string{dnetCommandName, "-d=false", "-H=tcp:/127.0.0.1:8080"}
|
|
||||||
executeDnetCommand(t, args, false)
|
|
||||||
|
|
||||||
args = []string{dnetCommandName, "-d=false", "-H=unix://var/run/dnet.sock"}
|
|
||||||
executeDnetCommand(t, args, false)
|
|
||||||
|
|
||||||
args = []string{dnetCommandName, "-d=false", "-H=", "-l=invalid"}
|
|
||||||
executeDnetCommand(t, args, false)
|
|
||||||
|
|
||||||
args = []string{dnetCommandName, "-d=false", "-H=", "-l=error", "invalid"}
|
|
||||||
executeDnetCommand(t, args, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDnetDefaultsWithFlags(t *testing.T) {
|
|
||||||
if !testutils.IsRunningInContainer() {
|
|
||||||
t.Skip("This test must run inside a container ")
|
|
||||||
}
|
|
||||||
doneChan := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
args := []string{dnetCommandName, "-d=true", "-H=", "-l=error"}
|
|
||||||
executeDnetCommand(t, args, true)
|
|
||||||
doneChan <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-doneChan:
|
|
||||||
t.Fatal("dnet Daemon is not supposed to exit")
|
|
||||||
case <-time.After(3 * time.Second):
|
|
||||||
args := []string{dnetCommandName, "-d=false", "network", "create", "-d=null", "test"}
|
|
||||||
executeDnetCommand(t, args, true)
|
|
||||||
|
|
||||||
args = []string{dnetCommandName, "-d=false", "-D", "network", "ls"}
|
|
||||||
executeDnetCommand(t, args, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDnetMain(t *testing.T) {
|
|
||||||
if !testutils.IsRunningInContainer() {
|
|
||||||
t.Skip("This test must run inside a container ")
|
|
||||||
}
|
|
||||||
customPort := 4568
|
|
||||||
doneChan := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
args := []string{dnetCommandName, "-d=true", "-h=false", fmt.Sprintf("-H=:%d", customPort)}
|
|
||||||
os.Args = args
|
|
||||||
main()
|
|
||||||
doneChan <- true
|
|
||||||
}()
|
|
||||||
select {
|
|
||||||
case <-doneChan:
|
|
||||||
t.Fatal("dnet Daemon is not supposed to exit")
|
|
||||||
case <-time.After(2 * time.Second):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func executeDnetCommand(t *testing.T, args []string, shouldSucced bool) {
|
|
||||||
_, w, _ := os.Pipe()
|
|
||||||
os.Stdout = w
|
|
||||||
|
|
||||||
os.Args = args
|
|
||||||
err := dnetCommand(ioutil.Discard, ioutil.Discard)
|
|
||||||
if shouldSucced && err != nil {
|
|
||||||
os.Stdout = origStdOut
|
|
||||||
t.Fatalf("cli [%v] must succeed, but failed with an error : %v", args, err)
|
|
||||||
} else if !shouldSucced && err == nil {
|
|
||||||
os.Stdout = origStdOut
|
|
||||||
t.Fatalf("cli [%v] must fail, but succeeded with an error : %v", args, err)
|
|
||||||
}
|
|
||||||
os.Stdout = origStdOut
|
|
||||||
}
|
|
|
@ -4,48 +4,84 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
flag "github.com/docker/docker/pkg/mflag"
|
"github.com/Sirupsen/logrus"
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
type command struct {
|
|
||||||
name string
|
|
||||||
description string
|
|
||||||
}
|
|
||||||
|
|
||||||
type byName []command
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
|
dnetFlags = []cli.Flag{
|
||||||
flHost = flag.String([]string{"H", "-host"}, "", "Daemon socket to connect to")
|
cli.BoolFlag{
|
||||||
flLogLevel = flag.String([]string{"l", "-log-level"}, "info", "Set the logging level")
|
Name: "d, -daemon",
|
||||||
flDebug = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode")
|
Usage: "Enable daemon mode",
|
||||||
flCfgFile = flag.String([]string{"c", "-cfg-file"}, "/etc/default/libnetwork.toml", "Configuration file")
|
},
|
||||||
flHelp = flag.Bool([]string{"h", "-help"}, false, "Print usage")
|
cli.StringFlag{
|
||||||
|
Name: "H, -host",
|
||||||
dnetCommands = []command{
|
Value: "",
|
||||||
{"network", "Network management commands"},
|
Usage: "Daemon socket to connect to",
|
||||||
{"service", "Service management commands"},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "l, -log-level",
|
||||||
|
Value: "info",
|
||||||
|
Usage: "Set the logging level",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "D, -debug",
|
||||||
|
Usage: "Enable debug mode",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "c, -cfg-file",
|
||||||
|
Value: "/etc/default/libnetwork.toml",
|
||||||
|
Usage: "Configuration file",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func processFlags(c *cli.Context) error {
|
||||||
flag.Usage = func() {
|
var err error
|
||||||
fmt.Fprint(os.Stdout, "Usage: dnet [OPTIONS] COMMAND [arg...]\n\nA self-sufficient runtime for container networking.\n\nOptions:\n")
|
|
||||||
|
|
||||||
flag.CommandLine.SetOutput(os.Stdout)
|
if c.String("l") != "" {
|
||||||
flag.PrintDefaults()
|
lvl, err := logrus.ParseLevel(c.String("l"))
|
||||||
|
if err != nil {
|
||||||
help := "\nCommands:\n"
|
fmt.Printf("Unable to parse logging level: %s\n", c.String("l"))
|
||||||
|
os.Exit(1)
|
||||||
for _, cmd := range dnetCommands {
|
}
|
||||||
help += fmt.Sprintf(" %-10.10s%s\n", cmd.name, cmd.description)
|
logrus.SetLevel(lvl)
|
||||||
|
} else {
|
||||||
|
logrus.SetLevel(logrus.InfoLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
help += "\nRun 'dnet COMMAND --help' for more information on a command."
|
if c.Bool("D") {
|
||||||
fmt.Fprintf(os.Stdout, "%s\n", help)
|
logrus.SetLevel(logrus.DebugLevel)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func printUsage() {
|
hostFlag := c.String("H")
|
||||||
fmt.Println("Usage: dnet <OPTIONS> COMMAND [arg...]")
|
if hostFlag == "" {
|
||||||
|
defaultHost := os.Getenv("DNET_HOST")
|
||||||
|
if defaultHost == "" {
|
||||||
|
// TODO : Add UDS support
|
||||||
|
defaultHost = fmt.Sprintf("tcp://%s:%d", DefaultHTTPHost, DefaultHTTPPort)
|
||||||
|
}
|
||||||
|
hostFlag = defaultHost
|
||||||
|
}
|
||||||
|
|
||||||
|
epConn, err = newDnetConnection(hostFlag)
|
||||||
|
if err != nil {
|
||||||
|
if c.Bool("d") {
|
||||||
|
logrus.Error(err)
|
||||||
|
} else {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Bool("d") {
|
||||||
|
err = epConn.dnetDaemon(c.String("c"))
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("dnet Daemon exited with an error : %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
31
libnetwork/test/integration/dnet/dnet.bats
Normal file
31
libnetwork/test/integration/dnet/dnet.bats
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
@test "Test dnet custom port" {
|
||||||
|
start_dnet 1 a none null 4567
|
||||||
|
dnet_cmd 4567 network ls
|
||||||
|
stop_dnet 1 a
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Test dnet invalid custom port" {
|
||||||
|
start_dnet 1 b none null 4567
|
||||||
|
run dnet_cmd 4568 network ls
|
||||||
|
echo ${output}
|
||||||
|
[ "$status" -ne 0 ]
|
||||||
|
stop_dnet 1 b
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Test dnet invalid params" {
|
||||||
|
start_dnet 1 c none null
|
||||||
|
run dnet_cmd 8080 network ls
|
||||||
|
echo ${output}
|
||||||
|
[ "$status" -ne 0 ]
|
||||||
|
run ./cmd/dnet/dnet -H=unix://var/run/dnet.sock network ls
|
||||||
|
echo ${output}
|
||||||
|
[ "$status" -ne 0 ]
|
||||||
|
run ./cmd/dnet/dnet -H= -l=invalid network ls
|
||||||
|
echo ${output}
|
||||||
|
[ "$status" -ne 0 ]
|
||||||
|
stop_dnet 1 c
|
||||||
|
}
|
|
@ -1,10 +1,21 @@
|
||||||
|
function inst_id2port() {
|
||||||
|
echo $((41000+${1}-1))
|
||||||
|
}
|
||||||
|
|
||||||
function start_consul() {
|
function start_consul() {
|
||||||
stop_consul
|
stop_consul
|
||||||
docker run -d --name=pr_consul -p 8500:8500 -p 8300-8302:8300-8302/tcp -p 8300-8302:8300-8302/udp -h consul progrium/consul -server -bootstrap
|
docker run -d \
|
||||||
|
--name=pr_consul \
|
||||||
|
-p 8500:8500 \
|
||||||
|
-p 8300-8302:8300-8302/tcp \
|
||||||
|
-p 8300-8302:8300-8302/udp \
|
||||||
|
-h consul \
|
||||||
|
progrium/consul -server -bootstrap
|
||||||
sleep 2
|
sleep 2
|
||||||
}
|
}
|
||||||
|
|
||||||
function stop_consul() {
|
function stop_consul() {
|
||||||
|
echo "consul started"
|
||||||
docker stop pr_consul || true
|
docker stop pr_consul || true
|
||||||
# You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
|
# You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
|
||||||
if [ -z "$CIRCLECI" ]; then
|
if [ -z "$CIRCLECI" ]; then
|
||||||
|
@ -13,11 +24,19 @@ function stop_consul() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function start_dnet() {
|
function start_dnet() {
|
||||||
stop_dnet $1
|
stop_dnet $1 $2
|
||||||
name="dnet-$1"
|
name="dnet-$1-$2"
|
||||||
|
if [ -z "$5" ]
|
||||||
|
then
|
||||||
hport=$((41000+${1}-1))
|
hport=$((41000+${1}-1))
|
||||||
|
cport=2385
|
||||||
|
hopt=""
|
||||||
|
else
|
||||||
|
hport=$5
|
||||||
|
cport=$5
|
||||||
|
hopt="-H tcp://0.0.0.0:${cport}"
|
||||||
|
fi
|
||||||
|
|
||||||
bridge_ip=$(docker inspect --format '{{.NetworkSettings.Gateway}}' pr_consul)
|
|
||||||
mkdir -p /tmp/dnet/${name}
|
mkdir -p /tmp/dnet/${name}
|
||||||
tomlfile="/tmp/dnet/${name}/libnetwork.toml"
|
tomlfile="/tmp/dnet/${name}/libnetwork.toml"
|
||||||
cat > ${tomlfile} <<EOF
|
cat > ${tomlfile} <<EOF
|
||||||
|
@ -25,21 +44,42 @@ title = "LibNetwork Configuration file"
|
||||||
|
|
||||||
[daemon]
|
[daemon]
|
||||||
debug = false
|
debug = false
|
||||||
defaultnetwork = "${2}"
|
defaultnetwork = "${3}"
|
||||||
defaultdriver = "${3}"
|
defaultdriver = "${4}"
|
||||||
labels = ["com.docker.network.driver.overlay.bind_interface=eth0"]
|
labels = ["com.docker.network.driver.overlay.bind_interface=eth0"]
|
||||||
[datastore]
|
[datastore]
|
||||||
embedded = false
|
embedded = false
|
||||||
|
EOF
|
||||||
|
if [ "${4}" == "overlay" ]
|
||||||
|
then
|
||||||
|
bridge_ip=$(docker inspect --format '{{.NetworkSettings.Gateway}}' pr_consul)
|
||||||
|
cat >> ${tomlfile} <<EOF
|
||||||
[datastore.client]
|
[datastore.client]
|
||||||
provider = "consul"
|
provider = "consul"
|
||||||
Address = "${bridge_ip}:8500"
|
Address = "${bridge_ip}:8500"
|
||||||
EOF
|
EOF
|
||||||
docker run -d --name=${name} --privileged -p ${hport}:2385 -v $(pwd)/:/go/src/github.com/docker/libnetwork -v /tmp:/tmp -w /go/src/github.com/docker/libnetwork golang:1.4 ./cmd/dnet/dnet -dD -c ${tomlfile}
|
fi
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
-d \
|
||||||
|
--name=${name} \
|
||||||
|
--privileged \
|
||||||
|
-p ${hport}:${cport} \
|
||||||
|
-v $(pwd)/:/go/src/github.com/docker/libnetwork \
|
||||||
|
-v /tmp:/tmp \
|
||||||
|
-w /go/src/github.com/docker/libnetwork \
|
||||||
|
golang:1.4 ./cmd/dnet/dnet -d -D ${hopt} -c ${tomlfile}
|
||||||
sleep 2
|
sleep 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function skip_for_circleci() {
|
||||||
|
if [ -n "$CIRCLECI" ]; then
|
||||||
|
skip
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
function stop_dnet() {
|
function stop_dnet() {
|
||||||
name="dnet-$1"
|
name="dnet-$1-$2"
|
||||||
rm -rf /tmp/dnet/${name} || true
|
rm -rf /tmp/dnet/${name} || true
|
||||||
docker stop ${name} || true
|
docker stop ${name} || true
|
||||||
# You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
|
# You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
|
||||||
|
@ -50,7 +90,7 @@ function stop_dnet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dnet_cmd() {
|
function dnet_cmd() {
|
||||||
hport=$((41000+${1}-1))
|
hport=$1
|
||||||
shift
|
shift
|
||||||
./cmd/dnet/dnet -H 127.0.0.1:${hport} $*
|
./cmd/dnet/dnet -H tcp://127.0.0.1:${hport} $*
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,24 @@
|
||||||
|
|
||||||
load helpers
|
load helpers
|
||||||
|
|
||||||
export BATS_TEST_CNT=0
|
|
||||||
|
|
||||||
function setup() {
|
function setup() {
|
||||||
if [ "${BATS_TEST_CNT}" -eq 0 ]; then
|
if [ "${BATS_TEST_NUMBER}" -eq 1 ]; then
|
||||||
start_consul
|
start_consul
|
||||||
start_dnet 1 multihost overlay
|
start_dnet 1 simple multihost overlay
|
||||||
export BATS_TEST_CNT=$((${BATS_TEST_CNT}+1))
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function teardown() {
|
function teardown() {
|
||||||
export BATS_TEST_CNT=$((${BATS_TEST_CNT}-1))
|
if [ "${BATS_TEST_NUMBER}" -eq 6 ]; then
|
||||||
if [ "${BATS_TEST_CNT}" -eq 0 ]; then
|
stop_dnet 1 simple
|
||||||
stop_dnet 1
|
|
||||||
stop_consul
|
stop_consul
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@test "Test default network" {
|
@test "Test default network" {
|
||||||
echo $(docker ps)
|
echo $(docker ps)
|
||||||
run dnet_cmd 1 network ls
|
run dnet_cmd $(inst_id2port 1) network ls
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
echo ${output}
|
echo ${output}
|
||||||
echo ${lines[1]}
|
echo ${lines[1]}
|
||||||
name=$(echo ${lines[1]} | cut -d" " -f2)
|
name=$(echo ${lines[1]} | cut -d" " -f2)
|
||||||
|
@ -32,3 +28,72 @@ function teardown() {
|
||||||
[ "$name" = "multihost" ]
|
[ "$name" = "multihost" ]
|
||||||
[ "$driver" = "overlay" ]
|
[ "$driver" = "overlay" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "Test network create" {
|
||||||
|
echo $(docker ps)
|
||||||
|
run dnet_cmd $(inst_id2port 1) network create -d overlay mh1
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
line=$(dnet_cmd $(inst_id2port 1) network ls | grep mh1)
|
||||||
|
echo ${line}
|
||||||
|
name=$(echo ${line} | cut -d" " -f2)
|
||||||
|
driver=$(echo ${line} | cut -d" " -f3)
|
||||||
|
echo ${name} ${driver}
|
||||||
|
[ "$name" = "mh1" ]
|
||||||
|
[ "$driver" = "overlay" ]
|
||||||
|
dnet_cmd $(inst_id2port 1) network rm mh1
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Test network delete with id" {
|
||||||
|
echo $(docker ps)
|
||||||
|
run dnet_cmd $(inst_id2port 1) network create -d overlay mh1
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
echo ${output}
|
||||||
|
dnet_cmd $(inst_id2port 1) network rm ${output}
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Test service create" {
|
||||||
|
echo $(docker ps)
|
||||||
|
run dnet_cmd $(inst_id2port 1) service publish svc1.multihost
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
echo ${output}
|
||||||
|
run dnet_cmd $(inst_id2port 1) service ls
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
echo ${output}
|
||||||
|
echo ${lines[1]}
|
||||||
|
svc=$(echo ${lines[1]} | cut -d" " -f2)
|
||||||
|
network=$(echo ${lines[1]} | cut -d" " -f3)
|
||||||
|
echo ${svc} ${network}
|
||||||
|
[ "$network" = "multihost" ]
|
||||||
|
[ "$svc" = "svc1" ]
|
||||||
|
dnet_cmd $(inst_id2port 1) service unpublish svc1.multihost
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Test service delete with id" {
|
||||||
|
echo $(docker ps)
|
||||||
|
run dnet_cmd $(inst_id2port 1) service publish svc1.multihost
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
echo ${output}
|
||||||
|
run dnet_cmd $(inst_id2port 1) service ls
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
echo ${output}
|
||||||
|
echo ${lines[1]}
|
||||||
|
id=$(echo ${lines[1]} | cut -d" " -f1)
|
||||||
|
dnet_cmd $(inst_id2port 1) service unpublish ${id}
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Test service attach" {
|
||||||
|
skip_for_circleci
|
||||||
|
echo $(docker ps)
|
||||||
|
dnet_cmd $(inst_id2port 1) service publish svc1.multihost
|
||||||
|
dnet_cmd $(inst_id2port 1) container create container_1
|
||||||
|
dnet_cmd $(inst_id2port 1) service attach container_1 svc1.multihost
|
||||||
|
run dnet_cmd $(inst_id2port 1) service ls
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
echo ${output}
|
||||||
|
echo ${lines[1]}
|
||||||
|
container=$(echo ${lines[1]} | cut -d" " -f4)
|
||||||
|
[ "$container" = "container_1" ]
|
||||||
|
dnet_cmd $(inst_id2port 1) service detach container_1 svc1.multihost
|
||||||
|
dnet_cmd $(inst_id2port 1) container rm container_1
|
||||||
|
dnet_cmd $(inst_id2port 1) service unpublish svc1.multihost
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue