ubalo 0.0.7 → 0.0.8

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 (3) hide show
  1. data/bin/ubalo +169 -19
  2. data/lib/ubalo.rb +52 -42
  3. metadata +8 -8
data/bin/ubalo CHANGED
@@ -43,6 +43,13 @@ def ubalo
43
43
  @ubalo
44
44
  end
45
45
 
46
+ def local_config
47
+ unless @local_config
48
+ raise "Please run this command from within a local pod directory"
49
+ end
50
+ @local_config
51
+ end
52
+
46
53
  program_desc 'Command-line access to ubalo.com.'
47
54
  version "0.0.7"
48
55
 
@@ -112,6 +119,7 @@ end
112
119
  def process_download response, destination_path=nil
113
120
  name = response.fetch('name')
114
121
  fullname = response.fetch('fullname')
122
+ url = response.fetch('url')
115
123
  files = response.fetch('files')
116
124
  destination_path ||= name
117
125
 
@@ -122,8 +130,8 @@ def process_download response, destination_path=nil
122
130
  FileUtils.mkdir(destination_path)
123
131
  FileUtils.mkdir(File.join(destination_path, ".ubalo"))
124
132
 
125
- File.open(File.join(destination_path, ".ubalo", "name"), "w") do |f|
126
- f.puts name
133
+ File.open(File.join(destination_path, ".ubalo", "config"), "w") do |f|
134
+ f.puts(YAML.dump("pod_url" => url, "filenames" => files.keys))
127
135
  end
128
136
 
129
137
  files.each do |filename,content|
@@ -150,7 +158,7 @@ command :get do |c|
150
158
 
151
159
  fullname, destination_path = process_download(response)
152
160
  $stderr.puts " done."
153
- $stderr.puts "Retrieved #{fullname} into #{destination_path}/."
161
+ $stderr.puts "Retrieved #{fullname} into #{destination_path}."
154
162
  end
155
163
  end
156
164
 
@@ -204,7 +212,6 @@ end
204
212
  desc 'Run a pod'
205
213
  arg_name '<pod name>'
206
214
  command :run do |c|
207
-
208
215
  c.action do |global_options,options,args|
209
216
  pod_name = args.shift
210
217
  unless pod_name
@@ -215,43 +222,182 @@ command :run do |c|
215
222
  response = ubalo.submit_task(pod_name, args.join(" "))
216
223
  task_label = response['label']
217
224
 
218
- result = ubalo.check_task(task_label, true)
225
+ result = ubalo.wait_task(task_label)
219
226
  ubalo.show_result(result)
220
227
  end
221
228
  end
222
229
 
230
+ def receive_json_from_stdin
231
+ if $stdin.tty?
232
+ raise "please pipe to stdin when using --json"
233
+ else
234
+ JSON.parse($stdin.read)
235
+ end
236
+ end
237
+
223
238
  desc 'Submit a pod for running in the background'
224
239
  arg_name '<pod name>'
225
240
  command :submit do |c|
