ubalo 0.0.22 → 0.0.23
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.
- data/bin/ubalo +33 -79
- data/lib/ubalo.rb +60 -69
- data/lib/ubalo/version.rb +3 -1
- metadata +10 -11
data/bin/ubalo
CHANGED
@@ -139,7 +139,9 @@ def process_download response, destination_path=nil
|
|
139
139
|
end
|
140
140
|
|
141
141
|
files.each do |filename,content|
|
142
|
-
File.
|
142
|
+
local_filename = File.join(destination_path, filename)
|
143
|
+
FileUtils.mkdir_p(File.dirname(local_filename))
|
144
|
+
File.open(local_filename, "w") do |f|
|
143
145
|
f.puts content
|
144
146
|
end
|
145
147
|
end
|
@@ -217,18 +219,24 @@ end
|
|
217
219
|
desc 'Delete a pod'
|
218
220
|
arg_name '<pod name>'
|
219
221
|
command :delete do |c|
|
222
|
+
c.switch :force
|
223
|
+
|
220
224
|
c.action do |global_options,options,args|
|
221
225
|
pod_name = normalize_pod_name(args.shift)
|
222
226
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
227
|
+
if options.force
|
228
|
+
ubalo.delete_pod(pod_name)
|
229
|
+
else
|
230
|
+
hl.choose do |menu|
|
231
|
+
menu.prompt = "Are you sure you want to delete #{pod_name}? "
|
232
|
+
menu.choice :yes do
|
233
|
+
$stderr.print "Deleting #{pod_name}..."
|
234
|
+
response = ubalo.delete_pod(pod_name)
|
235
|
+
$stderr.puts " done."
|
236
|
+
end
|
237
|
+
menu.choice :no do
|
238
|
+
raise UbaloMessage, "Cancelled! No changes made to #{pod_name}."
|
239
|
+
end
|
232
240
|
end
|
233
241
|
end
|
234
242
|
end
|
@@ -237,84 +245,43 @@ end
|
|
237
245
|
desc 'Run a pod'
|
238
246
|
arg_name '<pod name>'
|
239
247
|
command :run do |c|
|
240
|
-
c.desc 'Use JSON for input and output'
|
241
|
-
c.switch :json
|
242
|
-
|
243
248
|
c.action do |global_options,options,args|
|
244
249
|
pod_name = normalize_pod_name(args.shift)
|
245
|
-
|
246
|
-
|
247
|
-
else
|
248
|
-
arg = args.join(" ")
|
249
|
-
$stderr.print "Running #{pod_name}..."
|
250
|
-
end
|
250
|
+
arg = args.join(" ")
|
251
|
+
$stderr.print "Running #{pod_name}..."
|
251
252
|
|
252
253
|
response = ubalo.submit_task(pod_name, arg)
|
253
254
|
task_label = response.fetch('label')
|
254
|
-
result = ubalo.wait_task(task_label
|
255
|
-
ubalo.show_result(result
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
def receive_json_from_stdin
|
260
|
-
if $stdin.tty?
|
261
|
-
raise UbaloMessage, "please pipe to stdin when using --json"
|
262
|
-
else
|
263
|
-
JSON.parse($stdin.read)
|
255
|
+
result = ubalo.wait_task(task_label)
|
256
|
+
ubalo.show_result(result)
|
264
257
|
end
|
265
258
|
end
|
266
259
|
|
267
260
|
desc 'Submit a pod for running in the background'
|
268
261
|
arg_name '<pod name>'
|
269
262
|
command :submit do |c|
|
270
|
-
c.desc 'Receive JSON from stdin'
|
271
|
-
c.switch :json
|
272
|
-
|
273
263
|
c.action do |global_options,options,args|
|
274
|
-
|
275
|
-
args = receive_json_from_stdin
|
276
|
-
result = ubalo.submit_task_json(args)
|
277
|
-
else
|
278
|
-
pod_name = normalize_pod_name(args.shift)
|
264
|
+
pod_name = normalize_pod_name(args.shift)
|
279
265
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
ubalo.show_result(result
|
266
|
+
$stderr.print "Submitting #{pod_name}..."
|
267
|
+
result = ubalo.submit_task(pod_name, args.join(" "))
|
268
|
+
$stderr.puts " submitted."
|
269
|
+
|
270
|
+
ubalo.show_result(result)
|
285
271
|
end
|
286
272
|
end
|
287
273
|
|
288
274
|
desc 'Check or get the result of a task'
|
289
275
|
arg_name '<task label>'
|
290
276
|
command :check do |c|
|
291
|
-
c.desc 'Get details and give output as JSON'
|
292
|
-
c.switch :json
|
293
|
-
|
294
277
|
c.action do |global_options,options,args|
|
295
|
-
|
296
|
-
args = receive_json_from_stdin
|
297
|
-
result = ubalo.check_task_json(args)
|
298
|
-
else
|
299
|
-
task_label = args.first
|
300
|
-
|
301
|
-
$stderr.print "Checking task #{task_label}..."
|
302
|
-
result = ubalo.check_task(task_label)
|
303
|
-
$stderr.puts " found."
|
304
|
-
end
|
278
|
+
task_label = args.first
|
305
279
|
|
306
|
-
|
307
|
-
|
308
|
-
|
280
|
+
$stderr.print "Checking task #{task_label}..."
|
281
|
+
result = ubalo.check_task(task_label)
|
282
|
+
$stderr.puts " found."
|
309
283
|
|
310
|
-
|
311
|
-
arg_name '<task label>'
|
312
|
-
command :stop do |c|
|
313
|
-
c.action do |global_options,options,args|
|
314
|
-
task_label = args.first
|
315
|
-
$stderr.print "Stopping task #{task_label}..."
|
316
|
-
result = ubalo.stop_task(task_label)
|
317
|
-
$stderr.puts " stopped."
|
284
|
+
ubalo.show_result(result)
|
318
285
|
end
|
319
286
|
end
|
320
287
|
|
@@ -428,19 +395,6 @@ command :unpublish do |c|
|
|
428
395
|
end
|
429
396
|
end
|
430
397
|
|
431
|
-
|
432
|
-
# XXX testing
|
433
|
-
command :upload do |c|
|
434
|
-
c.action do |global_options,options,args|
|
435
|
-
while filename = args.shift
|
436
|
-
$stderr.print "Uploading #{filename.inspect}..."
|
437
|
-
response = ubalo.s3_put filename
|
438
|
-
$stderr.puts " done."
|
439
|
-
puts "Saved as #{response.inspect}."
|
440
|
-
end
|
441
|
-
end
|
442
|
-
end
|
443
|
-
|
444
398
|
def unauthorized_command?(command)
|
445
399
|
command && [:login, :help].include?(command.name)
|
446
400
|
end
|
data/lib/ubalo.rb
CHANGED
@@ -51,12 +51,41 @@ class UbaloMessage < StandardError
|
|
51
51
|
end
|
52
52
|
|
53
53
|
class Ubalo
|
54
|
-
class
|
54
|
+
class UbaloJSON
|
55
|
+
def self.content_type
|
56
|
+
"application/json; schema=ubalo-data"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.dump(obj)
|
60
|
+
JSON.dump('data' => obj)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.load(data)
|
64
|
+
JSON.load(data)['data']
|
65
|
+
end
|
55
66
|
end
|
56
|
-
|
67
|
+
|
68
|
+
class PodError < StandardError
|
57
69
|
end
|
58
70
|
|
59
71
|
class << self
|
72
|
+
def print_content name, content
|
73
|
+
data = content.fetch('data')
|
74
|
+
content_type = content.fetch('content_type')
|
75
|
+
if content_type == UbaloJSON.content_type
|
76
|
+
s = UbaloJSON.load(data).pretty_inspect.strip
|
77
|
+
if s.include?("\n")
|
78
|
+
puts "#{name}:"
|
79
|
+
puts s
|
80
|
+
else
|
81
|
+
puts "#{name}: #{s}"
|
82
|
+
end
|
83
|
+
else
|
84
|
+
puts "#{name}: (#{content_type})"
|
85
|
+
puts data.indent
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
60
89
|
def format_task task
|
61
90
|
"#{task['label']} #{"(#{task['state']})".lfit(10)} - #{task['pod_name']} (#{time_ago_in_words task['submitted_at']})"
|
62
91
|
end
|
@@ -78,13 +107,13 @@ class Ubalo
|
|
78
107
|
seconds = Time.now - Time.parse(time)
|
79
108
|
case
|
80
109
|
when seconds < 60
|
81
|
-
"#{pluralize
|
110
|
+
"#{pluralize(seconds.floor, "second")} ago"
|
82
111
|
when seconds/60 < 60
|
83
|
-
"#{pluralize
|
112
|
+
"#{pluralize((seconds/60).floor, "minute")} ago"
|
84
113
|
when seconds/60/60 < 24
|
85
|
-
"#{pluralize
|
114
|
+
"#{pluralize((seconds/60/60).floor, "hour")} ago"
|
86
115
|
else
|
87
|
-
"#{pluralize
|
116
|
+
"#{pluralize((seconds/60/60/24).floor, "day")} ago"
|
88
117
|
end
|
89
118
|
end
|
90
119
|
|
@@ -135,7 +164,7 @@ class Ubalo
|
|
135
164
|
|
136
165
|
def whoami
|
137
166
|
response = get("#{base_url}/user")
|
138
|
-
"You are
|
167
|
+
"You are logged in as #{response['username'].inspect}."
|
139
168
|
end
|
140
169
|
|
141
170
|
def tasks count
|
@@ -143,7 +172,11 @@ class Ubalo
|
|
143
172
|
end
|
144
173
|
|
145
174
|
def submit_task pod_name, arg
|
146
|
-
|
175
|
+
params = {
|
176
|
+
:arg_content_type => UbaloJSON.content_type,
|
177
|
+
:arg => UbaloJSON.dump(arg)
|
178
|
+
}
|
179
|
+
post("#{base_url}/pods/#{pod_name}/tasks", params)
|
147
180
|
end
|
148
181
|
|
149
182
|
def wait_task(label, silent=false)
|
@@ -173,38 +206,32 @@ class Ubalo
|
|
173
206
|
get("#{base_url}/pods")
|
174
207
|
end
|
175
208
|
|
176
|
-
def
|
177
|
-
|
178
|
-
|
209
|
+
def show_result(result)
|
210
|
+
puts " label: #{result['label']}"
|
211
|
+
puts " pod: #{result['pod_name']}"
|
212
|
+
if arg = result['arg']
|
213
|
+
Ubalo.print_content(' arg', arg)
|
214
|
+
end
|
179
215
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
puts " label: #{result['label']}"
|
185
|
-
puts " pod: #{result['pod_name']}"
|
186
|
-
puts " arg: #{result['arg']}"
|
187
|
-
puts " state: #{result['state']}"
|
188
|
-
case result['exit_type']
|
189
|
-
when 'exited'
|
190
|
-
puts "status: #{result['exit_result']}"
|
191
|
-
when 'terminated'
|
192
|
-
puts "terminated with signal: #{result['exit_result']}"
|
193
|
-
end
|
216
|
+
puts " state: #{result['state']}"
|
217
|
+
|
218
|
+
if container_process = result['container_process']
|
219
|
+
puts "status: #{container_process['exit_result']}"
|
194
220
|
|
195
|
-
if
|
221
|
+
if stdout = container_process['stdout'] and stdout.length > 0
|
196
222
|
puts "stdout:"
|
197
|
-
puts
|
223
|
+
puts stdout.indent
|
198
224
|
end
|
199
|
-
|
225
|
+
|
226
|
+
if stderr = container_process['stderr'] and stderr.length > 0
|
200
227
|
puts "stderr:"
|
201
|
-
puts
|
202
|
-
end
|
203
|
-
if result['outputs']
|
204
|
-
puts "output:"
|
205
|
-
puts result['outputs'].pretty_inspect.indent
|
228
|
+
puts stderr.indent
|
206
229
|
end
|
207
230
|
end
|
231
|
+
|
232
|
+
if outputs = result['outputs']
|
233
|
+
Ubalo.print_content('output', outputs)
|
234
|
+
end
|
208
235
|
end
|
209
236
|
|
210
237
|
def get_authorization login, password
|
@@ -231,10 +258,6 @@ class Ubalo
|
|
231
258
|
get("#{base_url}/tasks/#{label}")
|
232
259
|
end
|
233
260
|
|
234
|
-
def check_task_json hash
|
235
|
-
check_task(hash[:label])
|
236
|
-
end
|
237
|
-
|
238
261
|
def publish pod_name
|
239
262
|
post("#{base_url}/pods/#{pod_name}/publish")
|
240
263
|
end
|
@@ -247,39 +270,7 @@ class Ubalo
|
|
247
270
|
post("#{base_url}/pods/#{pod_name}/unpublish")
|
248
271
|
end
|
249
272
|
|
250
|
-
def s3_put filename
|
251
|
-
username = write_s3cfg_and_get_user
|
252
|
-
|
253
|
-
key = "#{username}/uploads/#{filename}"
|
254
|
-
pid = Process.spawn("s3cmd", "put", filename, "#{root_s3_path}/#{key}", {err: "/dev/null", out: "/dev/null"})
|
255
|
-
_, status = Process.wait2(pid)
|
256
|
-
|
257
|
-
unless status.success?
|
258
|
-
raise Ubalo::S3Error, "could not write file #{filename.inspect} from key #{key.inspect}"
|
259
|
-
end
|
260
|
-
key
|
261
|
-
end
|
262
|
-
|
263
273
|
private
|
264
|
-
def root_s3_path
|
265
|
-
"s3://ubalo/users"
|
266
|
-
end
|
267
|
-
|
268
|
-
def write_s3cfg_and_get_user
|
269
|
-
return @s3cfg_user if @s3cfg_user
|
270
|
-
|
271
|
-
response = put("#{base_url}/user")
|
272
|
-
conf = <<EOS
|
273
|
-
[default]
|
274
|
-
access_key = #{response['amazon_access_key_id']}
|
275
|
-
secret_key = #{response['amazon_secret_access_key']}
|
276
|
-
EOS
|
277
|
-
open(File.expand_path("~/.s3cfg"), "w") do |f|
|
278
|
-
f.write conf
|
279
|
-
end
|
280
|
-
@s3cfg_user = response['username']
|
281
|
-
end
|
282
|
-
|
283
274
|
|
284
275
|
def add_headers headers
|
285
276
|
# Add authorization headers.
|
data/lib/ubalo/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ubalo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.23
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-03-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gli
|
16
|
-
requirement: &
|
16
|
+
requirement: &70245226856660 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70245226856660
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: highline
|
27
|
-
requirement: &
|
27
|
+
requirement: &70245226856180 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70245226856180
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: json
|
38
|
-
requirement: &
|
38
|
+
requirement: &70245226855760 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70245226855760
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rest-client
|
49
|
-
requirement: &
|
49
|
+
requirement: &70245226855240 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: 1.6.3
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70245226855240
|
58
58
|
description: CLI and API client for Ubalo
|
59
59
|
email: dev@ubalo.com
|
60
60
|
executables:
|
@@ -90,4 +90,3 @@ signing_key:
|
|
90
90
|
specification_version: 3
|
91
91
|
summary: CLI and API client for Ubalo
|
92
92
|
test_files: []
|
93
|
-
has_rdoc:
|