forked from flynn/flynn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun_app_action.go
123 lines (110 loc) · 2.59 KB
/
run_app_action.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
123
package bootstrap
import (
"errors"
ct "github.com/flynn/flynn/controller/types"
"github.com/flynn/flynn/controller/utils"
"github.com/flynn/flynn/pkg/random"
"github.com/flynn/flynn/pkg/resource"
)
type RunAppAction struct {
*ct.ExpandedFormation
ID string `json:"id"`
AppStep string `json:"app_step"`
Resources []*ct.Provider `json:"resources,omitempty"`
}
type Provider struct {
Name string `json:"name"`
URL string `json:"url"`
}
func init() {
Register("run-app", &RunAppAction{})
}
type RunAppState struct {
*ct.ExpandedFormation
Providers []*ct.Provider `json:"providers"`
Resources []*resource.Resource `json:"resources"`
Jobs []Job `json:"jobs"`
}
type Job struct {
HostID string `json:"host_id"`
JobID string `json:"job_id"`
}
func (a *RunAppAction) Run(s *State) error {
if a.AppStep != "" {
data, err := getAppStep(s, a.AppStep)
if err != nil {
return err
}
a.App = data.App
procs := a.Processes
a.ExpandedFormation = data.ExpandedFormation
a.Processes = procs
}
as := &RunAppState{
ExpandedFormation: a.ExpandedFormation,
Resources: make([]*resource.Resource, 0, len(a.Resources)),
Providers: make([]*ct.Provider, 0, len(a.Resources)),
}
s.StepData[a.ID] = as
if a.App == nil {
a.App = &ct.App{}
}
if a.App.ID == "" {
a.App.ID = random.UUID()
}
if a.Artifact == nil {
return errors.New("bootstrap: artifact must be set")
}
if a.Artifact.ID == "" {
a.Artifact.ID = random.UUID()
}
if a.Release == nil {
return errors.New("bootstrap: release must be set")
}
if a.Release.ID == "" {
a.Release.ID = random.UUID()
}
a.Release.ArtifactID = a.Artifact.ID
if a.Release.Env == nil {
a.Release.Env = make(map[string]string)
}
interpolateRelease(s, a.Release)
for _, p := range a.Resources {
server, err := resource.NewServer(p.URL)
if err != nil {
return err
}
res, err := server.Provision(nil)
server.Close()
if err != nil {
return err
}
as.Providers = append(as.Providers, p)
as.Resources = append(as.Resources, res)
for k, v := range res.Env {
a.Release.Env[k] = v
}
}
cc, err := s.ClusterClient()
if err != nil {
return err
}
hosts, err := cc.ListHosts()
if err != nil {
return err
}
hostIDs := make([]string, 0, len(hosts))
for id := range hosts {
hostIDs = append(hostIDs, id)
}
for typ, count := range a.Processes {
for i := 0; i < count; i++ {
job, err := startJob(s, hostIDs[i%len(hosts)], utils.JobConfig(a.ExpandedFormation, typ))
if err != nil {
return err
}
as.Jobs = append(as.Jobs, *job)
}
}
return nil
}