123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- 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
- }
|