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 }