iron_worker_ng 0.10.2 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/bin/iron_worker +130 -323
  2. data/lib/iron_worker_ng/cli.rb +275 -0
  3. data/lib/iron_worker_ng/client.rb +32 -20
  4. data/lib/iron_worker_ng/code/base.rb +45 -37
  5. data/lib/iron_worker_ng/code/builder.rb +4 -3
  6. data/lib/iron_worker_ng/code/container/base.rb +31 -0
  7. data/lib/iron_worker_ng/code/container/dir.rb +31 -0
  8. data/lib/iron_worker_ng/code/container/zip.rb +30 -0
  9. data/lib/iron_worker_ng/code/runtime/binary.rb +1 -3
  10. data/lib/iron_worker_ng/code/runtime/go.rb +1 -3
  11. data/lib/iron_worker_ng/code/runtime/java.rb +2 -3
  12. data/lib/iron_worker_ng/code/runtime/mono.rb +1 -3
  13. data/lib/iron_worker_ng/code/runtime/node.rb +1 -3
  14. data/lib/iron_worker_ng/code/runtime/perl.rb +1 -3
  15. data/lib/iron_worker_ng/code/runtime/php.rb +1 -3
  16. data/lib/iron_worker_ng/code/runtime/python.rb +1 -3
  17. data/lib/iron_worker_ng/code/runtime/ruby.rb +11 -9
  18. data/lib/iron_worker_ng/feature/base.rb +14 -20
  19. data/lib/iron_worker_ng/feature/common/merge_dir.rb +14 -5
  20. data/lib/iron_worker_ng/feature/common/merge_exec.rb +79 -0
  21. data/lib/iron_worker_ng/feature/common/merge_file.rb +13 -4
  22. data/lib/iron_worker_ng/feature/java/merge_jar.rb +12 -0
  23. data/lib/iron_worker_ng/feature/ruby/merge_gem.rb +11 -55
  24. data/lib/iron_worker_ng/feature/ruby/merge_gem_dependency.rb +76 -0
  25. data/lib/iron_worker_ng/fetcher.rb +39 -18
  26. data/lib/iron_worker_ng/version.rb +1 -1
  27. metadata +45 -17
  28. data/lib/iron_worker_ng/code/dir_container.rb +0 -33
  29. data/lib/iron_worker_ng/feature/binary/merge_exec.rb +0 -51
  30. data/lib/iron_worker_ng/feature/go/merge_exec.rb +0 -51
  31. data/lib/iron_worker_ng/feature/java/merge_exec.rb +0 -57
  32. data/lib/iron_worker_ng/feature/mono/merge_exec.rb +0 -51
  33. data/lib/iron_worker_ng/feature/node/merge_exec.rb +0 -51
  34. data/lib/iron_worker_ng/feature/perl/merge_exec.rb +0 -51
  35. data/lib/iron_worker_ng/feature/php/merge_exec.rb +0 -51
  36. data/lib/iron_worker_ng/feature/python/merge_exec.rb +0 -51
  37. data/lib/iron_worker_ng/feature/ruby/merge_exec.rb +0 -53
