1
1
package cli
2
2
3
3
import (
4
- "os"
5
-
6
- docker "github.com/fsouza/go-dockerclient"
7
4
"github.com/mcuadros/ofelia/core"
8
5
"github.com/mcuadros/ofelia/middlewares"
9
- logging "github.com/op/go-logging"
10
6
11
7
defaults "github.com/mcuadros/go-defaults"
12
8
gcfg "gopkg.in/gcfg.v1"
@@ -20,132 +16,223 @@ const (
20
16
jobLocal = "job-local"
21
17
)
22
18
23
- var IsDockerEnv bool
24
-
25
19
// Config contains the configuration
26
20
type Config struct {
27
21
Global struct {
28
22
middlewares.SlackConfig `mapstructure:",squash"`
29
23
middlewares.SaveConfig `mapstructure:",squash"`
30
24
middlewares.MailConfig `mapstructure:",squash"`
31
25
}
32
- ExecJobs map [string ]* ExecJobConfig `gcfg:"job-exec" mapstructure:"job-exec,squash"`
33
- RunJobs map [string ]* RunJobConfig `gcfg:"job-run" mapstructure:"job-run,squash"`
34
- ServiceJobs map [string ]* RunServiceConfig `gcfg:"job-service-run" mapstructure:"job-service-run,squash"`
35
- LocalJobs map [string ]* LocalJobConfig `gcfg:"job-local" mapstructure:"job-local,squash"`
26
+ ExecJobs map [string ]* ExecJobConfig `gcfg:"job-exec" mapstructure:"job-exec,squash"`
27
+ RunJobs map [string ]* RunJobConfig `gcfg:"job-run" mapstructure:"job-run,squash"`
28
+ ServiceJobs map [string ]* RunServiceConfig `gcfg:"job-service-run" mapstructure:"job-service-run,squash"`
29
+ LocalJobs map [string ]* LocalJobConfig `gcfg:"job-local" mapstructure:"job-local,squash"`
30
+ sh * core.Scheduler
31
+ dockerHandler * DockerHandler
32
+ logger core.Logger
36
33
}
37
34
38
- // BuildFromDockerLabels builds a scheduler using the config from a docker labels
39
- func BuildFromDockerLabels () (* core.Scheduler , error ) {
40
- c := & Config {}
41
-
42
- d , err := c .buildDockerClient ()
43
- if err != nil {
44
- return nil , err
45
- }
46
-
47
- labels , err := getLabels (d )
48
- if err != nil {
49
- return nil , err
50
- }
51
-
52
- if err := c .buildFromDockerLabels (labels ); err != nil {
53
- return nil , err
35
+ func NewConfig (logger core.Logger ) * Config {
36
+ c := & Config {
37
+ ExecJobs : make (map [string ]* ExecJobConfig ),
38
+ RunJobs : make (map [string ]* RunJobConfig ),
39
+ ServiceJobs : make (map [string ]* RunServiceConfig ),
40
+ LocalJobs : make (map [string ]* LocalJobConfig ),
41
+ logger : logger ,
54
42
}
55
43
56
- return c .build ()
44
+ defaults .SetDefaults (c )
45
+ return c
57
46
}
58
47
59
48
// BuildFromFile builds a scheduler using the config from a file
60
- func BuildFromFile (filename string ) (* core.Scheduler , error ) {
61
- c := & Config {}
62
- if err := gcfg .ReadFileInto (c , filename ); err != nil {
63
- return nil , err
64
- }
65
-
66
- return c .build ()
49
+ func BuildFromFile (filename string , logger core.Logger ) (* Config , error ) {
50
+ c := NewConfig (logger )
51
+ err := gcfg .ReadFileInto (c , filename )
52
+ return c , err
67
53
}
68
54
69
55
// BuildFromString builds a scheduler using the config from a string
70
- func BuildFromString (config string ) (* core. Scheduler , error ) {
71
- c := & Config {}
56
+ func BuildFromString (config string , logger core. Logger ) (* Config , error ) {
57
+ c := NewConfig ( logger )
72
58
if err := gcfg .ReadStringInto (c , config ); err != nil {
73
59
return nil , err
74
60
}
75
-
76
- return c .build ()
61
+ return c , nil
77
62
}
78
63
79
- func (c * Config ) build () (* core.Scheduler , error ) {
80
- defaults .SetDefaults (c )
64
+ // Call this only once at app init
65
+ func (c * Config ) InitializeApp () error {
66
+ c .sh = core .NewScheduler (c .logger )
67
+ c .buildSchedulerMiddlewares (c .sh )
81
68
82
- d , err := c .buildDockerClient ()
69
+ var err error
70
+ c .dockerHandler , err = NewDockerHandler (c , c .logger )
83
71
if err != nil {
84
- return nil , err
72
+ return err
85
73
}
86
74
87
- sh := core .NewScheduler (c .buildLogger ())
88
- c .buildSchedulerMiddlewares (sh )
75
+ // In order to support non dynamic job types such as Local or Run using labels
76
+ // lets parse the labels and merge the job lists
77
+ dockerLabels , err := c .dockerHandler .GetDockerLabels ()
78
+ var parsedLabelConfig Config
79
+ parsedLabelConfig .buildFromDockerLabels (dockerLabels )
80
+ for name , j := range parsedLabelConfig .RunJobs {
81
+ c .RunJobs [name ] = j
82
+ }
83
+ for name , j := range parsedLabelConfig .LocalJobs {
84
+ c .LocalJobs [name ] = j
85
+ }
86
+ for name , j := range parsedLabelConfig .ServiceJobs {
87
+ c .ServiceJobs [name ] = j
88
+ }
89
89
90
90
for name , j := range c .ExecJobs {
91
91
defaults .SetDefaults (j )
92
-
93
- j .Client = d
92
+ j .Client = c .dockerHandler .GetInternalDockerClient ()
94
93
j .Name = name
95
94
j .buildMiddlewares ()
96
- sh .AddJob (j )
95
+ c . sh .AddJob (j )
97
96
}
98
97
99
98
for name , j := range c .RunJobs {
100
99
defaults .SetDefaults (j )
101
-
102
- j .Client = d
100
+ j .Client = c .dockerHandler .GetInternalDockerClient ()
103
101
j .Name = name
104
102
j .buildMiddlewares ()
105
- sh .AddJob (j )
103
+ c . sh .AddJob (j )
106
104
}
107
105
108
106
for name , j := range c .LocalJobs {
109
107
defaults .SetDefaults (j )
110
-
111
108
j .Name = name
112
109
j .buildMiddlewares ()
113
- sh .AddJob (j )
110
+ c . sh .AddJob (j )
114
111
}
115
112
116
113
for name , j := range c .ServiceJobs {
117
114
defaults .SetDefaults (j )
118
115
j .Name = name
119
- j .Client = d
116
+ j .Client = c . dockerHandler . GetInternalDockerClient ()
120
117
j .buildMiddlewares ()
121
- sh .AddJob (j )
118
+ c . sh .AddJob (j )
122
119
}
123
120
124
- return sh , nil
121
+ return nil
125
122
}
126
123
127
- func (c * Config ) buildDockerClient () (* docker.Client , error ) {
128
- d , err := docker .NewClientFromEnv ()
129
- if err != nil {
130
- return nil , err
124
+ func (c * Config ) buildSchedulerMiddlewares (sh * core.Scheduler ) {
125
+ sh .Use (middlewares .NewSlack (& c .Global .SlackConfig ))
126
+ sh .Use (middlewares .NewSave (& c .Global .SaveConfig ))
127
+ sh .Use (middlewares .NewMail (& c .Global .MailConfig ))
128
+ }
129
+
130
+ func (c * Config ) dockerLabelsUpdate (labels map [string ]map [string ]string ) {
131
+ // Get the current labels
132
+ var parsedLabelConfig Config
133
+ parsedLabelConfig .buildFromDockerLabels (labels )
134
+
135
+ // Calculate the delta execJobs
136
+ for name , j := range c .ExecJobs {
137
+ found := false
138
+ for newJobsName , newJob := range parsedLabelConfig .ExecJobs {
139
+ // Check if the schedule has changed
140
+ if name == newJobsName {
141
+ found = true
142
+ // There is a slight race condition were a job can be canceled / restarted with different params
143
+ // so, lets take care of it by simply restarting
144
+ // For the hash to work properly, we must fill the fields before calling it
145
+ defaults .SetDefaults (newJob )
146
+ newJob .Client = c .dockerHandler .GetInternalDockerClient ()
147
+ newJob .Name = newJobsName
148
+ if newJob .Hash () != j .Hash () {
149
+ // Remove from the scheduler
150
+ c .sh .RemoveJob (j )
151
+ // Add the job back to the scheduler
152
+ newJob .buildMiddlewares ()
153
+ c .sh .AddJob (newJob )
154
+ // Update the job config
155
+ c .ExecJobs [name ] = newJob
156
+ }
157
+ break
158
+ }
159
+ }
160
+ if ! found {
161
+ // Remove the job
162
+ c .sh .RemoveJob (j )
163
+ delete (c .ExecJobs , name )
164
+ }
131
165
}
132
166
133
- return d , nil
134
- }
167
+ // Check for aditions
168
+ for newJobsName , newJob := range parsedLabelConfig .ExecJobs {
169
+ found := false
170
+ for name := range c .ExecJobs {
171
+ if name == newJobsName {
172
+ found = true
173
+ break
174
+ }
175
+ }
176
+ if ! found {
177
+ defaults .SetDefaults (newJob )
178
+ newJob .Client = c .dockerHandler .GetInternalDockerClient ()
179
+ newJob .Name = newJobsName
180
+ newJob .buildMiddlewares ()
181
+ c .sh .AddJob (newJob )
182
+ c .ExecJobs [newJobsName ] = newJob
183
+ }
184
+ }
135
185
136
- func (c * Config ) buildLogger () core.Logger {
137
- stdout := logging .NewLogBackend (os .Stdout , "" , 0 )
138
- // Set the backends to be used.
139
- logging .SetBackend (stdout )
140
- logging .SetFormatter (logging .MustStringFormatter (logFormat ))
186
+ for name , j := range c .RunJobs {
187
+ found := false
188
+ for newJobsName , newJob := range parsedLabelConfig .RunJobs {
189
+ // Check if the schedule has changed
190
+ if name == newJobsName {
191
+ found = true
192
+ // There is a slight race condition were a job can be canceled / restarted with different params
193
+ // so, lets take care of it by simply restarting
194
+ // For the hash to work properly, we must fill the fields before calling it
195
+ defaults .SetDefaults (newJob )
196
+ newJob .Client = c .dockerHandler .GetInternalDockerClient ()
197
+ newJob .Name = newJobsName
198
+ if newJob .Hash () != j .Hash () {
199
+ // Remove from the scheduler
200
+ c .sh .RemoveJob (j )
201
+ // Add the job back to the scheduler
202
+ newJob .buildMiddlewares ()
203
+ c .sh .AddJob (newJob )
204
+ // Update the job config
205
+ c .RunJobs [name ] = newJob
206
+ }
207
+ break
208
+ }
209
+ }
210
+ if ! found {
211
+ // Remove the job
212
+ c .sh .RemoveJob (j )
213
+ delete (c .RunJobs , name )
214
+ }
215
+ }
141
216
142
- return logging .MustGetLogger ("ofelia" )
143
- }
217
+ // Check for aditions
218
+ for newJobsName , newJob := range parsedLabelConfig .RunJobs {
219
+ found := false
220
+ for name := range c .RunJobs {
221
+ if name == newJobsName {
222
+ found = true
223
+ break
224
+ }
225
+ }
226
+ if ! found {
227
+ defaults .SetDefaults (newJob )
228
+ newJob .Client = c .dockerHandler .GetInternalDockerClient ()
229
+ newJob .Name = newJobsName
230
+ newJob .buildMiddlewares ()
231
+ c .sh .AddJob (newJob )
232
+ c .RunJobs [newJobsName ] = newJob
233
+ }
234
+ }
144
235
145
- func (c * Config ) buildSchedulerMiddlewares (sh * core.Scheduler ) {
146
- sh .Use (middlewares .NewSlack (& c .Global .SlackConfig ))
147
- sh .Use (middlewares .NewSave (& c .Global .SaveConfig ))
148
- sh .Use (middlewares .NewMail (& c .Global .MailConfig ))
149
236
}
150
237
151
238
// ExecJobConfig contains all configuration params needed to build a ExecJob
0 commit comments