241
+ c.desc 'Receive JSON from stdin'
242
+ c.switch :json
243
+
244
+ c.action do |global_options,options,args|
245
+ if options.json
246
+ args = receive_json_from_stdin
247
+ result = ubalo.submit_task_json(args)
248
+ else
249
+ pod_name = args.shift
250
+ unless pod_name
251
+ raise "please specify a pod"
252
+ end
253
+
254
+ $stderr.print "Submitting #{pod_name}..."
255
+ result = ubalo.submit_task(pod_name, args.join(" "))
256
+ $stderr.puts " submitted."
257
+ end
258
+ ubalo.show_result(result, options.json)
259
+ end
260
+ end
261
+
262
+ desc 'Check or get the result of a task'
263
+ arg_name '<task label>'
264
+ command :check do |c|
265
+ c.desc 'Get details and give output as JSON'
266
+ c.switch :json
267
+
268
+ c.action do |global_options,options,args|
269
+ if options.json
270
+ args = receive_json_from_stdin
271
+ result = ubalo.check_task_json(args)
272
+ else
273
+ task_label = args.first
274
+ unless task_label
275
+ raise "please specify a task"
276
+ end
277
+
278
+ $stderr.print "Checking task #{task_label}..."
279
+ result = ubalo.check_task(task_label)
280
+ end
281
+
282
+ ubalo.show_result(result, options.json)
283
+ end
284
+ end
285
+
286
+ desc 'Add an ssh key (defaults to ~/.ssh/id_rsa.pub)'
287
+ arg_name '<file containing ssh key>'
288
+ command :add_key do |c|
289
+ c.action do |global_options,options,args|
290
+ public_key_file = args.shift
291
+ public_key_file ||= File.expand_path('~/.ssh/id_rsa.pub')
292
+
293
+ puts ubalo.upload_key(File.read(public_key_file))["message"]
294
+ end
295
+ end
296
+
297
+ desc 'Clear all ssh keys'
298
+ command :clear_keys do |c|
299
+ c.action do |global_options,options,args|
300
+ puts ubalo.clear_keys.fetch('message')
301
+ end
302
+ end
226
303
 
304
+ desc 'Modify a pod'
305
+ arg_name '<pod name>'
306
+ command :edit do |c|
227
307
  c.action do |global_options,options,args|
228
308
  pod_name = args.shift
229
309
  unless pod_name
230
310
  raise "please specify a pod"
231
311
  end
232
312
 
233
- $stderr.print "Submitting #{pod_name}..."
234
- result = ubalo.submit_task(pod_name, args.join(" "))
235
- $stderr.puts " submitted."
313
+ ubalo.ssh(pod_name)
314
+ end
315
+ end
236
316
 
237
- ubalo.show_result(result)
317
+ desc 'Push code to Ubalo'
318
+ command :push do |c|
319
+ c.action do |global_options,options,args|
320
+ filenames = local_config['filenames']
321
+ contents = {}
322
+ filenames.each do |filename|
323
+ contents[filename] = File.read(filename)
324
+ end
325
+
326
+ # Don't bother formatting for multiple files just yet.
327
+ fail unless filenames.length == 1
238
328
 
329
+ print "Uploading changes to #{filenames.first}... "
330
+ result = ubalo.push(local_config['pod_url'], contents)
331
+ puts result['message']
239
332
  end
240
333
  end
241
334
 
242
- desc 'Check or get the result of a task'
243
- arg_name '<task label>'
244
- command :check do |c|
335
+ desc 'Pull code from Ubalo'
336
+ command :pull do |c|
245
337
  c.action do |global_options,options,args|
246
- task_label = args.first
247
- unless task_label
248
- raise "please specify a task"
338
+ print "Pulling changes from Ubalo..."
339
+ contents = ubalo.pull(local_config['pod_url'])
340
+ puts " received."
341
+
342
+ filenames = local_config['filenames']
343
+
344
+ filenames.each do |filename|
345
+
346
+ if File.exists?(filename)
347
+ existing_contents = File.read(filename)
348
+ else
349
+ existing_contents = nil
350
+ end
351
+
352
+ if contents[filename] == existing_contents
353
+ puts "Checking #{filename}... no changes."
354
+ else
355
+ hl.choose do |menu|
356
+ menu.prompt = "Changes made to #{filename}. Overwrite your copy? "
357
+ menu.choice :yes do
358
+ open(filename, 'w') do |f|
359
+ f.puts contents[filename]
360
+ end
361
+ puts "Changes saved to #{filename}."
362
+ end
363
+
364
+ menu.choice :no do
365
+ puts "Cancelled! No changes made to #{filename}."
366
+ end
367
+ end
368
+ end
249
369
  end
370
+ end
371
+ end
372
+
373
+ desc 'Add an ssh key (defaults to ~/.ssh/id_rsa.pub)'
374
+ arg_name '<file containing ssh key>'
375
+ command :add_key do |c|
376
+ c.action do |global_options,options,args|
377
+ public_key_file = args.shift
378
+ public_key_file ||= File.expand_path('~/.ssh/id_rsa.pub')
250
379
 
