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:
parent
aa5e7d038a
commit
bd8de8d8be
3 changed files with 144 additions and 87 deletions
|
@ -58,100 +58,18 @@ func newDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDeploy(dockerCli *command.DockerCli, opts deployOptions) error {
|
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).")
|
return fmt.Errorf("Please specify either a bundle file (with --bundle-file) or a Compose file (with --compose-file).")
|
||||||
}
|
case opts.bundlefile != "" && opts.composefile != "":
|
||||||
|
|
||||||
if opts.bundlefile != "" && opts.composefile != "" {
|
|
||||||
return fmt.Errorf("You cannot specify both a bundle file and a Compose file.")
|
return fmt.Errorf("You cannot specify both a bundle file and a Compose file.")
|
||||||
}
|
case opts.bundlefile != "":
|
||||||
|
|
||||||
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 != "" {
|
|
||||||
return deployBundle(dockerCli, opts)
|
return deployBundle(dockerCli, opts)
|
||||||
} else {
|
default:
|
||||||
return deployCompose(dockerCli, opts)
|
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 {
|
func deployCompose(dockerCli *command.DockerCli, opts deployOptions) error {
|
||||||
configDetails, err := getConfigDetails(opts)
|
configDetails, err := getConfigDetails(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
80
cli/command/stack/deploy_bundlefile.go
Normal file
80
cli/command/stack/deploy_bundlefile.go
Normal 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)
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/integration/checker"
|
"github.com/docker/docker/pkg/integration/checker"
|
||||||
"github.com/go-check/check"
|
"github.com/go-check/check"
|
||||||
)
|
)
|
||||||
|
@ -61,3 +64,59 @@ func (s *DockerSwarmSuite) TestStackDeployComposeFile(c *check.C) {
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
c.Assert(out, check.Equals, "NAME SERVICES\n")
|
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")
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue