1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Restore stack deploy integration test with dab

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2016-11-08 15:20:16 -05:00
parent aa5e7d038a
commit bd8de8d8be
3 changed files with 144 additions and 87 deletions

View file

@ -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 {

View file

@ -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)
}

View file

@ -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")
}