@@ -0,0 +1,275 @@
1
+ module IronWorkerNG
2
+ class CLI
3
+ LOG_ENTRY = ' '
4
+ LOG_GROUP = '------> '
5
+
6
+ def initialize
7
+ @client = nil
8
+
9
+ @env = nil
10
+ @project_id = nil
11
+ end
12
+
13
+ def beta?
14
+ ENV['IRON_BETA'] == '1'
15
+ end
16
+
17
+ def env=(env)
18
+ @client = nil
19
+
20
+ @env = env
21
+ end
22
+
23
+ def project_id=(project_id)
24
+ @client = nil
25
+
26
+ @project_id = project_id
27
+ end
28
+
29
+ def log(msg)
30
+ IronCore::Logger.info 'IronWorkerNG', msg
31
+ end
32
+
33
+ def log_group(msg)
34
+ IronCore::Logger.info 'IronWorkerNG', LOG_GROUP + msg
35
+ end
36
+
37
+ def client
38
+ if @client.nil?
39
+ log_group "Creating client"
40
+
41
+ @client = IronWorkerNG::Client.new(:env => @env, :project_id => @project_id)
42
+
43
+ project = client.projects.get
44
+
45
+ log "Project '#{project.name}' with id='#{project.id}'"
46
+ end
47
+
48
+ @client
49
+ end
50
+
51
+ def upload(name, params, options)
52
+ client
53
+
54
+ log_group "Creating code package"
55
+
56
+ code = IronWorkerNG::Code::Base.new(name)
57
+
58
+ code.name(params[:name]) unless params[:name].nil?
59
+
60
+ log "Code package name is '#{code.name}'"
61
+ log "Max concurrency set to '#{options[:max_concurrency]}'" unless options[:max_concurrency].nil?
62
+ log "Retries set to '#{options[:retries]}'" unless options[:retries].nil?
63
+ log "Retries delay set to '#{options[:retries_delay]}'" unless options[:retries_delay].nil?
64
+
65
+ if code.remote_build_command
66
+ log_group "Uploading and building code package '#{code.name}'"
67
+ else
68
+ log_group "Uploading code package '#{code.name}'"
69
+ end
70
+
71
+ if (params[:async] || params['async']) && code.remote_build_command
72
+ builder_task_id = client.codes.create_async(code, options)
73
+
74
+ log 'Code package is building'
75
+ log "Check 'https://hud.iron.io/tq/projects/#{client.api.project_id}/jobs/#{builder_task_id}' for more info"
76
+ else
77
+ code_id = client.codes.create(code, options).id
78
+ code_info = client.codes.get(code_id)
79
+
80
+ log "Code package uploaded with id='#{code_id}' and revision='#{code_info.rev}'"
81
+ log "Check 'https://hud.iron.io/tq/projects/#{client.api.project_id}/code/#{code_id}' for more info"
82
+ end
83
+ end
84
+
85
+ def queue(name, params, options)
86
+ client
87
+
88
+ log_group "Queueing task"
89
+
90
+ id = client.tasks.create(name, params[:payload] || params['payload'], options).id
91
+
92
+ log "Code package '#{name}' queued with id='#{id}'"
93
+ log "Check 'https://hud.iron.io/tq/projects/#{client.api.project_id}/jobs/#{id}' for more info"
94
+ end
95
+
96
+ def schedule(name, params, options)
97
+ client
98
+
99
+ log_group "Scheduling task"
100
+
101
+ id = client.schedules.create(name, params[:payload] || params['payload'], options).id
102
+
103
+ log "Code package '#{name}' scheduled with id='#{id}'"
104
+ log "Check 'https://hud.iron.io/tq/projects/#{client.api.project_id}/scheduled_jobs/#{id}' for more info"
105
+ end
106
+
107
+ def retry(task_id, params, options)
108
+ client
109
+
110
+ log_group "Retrying task with id='#{task_id}'"
111
+
112
+ retry_task_id = client.tasks.retry(task_id, options).id
113
+
114
+ log "Task retried with id='#{retry_task_id}'"
115
+ log "Check 'https://hud.iron.io/tq/projects/#{client.api.project_id}/jobs/#{retry_task_id}' for more info"
116
+ end
117
+
118
+ def getlog(task_id, params, options)
119
+ client
120
+
121
+ live = params[:live] || params['live']
122
+ wait = params[:wait] || params['wait']
123
+
124
+ log_group "Getting log for task with id='#{task_id}'"
125
+
126
+ log = ''
127
+
128
+ if live
129
+ begin
130
+ log = client.tasks.log(task_id)
131
+ rescue IronCore::Error
132
+ end
133
+ else
134
+ if wait
135
+ client.tasks.wait_for(task_id)
136
+ end
137
+
138
+ log = client.tasks.log(task_id)
139
+ end
140
+
141
+ print log
142
+
143
+ if live
144
+ client.tasks.wait_for(task_id) do |task|
145
+ if task.status == 'running'
146
+ begin
147
+ next_log = client.tasks.log(task_id)
148
+ print next_log[log.length .. - 1]
149
+ log = next_log
150
+ rescue IronCore::Error
151
+ end
152
+ end
153
+ end
154
+
155
+ begin
156
+ next_log = client.tasks.log(task_id)
157
+ print next_log[log.length .. - 1]
158
+ rescue IronCore::Error
159
+ end
160
+ end
161
+ end
162
+
163
+ def run(name, params, options)
164
+ log_group "Creating code package"
165
+
166
+ code = IronWorkerNG::Code::Base.new(name)
167
+
168
+ log "Code package name is '#{code.name}'"
169
+
170
+ log_group "Running '#{code.name}'"
171
+
172
+ code.run(params[:payload] || params['payload'])
173
+ end
174
+
175
+ def install(name, params, options)
176
+ log_group "Installing dependencies for code package with name='#{name}'"
177
+
178
+ code = IronWorkerNG::Code::Base.new(name)
179
+
180
+ code.install
181
+ end
182
+
183
+ def webhook(name, params, options)
184
+ client
185
+
186
+ log_group 'Generating code package webhook'
187
+
188
+ log 'You can invoke your worker by POSTing to the following URL'
189
+ log "#{client.api.url(client.api.project_id)}/tasks/webhook?code_name=#{name}&oauth=#{client.api.token}"
190
+ end
191
+
192
+ def info_code(name, params, options)
193
+ client
194
+
195
+ log_group 'Getting code package info'
196
+
197
+ codes = client.codes.list({:all => true})
198
+ code = codes.find { |code| code.name == name }
199
+
200
+ unless code
201
+ log_name "Code package with name='#{name}' not found"
202
+ exit 1
203
+ end
204
+
205
+ data = []
206
+ data << ['id', code.id]
207
+ data << ['name', code.name]
208
+ data << ['revision', code.rev]
209
+ data << ['uploaded', parse_time(code.latest_change) || '-']
210
+ data << ['max concurrency', code.max_concurrency || '-']
211
+ data << ['retries', code.retries || '-']
212
+ data << ['retries delay', code.retries_delay || '-']
213
+ data << ['info', "https://hud.iron.io/tq/projects/#{client.api.project_id}/code/#{code.id}"]
214
+ data << ['tasks info', "https://hud.iron.io/tq/projects/#{client.api.project_id}/jobs/#{code.id}/activity"]
215
+
216
+ display_table(data)
217
+ end
218
+
219
+ def info_task(task_id, params, options)
220
+ client
221
+
222
+ log_group 'Getting task info'
223
+
224
+ task = client.tasks.get(task_id)
225
+
226
+ data = []
227
+ data << ['id', task.id]
228
+ data << ['code package', task.code_name]
229
+ data << ['code revision', task.code_rev]
230
+ data << ['status', task.status]
231
+ data << ['priority', task.priority || 2]
232
+ data << ['queued', parse_time(task.created_at) || '-']
233
+ data << ['started', parse_time(task.start_time) || '-']
234
+ data << ['finished', parse_time(task.end_time) || '-']
235
+ data << ['payload', task.payload]
236
+ data << ['info', "https://hud.iron.io/tq/projects/#{client.api.project_id}/jobs/#{task.id}"]
237
+
238
+ display_table(data)
239
+ end
240
+
241
+ def info_schedule(schedule_id, params, options)
242
+ client
243
+
244
+ log_group 'Getting schedule info'
245
+
246
+ schedule = client.schedules.get(schedule_id)
247
+
248
+ data = []
249
+ data << ['id', schedule.id]
250
+ data << ['code package', schedule.code_name]
251
+ data << ['status', schedule.status]
252
+ data << ['created', parse_time(schedule.created_at) || '-']
253
+ data << ['next start', parse_time(schedule.next_start) || '-']
254
+ data << ['run count', schedule.run_count || '-']
255
+ data << ['payload', schedule.payload]
256
+ data << ['info', "https://hud.iron.io/tq/projects/#{client.api.project_id}/scheduled_jobs/#{schedule.id}"]
257
+
258
+ display_table(data)
259
+ end
260
+
261
+ def parse_time(s)
262
+ t = Time.parse(s)
263
+
264
+ return nil if t == Time.utc(1)
265
+
266
+ t
267
+ end
268
+
269
+ def display_table(t)
270
+ t.each do |r|
271
+ log sprintf('%-16s %s', r[0], r[1])
272
+ end
273
+ end
274
+ end
275
+ end
@@ -51,7 +51,7 @@ module IronWorkerNG
51
51
  def codes_list(options = {})