251
- $stderr.print "Checking task #{task_label}..."
380
+ puts ubalo.upload_key(File.read(public_key_file))["message"]
381
+ end
382
+ end
252
383
 
253
- result = ubalo.check_task(task_label, true)
254
- ubalo.show_result(result, options.verbose, options.json)
384
+ desc 'Clear all ssh keys'
385
+ command :clear_keys do |c|
386
+ c.action do |global_options,options,args|
387
+ puts ubalo.clear_keys.fetch('message')
388
+ end
389
+ end
390
+
391
+ desc 'Modify a pod'
392
+ arg_name '<pod name>'
393
+ command :edit do |c|
394
+ c.action do |global_options,options,args|
395
+ pod_name = args.shift
396
+ unless pod_name
397
+ raise "please specify a pod"
398
+ end
399
+
400
+ ubalo.ssh(pod_name)
255
401
  end
256
402
  end
257
403
 
@@ -294,8 +440,12 @@ pre do |global,command,options,args|
294
440
  raise "No credentials found. Please run 'ubalo login'."
295
441
  end
296
442
 
297
- @ubalo ||= Ubalo.login(token, connect_url)
443
+ local_config_filename = ".ubalo/config"
444
+ if File.exists?(local_config_filename)
445
+ @local_config = YAML.load_file(local_config_filename)
446
+ end
298
447
 
448
+ @ubalo ||= Ubalo.login(token, connect_url)
299
449
  @debug = global.debug
300
450
 
301
451
  true
data/lib/ubalo.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rest-client'
2
2
  require 'json'
3
3
  require 'open3'
4
+ require 'pp'
4
5
 
5
6
  class String
6
7
  def lfit max_length
@@ -74,6 +75,10 @@ class Ubalo
74
75
 
75
76
  def get(action, params={})
76
77
  url = "#{base_url}/#{action}"
78
+ url_get(url, params)
79
+ end
80
+
81
+ def url_get url, params={}
77
82
  if token
78
83
  params.merge!({:auth_token => token})
79
84
  end
@@ -83,6 +88,10 @@ class Ubalo
83
88
 
84
89
  def post(action, params={})
85
90
  url = "#{base_url}/#{action}"
91
+ url_post(url, params)
92
+ end
93
+
94
+ def url_post(url, params={})
86
95
  response = RestClient.post url, {:auth_token => token}.merge(params)
87
96
  parse(response)
88
97
  end
@@ -97,26 +106,26 @@ class Ubalo
97
106
  end
98
107
 
99
108
  def submit_task(pod_name, arg)
100
- post(:submit_task, {:pod_name => pod_name, :arg => arg})
101
- end
102
-
103
- def check_task(label, blocking=false)
104
- if blocking
105
- 60.times do
106
- h = check_task_once(label)
107
- if %w{complete failed}.include?(h['state'])
108
- $stderr.puts " done."
109
- return h
110
- end
111
- $stderr.print '.'
112
- $stderr.flush
113
- sleep 0.5
109
+ submit_task_json({:pod_name => pod_name, :arg => arg})
110
+ end
111
+
112
+ def submit_task_json hash
113
+ post(:submit_task, hash)
114
+ end
115
+
116
+ def wait_task(label)
117
+ 60.times do
118
+ h = check_task(label)
119
+ if %w{complete failed}.include?(h['state'])
120
+ $stderr.puts " done."
121
+ return h
114
122
  end
115
- $stderr.puts
116
- raise "timed-out waiting for task"
117
- else
118
- check_task_once(label)
123
+ $stderr.print '.'
124
+ $stderr.flush
125
+ sleep 0.5
119
126
  end
127
+ $stderr.puts
128
+ raise "timed-out waiting for task"
120
129
  end
121
130
 
122
131
  def upload_key(key)
@@ -137,7 +146,7 @@ class Ubalo
137
146
 
