forked from flynn-archive/flynn-controller
/
utils.go
86 lines (81 loc) · 2.06 KB
/
utils.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
package utils
import (
"errors"
"net/url"
"strings"
ct "github.com/flynn/flynn-controller/types"
"github.com/flynn/flynn-host/types"
"github.com/flynn/go-dockerclient"
)
func FormatEnv(envs ...map[string]string) []string {
env := make(map[string]string)
for _, e := range envs {
for k, v := range e {
env[k] = v
}
}
res := make([]string, 0, len(env))
for k, v := range env {
res = append(res, k+"="+v)
}
return res
}
func DockerImage(uri string) (string, error) {
// TODO: ID refs (see https://github.com/dotcloud/docker/issues/4106)
u, err := url.Parse(uri)
if err != nil {
return "", err
}
if u.Scheme != "docker" {
return "", errors.New("utils: only docker artifact URIs are currently supported")
}
if tag := u.Query().Get("tag"); tag != "" {
u.Path += ":" + tag
}
if u.Host == "" {
// docker:///foo/bar results in u.Host == ""
u.Path = strings.TrimPrefix(u.Path, "/")
}
return u.Host + u.Path, nil
}
func JobConfig(f *ct.ExpandedFormation, name string) (*host.Job, error) {
t := f.Release.Processes[name]
image, err := DockerImage(f.Artifact.URI)
if err != nil {
return nil, err
}
job := &host.Job{
TCPPorts: t.Ports.TCP,
Attributes: map[string]string{
"flynn-controller.app": f.App.ID,
"flynn-controller.release": f.Release.ID,
"flynn-controller.type": name,
},
Config: &docker.Config{
Cmd: t.Cmd,
Env: FormatEnv(f.Release.Env, t.Env,
map[string]string{
"FLYNN_APP_ID": f.App.ID,
"FLYNN_RELEASE_ID": f.Release.ID,
},
),
Image: image,
},
}
if t.Data {
job.Config.Volumes = map[string]struct{}{"/data": {}}
}
if p := t.Env["FLYNN_HOST_PORTS"]; p != "" {
ports := strings.Split(p, ",")
job.HostConfig = &docker.HostConfig{
PortBindings: make(map[string][]docker.PortBinding, len(ports)),
PublishAllPorts: true,
}
job.Config.ExposedPorts = make(map[string]struct{}, len(ports))
for _, port := range ports {
job.Config.ExposedPorts[port+"/tcp"] = struct{}{}
job.HostConfig.PortBindings[port+"/tcp"] = []docker.PortBinding{{HostPort: port}}
}
}
return job, nil
}