52
52
  IronCore::Logger.debug 'IronWorkerNG', "Calling codes.list with options='#{options.to_s}'"
53
53
 
54
- all = options.delete(:all) || options.delete('all')
54
+ all = options[:all] || options['all']
55
55
 
56
56
  if all
57
57
  result = []
@@ -60,9 +60,9 @@ module IronWorkerNG
60
60
  per_page = options[:per_page] || options['per_page'] || 100
61
61
 
62
62
  while true
63
- next_codes = codes_list(options.merge({:page => page}))
63
+ next_codes = codes_list(options.merge({:page => page}).delete_if { |name| name == :all || name == 'all' })
64
64
 
65
- result += next_codes
65
+ result += next_codes
66
66
 
67
67
  break if next_codes.length != per_page
68
68
  page += 1
@@ -83,40 +83,52 @@ module IronWorkerNG
83
83
  def codes_create(code, options = {})
84
84
  IronCore::Logger.debug 'IronWorkerNG', "Calling codes.create with code='#{code.to_s}' and options='#{options.to_s}'"
85
85
 
86
- async = options.delete(:async) || options.delete('async')
87
-
88
86
  container_file = code.create_container
89
87
 
90
88
  if code.remote_build_command.nil?
91
89
  res = @api.codes_create(code.name, container_file, 'sh', '__runner__.sh', options)