138
147
  def ssh_path(name)
139
148
  h = get(:ssh_path, :pod_name => name)
140
- [h['ssh_path'], h['environ'], h['environ_fullname']]
149
+ [h['ssh_path'], h['environ_fullname']]
141
150
  end
142
151
 
143
152
  def pods
@@ -148,27 +157,16 @@ class Ubalo
148
157
  ssh_path, environ = ssh_path(pod_name)
149
158
  puts "Opening an ssh connection to edit the '#{environ}' environment for the '#{pod_name}' pod."
150
159
  ssh_command = "ssh -o SendEnv='UBALO_ENVIRON TERM' -tq #{ssh_path}"
151
- Process.exec({'UBALO_ENVIRON' => environ}, ssh_command)
152
- end
153
-
154
- def scp(environ, opts, args)
155
- Process.exec({'UBALO_ENVIRON' => environ}, "scp -o SendEnv=UBALO_ENVIRON #{opts} #{args}")
156
- end
157
-
158
- def ls(pod_name, options)
159
- ssh_path, environ = ssh_path(pod_name)
160
- ssh_command = "ssh -o SendEnv=UBALO_ENVIRON -q #{ssh_path}"
161
- out_and_err, status = Open3.capture2e({'UBALO_ENVIRON' => environ}, "#{ssh_command} ls#{options}")
162
- out_and_err
163
- end
164
-
165
- def show_result(result, verbose=false, json=false)
166
- if result['outputs']
167
- outputs = JSON.dump(result['outputs'])
160
+ Process.spawn({'UBALO_ENVIRON' => environ}, ssh_command)
161
+ pid, status = Process.wait2
162
+ unless status.success?
163
+ abort "Error running ssh"
168
164
  end
165
+ end
169
166
 
167
+ def show_result(result, json=false)
170
168
  if json
171
- puts outputs
169
+ puts JSON.dump(result)
172
170
  else
173
171
  puts " label: #{result['label']}"
174
172
  puts " pod: #{result['pod_name']}"
@@ -183,9 +181,9 @@ class Ubalo
183
181
  puts "stderr:"
184
182
  puts result['stderr'].indent
185
183
  end
186
- if outputs
184
+ if result['outputs']
187
185
  puts "output:"
188
- puts outputs.indent
186
+ puts result['outputs'].pretty_inspect.indent
189
187
  end
190
188
  end
191
189
  end
@@ -202,11 +200,23 @@ class Ubalo
202
200
  post(:create_pod, template: type, pod_name: name)
203
201
  end
204
202
 
205
- private
206
- def check_task_once label
207
- get(:check_task, :label => label)
203
+ def push pod_url, contents
204
+ url_post("#{pod_url}/api/push", contents: contents)
205
+ end
206
+
207
+ def pull pod_url
208
+ url_get("#{pod_url}/api/pull")['contents']
209
+ end
210
+
211
+ def check_task label
212
+ check_task_json({label: label})
208
213
  end
209
214
 
215
+ def check_task_json hash
216
+ get(:check_task, hash)
217
+ end
218
+
219
+ private
210
220
  def parse(result)
211
221
  JSON.load(result)
212
222
  end
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.7
4
+ version: 0.0.8
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: 2011-12-02 00:00:00.000000000Z
12
+ date: 2011-12-03 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gli
16
- requirement: &2161042040 !ruby/object:Gem::Requirement
16
+ requirement: &2157148100 !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: *2161042040
24
+ version_requirements: *2157148100
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: highline
27
- requirement: &2161041600 !ruby/object:Gem::Requirement
27
+ requirement: &2157147660 !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: *2161041600
35
+ version_requirements: *2157147660
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rest-client
38
- requirement: &2161041080 !ruby/object:Gem::Requirement
38
+ requirement: &2157147160 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 1.6.3
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2161041080
46
+ version_requirements: *2157147160
47
47
  description: CLI and API client for Ubalo
48
48
  email: dev@ubalo.com
49
49
  executables: