deploy.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package stack
  2. import (
  3. "fmt"
  4. "github.com/docker/docker/cli"
  5. "github.com/docker/docker/cli/command"
  6. "github.com/pkg/errors"
  7. "github.com/spf13/cobra"
  8. "golang.org/x/net/context"
  9. )
  10. const (
  11. defaultNetworkDriver = "overlay"
  12. )
  13. type deployOptions struct {
  14. bundlefile string
  15. composefile string
  16. namespace string
  17. sendRegistryAuth bool
  18. }
  19. func newDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
  20. var opts deployOptions
  21. cmd := &cobra.Command{
  22. Use: "deploy [OPTIONS] STACK",
  23. Aliases: []string{"up"},
  24. Short: "Deploy a new stack or update an existing stack",
  25. Args: cli.ExactArgs(1),
  26. RunE: func(cmd *cobra.Command, args []string) error {
  27. opts.namespace = args[0]
  28. return runDeploy(dockerCli, opts)
  29. },
  30. }
  31. flags := cmd.Flags()
  32. addBundlefileFlag(&opts.bundlefile, flags)
  33. addComposefileFlag(&opts.composefile, flags)
  34. addRegistryAuthFlag(&opts.sendRegistryAuth, flags)
  35. return cmd
  36. }
  37. func runDeploy(dockerCli *command.DockerCli, opts deployOptions) error {
  38. ctx := context.Background()
  39. switch {
  40. case opts.bundlefile == "" && opts.composefile == "":
  41. return fmt.Errorf("Please specify either a bundle file (with --bundle-file) or a Compose file (with --compose-file).")
  42. case opts.bundlefile != "" && opts.composefile != "":
  43. return fmt.Errorf("You cannot specify both a bundle file and a Compose file.")
  44. case opts.bundlefile != "":
  45. return deployBundle(ctx, dockerCli, opts)
  46. default:
  47. return deployCompose(ctx, dockerCli, opts)
  48. }
  49. }
  50. // checkDaemonIsSwarmManager does an Info API call to verify that the daemon is
  51. // a swarm manager. This is necessary because we must create networks before we
  52. // create services, but the API call for creating a network does not return a
  53. // proper status code when it can't create a network in the "global" scope.
  54. func checkDaemonIsSwarmManager(ctx context.Context, dockerCli *command.DockerCli) error {
  55. info, err := dockerCli.Client().Info(ctx)
  56. if err != nil {
  57. return err
  58. }
  59. if !info.Swarm.ControlAvailable {
  60. return errors.New("This node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again.")
  61. }
  62. return nil
  63. }