92
90
  else
93
- builder_code_name = code.name + (code.name.capitalize == code.name ? '::Builder' : '::builder')
94
-
95
- IronCore::Logger.info 'IronWorkerNG', 'Uploading builder'
91
+ builder_code_name = code.name + (code.name[0].upcase == code.name[0] ? '::Builder' : '::builder')
96
92
 
97
93
  @api.codes_create(builder_code_name, container_file, 'sh', '__runner__.sh', options)
98
94
 
99
95
  builder_task = tasks.create(builder_code_name, :code_name => code.name, :client_options => @api.options.to_json, :codes_create_options => options.to_json)
100
96
 
101
- if async
102
- IronCore::Logger.info 'IronWorkerNG', 'Running builder asynchronously'
97
+ builder_task = tasks.wait_for(builder_task.id)
98
+
99
+ if builder_task.status != 'complete'
100
+ log = tasks.log(builder_task.id)
103
101
 
104
102
  File.unlink(container_file)
105
103
 
106
- return builder_task.id
104
+ IronCore::Logger.error 'IronWorkerNG', "Error while remote building worker\n" + log, IronCore::Error
107
105
  end
108
106
 
109
- IronCore::Logger.info 'IronWorkerNG', 'Waiting for builder to complete'
107
+ res = JSON.parse(builder_task.msg)
108
+ end
110
109
 
111
- builder_task = tasks.wait_for(builder_task.id)
110
+ File.unlink(container_file)
112
111
 
113
- unless builder_task.status == 'complete'
114
- log = tasks.log(builder_task.id)
112
+ OpenStruct.new(res)
113
+ end
115
114
 
116
- IronCore::Logger.error 'IronWorkerNG', 'Error while remote building worker: ' + log, IronCore::Error
117
- end
115
+ def codes_create_async(code, options = {})
116
+ IronCore::Logger.debug 'IronWorkerNG', "Calling codes.create_async with code='#{code.to_s}' and options='#{options.to_s}'"
118
117
 
