-
Notifications
You must be signed in to change notification settings - Fork 1
/
compose.go
122 lines (112 loc) · 3.03 KB
/
compose.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"text/template"
"github.com/docker/docker/client"
)
const composeTemplate = `# generated by integration-cli-on-swarm
version: "3"
services:
worker:
image: "{{.WorkerImage}}"
command: ["-worker-image-digest={{.WorkerImageDigest}}", "-dry-run={{.DryRun}}", "-keep-executor={{.KeepExecutor}}"]
networks:
- net
volumes:
# Bind-mount the API socket so that we can invoke "docker run --privileged" within the service containers
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DOCKER_GRAPHDRIVER={{.EnvDockerGraphDriver}}
- DOCKER_EXPERIMENTAL={{.EnvDockerExperimental}}
deploy:
mode: replicated
replicas: {{.Replicas}}
restart_policy:
# The restart condition needs to be any for funker function
condition: any
master:
image: "{{.MasterImage}}"
command: ["-worker-service=worker", "-input=/mnt/input", "-chunks={{.Chunks}}", "-shuffle={{.Shuffle}}", "-rand-seed={{.RandSeed}}"]
networks:
- net
volumes:
- {{.Volume}}:/mnt
deploy:
mode: replicated
replicas: 1
restart_policy:
condition: none
placement:
# Make sure the master can access the volume
constraints: [node.id == {{.SelfNodeID}}]
networks:
net:
volumes:
{{.Volume}}:
external: true
`
type composeOptions struct {
Replicas int
Chunks int
MasterImage string
WorkerImage string
Volume string
Shuffle bool
RandSeed int64
DryRun bool
KeepExecutor bool
}
type composeTemplateOptions struct {
composeOptions
WorkerImageDigest string
SelfNodeID string
EnvDockerGraphDriver string
EnvDockerExperimental string
}
// createCompose creates "dir/docker-compose.yml".
// If dir is empty, TempDir() is used.
func createCompose(dir string, cli *client.Client, opts composeOptions) (string, error) {
if dir == "" {
var err error
dir, err = ioutil.TempDir("", "integration-cli-on-swarm-")
if err != nil {
return "", err
}
}
resolved := composeTemplateOptions{}
resolved.composeOptions = opts
workerImageInspect, _, err := cli.ImageInspectWithRaw(context.Background(), defaultWorkerImageName)
if err != nil {
return "", err
}
if len(workerImageInspect.RepoDigests) > 0 {
resolved.WorkerImageDigest = workerImageInspect.RepoDigests[0]
} else {
// fall back for non-pushed image
resolved.WorkerImageDigest = workerImageInspect.ID
}
info, err := cli.Info(context.Background())
if err != nil {
return "", err
}
resolved.SelfNodeID = info.Swarm.NodeID
resolved.EnvDockerGraphDriver = os.Getenv("DOCKER_GRAPHDRIVER")
resolved.EnvDockerExperimental = os.Getenv("DOCKER_EXPERIMENTAL")
composeFilePath := filepath.Join(dir, "docker-compose.yml")
tmpl, err := template.New("").Parse(composeTemplate)
if err != nil {
return "", err
}
f, err := os.Create(composeFilePath)
if err != nil {
return "", err
}
defer f.Close()
if err = tmpl.Execute(f, resolved); err != nil {
return "", err
}
return composeFilePath, nil
}