瀏覽代碼

Restore stack deploy integration test with dab

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin 8 年之前
父節點
當前提交
bd8de8d8be
共有 3 個文件被更改,包括 144 次插入87 次删除
  1. 5 87
      cli/command/stack/deploy.go
  2. 80 0
      cli/command/stack/deploy_bundlefile.go
  3. 59 0
      integration-cli/docker_cli_stack_test.go

+ 5 - 87
cli/command/stack/deploy.go

@@ -58,100 +58,18 @@ func newDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
 }
 
 func runDeploy(dockerCli *command.DockerCli, opts deployOptions) error {
-	if opts.bundlefile == "" && opts.composefile == "" {
+	switch {
+	case opts.bundlefile == "" && opts.composefile == "":
 		return fmt.Errorf("Please specify either a bundle file (with --bundle-file) or a Compose file (with --compose-file).")
-	}
-
-	if opts.bundlefile != "" && opts.composefile != "" {
+	case opts.bundlefile != "" && opts.composefile != "":
 		return fmt.Errorf("You cannot specify both a bundle file and a Compose file.")
-	}
-
-	info, err := dockerCli.Client().Info(context.Background())
-	if err != nil {
-		return err
-	}
-	if !info.Swarm.ControlAvailable {
-		return fmt.Errorf("This node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again.")
-	}
-
-	if opts.bundlefile != "" {
+	case opts.bundlefile != "":
 		return deployBundle(dockerCli, opts)
-	} else {
+	default:
 		return deployCompose(dockerCli, opts)
 	}
 }
 
-func deployBundle(dockerCli *command.DockerCli, opts deployOptions) error {
-	bundle, err := loadBundlefile(dockerCli.Err(), opts.namespace, opts.bundlefile)
-	if err != nil {
-		return err
-	}
-
-	namespace := namespace{name: opts.namespace}
-
-	networks := make(map[string]types.NetworkCreate)
-	for _, service := range bundle.Services {
-		for _, networkName := range service.Networks {
-			networks[networkName] = types.NetworkCreate{
-				Labels: getStackLabels(namespace.name, nil),
-			}
-		}
-	}
-
-	services := make(map[string]swarm.ServiceSpec)
-	for internalName, service := range bundle.Services {
-		name := namespace.scope(internalName)
-
-		var ports []swarm.PortConfig
-		for _, portSpec := range service.Ports {
-			ports = append(ports, swarm.PortConfig{
-				Protocol:   swarm.PortConfigProtocol(portSpec.Protocol),
-				TargetPort: portSpec.Port,
-			})
-		}
-
-		nets := []swarm.NetworkAttachmentConfig{}
-		for _, networkName := range service.Networks {
-			nets = append(nets, swarm.NetworkAttachmentConfig{
-				Target:  namespace.scope(networkName),
-				Aliases: []string{networkName},
-			})
-		}
-
-		serviceSpec := swarm.ServiceSpec{
-			Annotations: swarm.Annotations{
-				Name:   name,
-				Labels: getStackLabels(namespace.name, service.Labels),
-			},
-			TaskTemplate: swarm.TaskSpec{
-				ContainerSpec: swarm.ContainerSpec{
-					Image:   service.Image,
-					Command: service.Command,
-					Args:    service.Args,
-					Env:     service.Env,
-					// Service Labels will not be copied to Containers
-					// automatically during the deployment so we apply
-					// it here.
-					Labels: getStackLabels(namespace.name, nil),
-				},
-			},
-			EndpointSpec: &swarm.EndpointSpec{
-				Ports: ports,
-			},
-			Networks: nets,
-		}
-
-		services[internalName] = serviceSpec
-	}
-
-	ctx := context.Background()
-
-	if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil {
-		return err
-	}
-	return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth)
-}
-
 func deployCompose(dockerCli *command.DockerCli, opts deployOptions) error {
 	configDetails, err := getConfigDetails(opts)
 	if err != nil {

+ 80 - 0
cli/command/stack/deploy_bundlefile.go

@@ -0,0 +1,80 @@
+package stack
+
+import (
+	"golang.org/x/net/context"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/swarm"
+	"github.com/docker/docker/cli/command"
+)
+
+func deployBundle(dockerCli *command.DockerCli, opts deployOptions) error {
+	bundle, err := loadBundlefile(dockerCli.Err(), opts.namespace, opts.bundlefile)
+	if err != nil {
+		return err
+	}
+
+	namespace := namespace{name: opts.namespace}
+
+	networks := make(map[string]types.NetworkCreate)
+	for _, service := range bundle.Services {
+		for _, networkName := range service.Networks {
+			networks[networkName] = types.NetworkCreate{
+				Labels: getStackLabels(namespace.name, nil),
+			}
+		}
+	}
+
+	services := make(map[string]swarm.ServiceSpec)
+	for internalName, service := range bundle.Services {
+		name := namespace.scope(internalName)
+
+		var ports []swarm.PortConfig
+		for _, portSpec := range service.Ports {
+			ports = append(ports, swarm.PortConfig{
+				Protocol:   swarm.PortConfigProtocol(portSpec.Protocol),
+				TargetPort: portSpec.Port,
+			})
+		}
+
+		nets := []swarm.NetworkAttachmentConfig{}
+		for _, networkName := range service.Networks {
+			nets = append(nets, swarm.NetworkAttachmentConfig{
+				Target:  namespace.scope(networkName),
+				Aliases: []string{networkName},
+			})
+		}
+
+		serviceSpec := swarm.ServiceSpec{
+			Annotations: swarm.Annotations{
+				Name:   name,
+				Labels: getStackLabels(namespace.name, service.Labels),
+			},
+			TaskTemplate: swarm.TaskSpec{
+				ContainerSpec: swarm.ContainerSpec{
+					Image:   service.Image,
+					Command: service.Command,
+					Args:    service.Args,
+					Env:     service.Env,
+					// Service Labels will not be copied to Containers
+					// automatically during the deployment so we apply
+					// it here.
+					Labels: getStackLabels(namespace.name, nil),
+				},
+			},
+			EndpointSpec: &swarm.EndpointSpec{
+				Ports: ports,
+			},
+			Networks: nets,
+		}
+
+		services[internalName] = serviceSpec
+	}
+
+	ctx := context.Background()
+
+	if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil {
+		return err
+	}
+	return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth)
+}

+ 59 - 0
integration-cli/docker_cli_stack_test.go

@@ -1,6 +1,9 @@
 package main
 
 import (
+	"io/ioutil"
+	"os"
+
 	"github.com/docker/docker/pkg/integration/checker"
 	"github.com/go-check/check"
 )
@@ -61,3 +64,59 @@ func (s *DockerSwarmSuite) TestStackDeployComposeFile(c *check.C) {
 	c.Assert(err, checker.IsNil)
 	c.Assert(out, check.Equals, "NAME  SERVICES\n")
 }
+
+// testDAB is the DAB JSON used for testing.
+// TODO: Use template/text and substitute "Image" with the result of
+// `docker inspect --format '{{index .RepoDigests 0}}' busybox:latest`
+const testDAB = `{
+    "Version": "0.1",
+    "Services": {
+	"srv1": {
+	    "Image": "busybox@sha256:e4f93f6ed15a0cdd342f5aae387886fba0ab98af0a102da6276eaf24d6e6ade0",
+	    "Command": ["top"]
+	},
+	"srv2": {
+	    "Image": "busybox@sha256:e4f93f6ed15a0cdd342f5aae387886fba0ab98af0a102da6276eaf24d6e6ade0",
+	    "Command": ["tail"],
+	    "Args": ["-f", "/dev/null"]
+	}
+    }
+}`
+
+func (s *DockerSwarmSuite) TestStackDeployWithDAB(c *check.C) {
+	testRequires(c, ExperimentalDaemon)
+	// setup
+	testStackName := "test"
+	testDABFileName := testStackName + ".dab"
+	defer os.RemoveAll(testDABFileName)
+	err := ioutil.WriteFile(testDABFileName, []byte(testDAB), 0444)
+	c.Assert(err, checker.IsNil)
+	d := s.AddDaemon(c, true, true)
+	// deploy
+	stackArgs := []string{
+		"stack", "deploy",
+		"--bundle-file", testDABFileName,
+		testStackName,
+	}
+	out, err := d.Cmd(stackArgs...)
+	c.Assert(err, checker.IsNil)
+	c.Assert(out, checker.Contains, "Loading bundle from test.dab\n")
+	c.Assert(out, checker.Contains, "Creating service test_srv1\n")
+	c.Assert(out, checker.Contains, "Creating service test_srv2\n")
+	// ls
+	stackArgs = []string{"stack", "ls"}
+	out, err = d.Cmd(stackArgs...)
+	c.Assert(err, checker.IsNil)
+	c.Assert(out, check.Equals, "NAME  SERVICES\n"+"test  2\n")
+	// rm
+	stackArgs = []string{"stack", "rm", testStackName}
+	out, err = d.Cmd(stackArgs...)
+	c.Assert(err, checker.IsNil)
+	c.Assert(out, checker.Contains, "Removing service test_srv1\n")
+	c.Assert(out, checker.Contains, "Removing service test_srv2\n")
+	// ls (empty)
+	stackArgs = []string{"stack", "ls"}
+	out, err = d.Cmd(stackArgs...)
+	c.Assert(err, checker.IsNil)
+	c.Assert(out, check.Equals, "NAME  SERVICES\n")
+}