119
- res = JSON.parse(builder_task.msg)
118
+ container_file = code.create_container
119
+
120
+ if code.remote_build_command.nil?
121
+ res = @api.codes_create(code.name, container_file, 'sh', '__runner__.sh', options)
122
+ else
123
+ builder_code_name = code.name + (code.name[0].upcase == code.name[0] ? '::Builder' : '::builder')
124
+
125
+ @api.codes_create(builder_code_name, container_file, 'sh', '__runner__.sh', options)
126
+
127
+ builder_task = tasks.create(builder_code_name, :code_name => code.name, :client_options => @api.options.to_json, :codes_create_options => options.to_json)
128
+
129
+ File.unlink(container_file)
130
+
131
+ return builder_task.id
120
132
  end
121
133
 
122
134
  File.unlink(container_file)
@@ -202,7 +214,7 @@ module IronWorkerNG
202
214
  true
203
215
  end
204
216
 
205
- def tasks_wait_for(task_id, options = {})
217
+ def tasks_wait_for(task_id, options = {}, &block)
206
218
  IronCore::Logger.debug 'IronWorkerNG', "Calling tasks.wait_for with task_id='#{task_id}' and options='#{options.to_s}'"
207
219
 
208
220
  options[:sleep] ||= options['sleep'] || 5
@@ -210,7 +222,7 @@ module IronWorkerNG
210
222
  task = tasks_get(task_id)
211
223
 
212
224
  while task.status == 'queued' || task.status == 'running'
213
- yield task if block_given?
225
+ block.call(task) unless block.nil?
214
226
  sleep options[:sleep]
215
227
  task = tasks_get(task_id)
216
228
  end
@@ -1,9 +1,10 @@
1
- require 'tmpdir'
2
- require 'zip/zip'
3
1
  require 'fileutils'
4
2
 
5
- require_relative 'dir_container'
3
+ require_relative 'container/base'
4
+ require_relative 'container/zip'
5
+ require_relative 'container/dir'
6
6
  require_relative '../feature/base'
7
+ require_relative '../feature/common/merge_exec'
7
8
  require_relative '../feature/common/merge_file'
8
9
  require_relative '../feature/common/merge_dir'
9
10
 
@@ -38,19 +39,19 @@ module IronWorkerNG
38
39
 
39
40
  @inside_builder = false
40
41
 
41
- wfiles = []
42
+ worker_files = []
42
43
 
43
44
  if args.length == 1 && args[0].is_a?(String)
44
- if args[0].end_with?('.worker') || args[0].end_with?('.workerfile')
45
- @name = args[0].gsub(/\.worker$/, '').gsub(/\.workerfile$/, '')
45
+ if args[0].end_with?('.worker')
46
+ @name = args[0].gsub(/\.worker$/, '')
46
47
  else
47
48
  @name = args[0]
48
49
  end
49
50
  elsif args.length == 1 && args[0].is_a?(Hash)
50
51
  @name = args[0][:name] || args[0]['name']
51
52
 
52
- wfile = args[0][:workerfile] || args[0]['workerfile']
53
- wfiles << wfile unless wfile.nil?
53
+ worker_file = args[0][:workerfile] || args[0]['workerfile']
54
+ worker_files << worker_file unless worker_file.nil?
54
55
 
55
56
  exec = args[0][:exec] || args[0]['exec'] || args[0][:worker] || args[0]['worker']
56
57
  unless exec.nil?
@@ -63,23 +64,20 @@ module IronWorkerNG
63
64
  end
64
65
 
65
66
  unless @name.nil?
66
- wfiles << @name + '.worker'
67
- wfiles << @name + '.workerfile'
67
+ worker_files << @name + '.worker'
68
68
  end
69
69
 
70
- wfiles << 'Workerfile'
70
+ worker_files.each do |worker_file|
71
+ IronWorkerNG::Fetcher.fetch(worker_file) do |content|
72
+ unless content.nil?
73
+ IronCore::Logger.info 'IronWorkerNG', "Found workerfile with path='#{worker_file}'"
71
74
 
