Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package stack |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "errors" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"io/ioutil" |
| 6 | 7 |
"os" |
| ... | ... |
@@ -59,19 +60,36 @@ func newDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
func runDeploy(dockerCli *command.DockerCli, opts deployOptions) error {
|
| 62 |
+ ctx := context.Background() |
|
| 63 |
+ |
|
| 62 | 64 |
switch {
|
| 63 | 65 |
case opts.bundlefile == "" && opts.composefile == "": |
| 64 | 66 |
return fmt.Errorf("Please specify either a bundle file (with --bundle-file) or a Compose file (with --compose-file).")
|
| 65 | 67 |
case opts.bundlefile != "" && opts.composefile != "": |
| 66 | 68 |
return fmt.Errorf("You cannot specify both a bundle file and a Compose file.")
|
| 67 | 69 |
case opts.bundlefile != "": |
| 68 |
- return deployBundle(dockerCli, opts) |
|
| 70 |
+ return deployBundle(ctx, dockerCli, opts) |
|
| 69 | 71 |
default: |
| 70 |
- return deployCompose(dockerCli, opts) |
|
| 72 |
+ return deployCompose(ctx, dockerCli, opts) |
|
| 71 | 73 |
} |
| 72 | 74 |
} |
| 73 | 75 |
|
| 74 |
-func deployCompose(dockerCli *command.DockerCli, opts deployOptions) error {
|
|
| 76 |
+// checkDaemonIsSwarmManager does an Info API call to verify that the daemon is |
|
| 77 |
+// a swarm manager. This is necessary because we must create networks before we |
|
| 78 |
+// create services, but the API call for creating a network does not return a |
|
| 79 |
+// proper status code when it can't create a network in the "global" scope. |
|
| 80 |
+func checkDaemonIsSwarmManager(ctx context.Context, dockerCli *command.DockerCli) error {
|
|
| 81 |
+ info, err := dockerCli.Client().Info(ctx) |
|
| 82 |
+ if err != nil {
|
|
| 83 |
+ return err |
|
| 84 |
+ } |
|
| 85 |
+ if !info.Swarm.ControlAvailable {
|
|
| 86 |
+ 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.")
|
|
| 87 |
+ } |
|
| 88 |
+ return nil |
|
| 89 |
+} |
|
| 90 |
+ |
|
| 91 |
+func deployCompose(ctx context.Context, dockerCli *command.DockerCli, opts deployOptions) error {
|
|
| 75 | 92 |
configDetails, err := getConfigDetails(opts) |
| 76 | 93 |
if err != nil {
|
| 77 | 94 |
return err |
| ... | ... |
@@ -99,7 +117,10 @@ func deployCompose(dockerCli *command.DockerCli, opts deployOptions) error {
|
| 99 | 99 |
propertyWarnings(deprecatedProperties)) |
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 |
- ctx := context.Background() |
|
| 102 |
+ if err := checkDaemonIsSwarmManager(ctx, dockerCli); err != nil {
|
|
| 103 |
+ return err |
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 103 | 106 |
namespace := namespace{name: opts.namespace}
|
| 104 | 107 |
|
| 105 | 108 |
networks := convertNetworks(namespace, config.Networks) |
| ... | ... |
@@ -8,12 +8,16 @@ import ( |
| 8 | 8 |
"github.com/docker/docker/cli/command" |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 |
-func deployBundle(dockerCli *command.DockerCli, opts deployOptions) error {
|
|
| 11 |
+func deployBundle(ctx context.Context, dockerCli *command.DockerCli, opts deployOptions) error {
|
|
| 12 | 12 |
bundle, err := loadBundlefile(dockerCli.Err(), opts.namespace, opts.bundlefile) |
| 13 | 13 |
if err != nil {
|
| 14 | 14 |
return err |
| 15 | 15 |
} |
| 16 | 16 |
|
| 17 |
+ if err := checkDaemonIsSwarmManager(ctx, dockerCli); err != nil {
|
|
| 18 |
+ return err |
|
| 19 |
+ } |
|
| 20 |
+ |
|
| 17 | 21 |
namespace := namespace{name: opts.namespace}
|
| 18 | 22 |
|
| 19 | 23 |
networks := make(map[string]types.NetworkCreate) |
| ... | ... |
@@ -71,8 +75,6 @@ func deployBundle(dockerCli *command.DockerCli, opts deployOptions) error {
|
| 71 | 71 |
services[internalName] = serviceSpec |
| 72 | 72 |
} |
| 73 | 73 |
|
| 74 |
- ctx := context.Background() |
|
| 75 |
- |
|
| 76 | 74 |
if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil {
|
| 77 | 75 |
return err |
| 78 | 76 |
} |