72
- wfiles.each do |wfile|
73
- src, clean = IronWorkerNG::Fetcher.fetch(wfile)
75
+ eval(content)
74
76
 
75
- unless src.nil?
76
- IronCore::Logger.info 'IronWorkerNG', "Found workerfile with path='#{wfile}'"
77
+ @base_dir = File.dirname(worker_file) == '.' ? '' : File.dirname(worker_file) + '/'
77
78
 
78
- eval(src)
79
-
80
- @base_dir = File.dirname(wfile) == '.' ? '' : File.dirname(wfile) + '/'
81
-
82
- break
79
+ break
80
+ end
83
81
  end
84
82
  end
85
83
 
@@ -228,33 +226,29 @@ RUNNER
228
226
 
229
227
  fixate
230
228
 
231
- container_name = Dir.tmpdir + '/' + Dir::Tmpname.make_tmpname('iron-worker-ng-', "container#{local ? '' : '.zip'}")
229
+ container = local ? IronWorkerNG::Code::Container::Dir.new : IronWorkerNG::Code::Container::Zip.new
232
230
 
233
- IronCore::Logger.debug 'IronWorkerNG', "Creating #{local ? 'local ' : ''}code container '#{container_name}'"
231
+ IronCore::Logger.debug 'IronWorkerNG', "Creating #{local ? 'local ' : ''}code container '#{container.name}'"
234
232
 
235
233
  if local
236
- container = IronWorkerNG::Code::DirContainer.new(container_name)
237
-
238
234
  bundle(container)
239
235
  else
240
236
  if @remote_build_command
241
237
  @dest_dir = '__build__/'
242
238
  end
243
239
 
244
- Zip::ZipFile.open(container_name, Zip::ZipFile::CREATE) do |container|
245
- bundle(container)
240
+ bundle(container)
246
241
 
247
- if @remote_build_command
248
- IronCore::Logger.info 'IronWorkerNG', 'Creating builder'
242
+ if @remote_build_command
243
+ IronCore::Logger.info 'IronWorkerNG', 'Creating builder'
249
244
 
250
- builder = IronWorkerNG::Code::Builder.new
251
- builder.remote_build_command = @remote_build_command
245
+ builder = IronWorkerNG::Code::Builder.new
246
+ builder.remote_build_command = @remote_build_command
252
247
 
253
- builder.gem('iron_worker_ng')
254
-
255
- builder.fixate
256
- builder.bundle(container)
257
- end
248
+ builder.gem('iron_worker_ng')
249
+ builder.fixate
250
+
251
+ builder.bundle(container)
258
252
  end
259
253
 
260
254
  if @remote_build_command
@@ -262,7 +256,9 @@ RUNNER
262
256
  end
263
257
  end
264
258
 
265
- container_name
259
+ container.close
260
+
261
+ container.name
266
262
  end
267
263
 
268
264
  def run(params = {})
@@ -278,12 +274,24 @@ RUNNER
278
274
 
279
275
  system("sh #{container_name}/__runner__.sh -d #{container_name} -payload #{container_name}/__payload__ -id 0")
280
276
 
281
- FileUtils.rm_f(container_name)
277
+ FileUtils.rm_rf(container_name)
282
278
  end
283
279
 
284
280
  def install
285
281
  end
286
282
 
283
+ def workerfile(remote = false)
284
+ commands = []
285
+
286
+ commands << "runtime '#{runtime}'"
287
+ commands << "name '#{name}'"
288
+ commands << "build '#{remote_build_command}'"
289
+
290
+ commands << @features.map { |f| f.command(remote) }
291
+
292
+ commands.compact.join("\n")
293
+ end
294
+
287
295
  def to_s
288
296
  "runtime='#{@runtime}', name='#{@name}', exec='#{@inside_builder || @exec.nil? ? '' : @exec.path}'"
289
297
  end