ubalo 0.0.6 → 0.0.7

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 +106 -104
  2. data/lib/ubalo.rb +30 -25
  3. metadata +8 -8
data/bin/ubalo CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  require 'gli'
4
4
  require 'yaml'
5
+ require 'fileutils'
5
6
 
6
7
  require 'highline'
7
- require 'highline/import'
8
8
  hl = HighLine.new
9
9
 
10
10
  require 'ubalo'
@@ -44,11 +44,14 @@ def ubalo
44
44
  end
45
45
 
46
46
  program_desc 'Command-line access to ubalo.com.'
47
- version "0.0.6"
47
+ version "0.0.7"
48
48
 
49
49
  desc "Change the connect url"
50
50
  flag 'connect-url'
51
51
 
52
+ desc "Enable debug mode"
53
+ switch :debug
54
+
52
55
  desc 'Display authentication information'
53
56
  command :whoami do |c|
54
57
  c.action do |global_options,options,args|
@@ -106,120 +109,120 @@ command :tasks do |c|
106
109
  end
107
110
  end
108
111
 
109
- desc 'Add an ssh key (defaults to ~/.ssh/id_rsa.pub)'
110
- arg_name '<file containing ssh key>'
111
- command :add_key do |c|
112
- c.action do |global_options,options,args|
112
+ def process_download response, destination_path=nil
113
+ name = response.fetch('name')
114
+ fullname = response.fetch('fullname')
115
+ files = response.fetch('files')
116
+ destination_path ||= name
113
117
 
114
- public_key_file, = *args
118
+ if Dir.exist?(destination_path)
119
+ raise "directory #{destination_path.inspect} already exists"
120
+ end
115
121
 
116
- public_key_file ||= '~/.ssh/id_rsa.pub'
117
- public_key_file = File.expand_path(public_key_file)
122
+ FileUtils.mkdir(destination_path)
123
+ FileUtils.mkdir(File.join(destination_path, ".ubalo"))
118
124
 
119
- puts ubalo.upload_key(File.read(public_key_file))
125
+ File.open(File.join(destination_path, ".ubalo", "name"), "w") do |f|
126
+ f.puts name
120
127
  end
121
- end
122
128
 
123
- desc 'Clear all ssh keys'
124
- command :clear_keys do |c|
125
- c.action do |global_options,options,args|
126
- puts ubalo.clear_keys
129
+ files.each do |filename,content|
130
+ File.open(File.join(destination_path, filename), "w") do |f|
131
+ f.puts content
132
+ end
127
133
  end
134
+
135
+ [fullname, destination_path]
128
136
  end
129
137
 
130
- desc 'Modify a pod'
138
+ desc 'Download a pod to your computer'
131
139
  arg_name '<pod name>'
132
- command :edit do |c|
140
+ command :get do |c|
133
141
  c.action do |global_options,options,args|
134
142
  pod_name = args.shift
135
143
  unless pod_name
136
144
  raise "please specify a pod"
137
145
  end
146
+ destination_path = args.shift
138
147
 
139
- ubalo.ssh(pod_name)
148
+ $stderr.print "Fetching code for #{pod_name}..."
149
+ response = ubalo.download(pod_name)
150
+
151
+ fullname, destination_path = process_download(response)
152
+ $stderr.puts " done."
153
+ $stderr.puts "Retrieved #{fullname} into #{destination_path}/."
140
154
  end
141
155
  end
142
156
 
143
- desc 'Show the code in a pod'
157
+ desc 'Create a new pod'
144
158
  arg_name '<pod name>'
145
- command :cat do |c|
146
- c.action do |global_options,options,args|
147
- pod_name = args.shift
148
- unless pod_name
149
- raise "please specify a pod"
150
- end
159
+ command :create do |c|
151
160
 
152
- puts ubalo.cat_code(pod_name)
153
- end
154
- end
161
+ c.desc "Pod name"
162
+ c.flag :name
163
+ c.desc "Pod type"
164
+ c.flag :type
155
165
 
156
- desc 'Set the code in a pod'
157
- arg_name '<pod_name> <code_file>'
158
- command :code do |c|
159
166
  c.action do |global_options,options,args|
160
- pod_name = args.first
161
- unless pod_name
162
- raise "please specify a pod"
167
+ if options.name
168
+ pod_name = options.name
169
+ else
170
+ pod_name = hl.ask("New pod name: ")
171
+ if pod_name.empty?
172
+ raise "No pod name given"
173
+ end
163
174
  end
175
+ destination_path = pod_name
164
176
 
165
- file_name = args.last
166
- if file_name
167
- code = File.read(file_name)
168
- elsif $stdin.tty?
169
- raise "please give the new code as a filename or on stdin"
177
+ if Dir.exist?(pod_name)
178
+ raise "directory #{destination_path} already exists, giving up."
179
+ end
180
+
181
+ templates = ubalo.available_templates
182
+ if options.type
183
+ pod_type = options.type
184
+ unless templates.include? pod_type
185
+ raise "Invalid pod type"
186
+ end
170
187
  else
171
- code = $stdin.read
188
+ pod_type = hl.choose do |menu|
189
+ menu.prompt = "New pod type: "
190
+ menu.choices(*templates.keys)
191
+ end
172
192
  end
173
193
 
174
- puts ubalo.upload_code(pod_name, code)
194
+ $stderr.print "Creating a new #{pod_type} pod called #{pod_name}..."
195
+ response = ubalo.create_pod(pod_name, templates[pod_type])
196
+
197
+ fullname, destination_path = process_download(response)
198
+
199
+ $stderr.puts " done."
200
+ $stderr.puts "Created #{fullname} and placed in #{destination_path}/."
175
201
  end
176
202
  end
177
203
 
178
- desc 'Show the files in a pod environ'
204
+ desc 'Run a pod'
179
205
  arg_name '<pod name>'
180
- command :ls do |c|
181
- c.desc 'list in long format'
182
- c.switch :l
183
-
184
- c.desc 'list in human-readable form'
185
- c.switch :h
206
+ command :run do |c|
186
207
 
187
208
  c.action do |global_options,options,args|
188
- opts = ""
189
- opts << " -l" if options.l
190
- opts << " -h" if options.h
191
-
192
- pod_name = args.last
209
+ pod_name = args.shift
193
210
  unless pod_name
194
211
  raise "please specify a pod"
195
212
  end
196
- puts ubalo.ls(pod_name, opts)
197
- end
198
- end
199
213
 
200
- desc 'Copy files into and out of a pod environ'
201
- arg_name '<pod name>'
202
- command :cp do |c|
203
- c.desc 'copy recursively'
204
- c.switch :r
205
-
206
- c.action do |global_options,options,args|
207
- opts = ""
208
- opts << " -r" if options.r
209
-
210
- environ = nil
211
- scp_args = args.join(" ").gsub(/[\w-]+(?=:)/) do |pod_name|
212
- ssh_path, environ = ubalo.ssh_path(pod_name)
213
- "#{ssh_path}"
214
- end
214
+ $stderr.print "Running #{pod_name}..."
215
+ response = ubalo.submit_task(pod_name, args.join(" "))
216
+ task_label = response['label']
215
217
 
216
- ubalo.scp(environ, opts, scp_args)
218
+ result = ubalo.check_task(task_label, true)
219
+ ubalo.show_result(result)
217
220
  end
218
221
  end
219
222
 
220
- desc 'Snap a pod'
223
+ desc 'Submit a pod for running in the background'
221
224
  arg_name '<pod name>'
222
- command :run do |c|
225
+ command :submit do |c|
223
226
 
224
227
  c.action do |global_options,options,args|
225
228
  pod_name = args.shift
@@ -227,54 +230,49 @@ command :run do |c|
227
230
  raise "please specify a pod"
228
231
  end
229
232
 
230
- $stderr.print "Running #{pod_name}..."
231
- response = ubalo.submit_task(pod_name, args.join(" "))
232
- task_id = response['id']
233
+ $stderr.print "Submitting #{pod_name}..."
234
+ result = ubalo.submit_task(pod_name, args.join(" "))
235
+ $stderr.puts " submitted."
233
236
 
234
- result = ubalo.check_task(task_id, true)
235
237
  ubalo.show_result(result)
238
+
236
239
  end
237
240
  end
238
241
 
239
242
  desc 'Check or get the result of a task'
240
- arg_name '<task id>'
243
+ arg_name '<task label>'
241
244
  command :check do |c|
242
- c.desc 'explicitly show the complete result'
243
- c.switch [:verbose, :v]
244
-
245
- c.desc 'wait for the result if the task is pending'
246
- c.switch [:wait, :w]
247
-
248
- c.desc 'outputs as json to stdout; stdout > stderr'
249
- c.switch [:json, :j]
250
-
251
245
  c.action do |global_options,options,args|
252
- task_id = args.first
253
- unless task_id
246
+ task_label = args.first
247
+ unless task_label
254
248
  raise "please specify a task"
255
249
  end
256
250
 
257
- result = ubalo.check_task(task_id, true)
251
+ $stderr.print "Checking task #{task_label}..."
252
+
253
+ result = ubalo.check_task(task_label, true)
258
254
  ubalo.show_result(result, options.verbose, options.json)
259
255
  end
260
256
  end
261
257
 
262
- desc 'Sign into Ubalo'
263
- command :signin do |c|
258
+ desc 'Enter username and password for access'
259
+ command :login do |c|
264
260
  c.action do |global_options,options,args|
265
- puts "Please enter your Ubalo username/email and password to unlock command-line access."
261
+ puts "Please enter your Ubalo details for command-line access."
266
262
  login = hl.ask(" login: "){|q| q.echo = true}
267
263
  password = hl.ask(" password: "){|q| q.echo = false}
268
264
 
269
- ubalo.token = ubalo.get_api_token(login, password)
265
+ response = ubalo.get_api_token(login, password)
266
+ ubalo.token = response['api_token']
267
+ username = response['username']
268
+
270
269
  Ubalo.write_config("connect-url" => ubalo.base_url, ubalo.base_url => {'token' => ubalo.token})
271
- puts "Access details saved to ~/.ubalorc."
272
- puts ubalo.whoami
270
+ puts "Success! Ready to use as #{username}."
273
271
  end
274
272
  end
275
273
 
276
- desc 'Sign out of Ubalo'
277
- command :signout do |c|
274
+ desc 'Remove saved username and password'
275
+ command :logout do |c|
278
276
  c.action do |global_options,options,args|
279
277
  Ubalo.write_config(ubalo.base_url => nil)
280
278
  puts "Access details deleted."
@@ -285,23 +283,26 @@ pre do |global,command,options,args|
285
283
  config = Ubalo.config
286
284
  connect_url = global['connect-url'] || config['connect-url']
287
285
 
288
- # When signing in, don't use the token:
289
- unless command && command.name == :signin
286
+ # When logging in, don't use the token:
287
+ unless command && command.name == :login
290
288
  if host_config = config[connect_url]
291
289
  token = host_config['token']
292
290
  end
293
291
  end
294
292
 
295
- unless token or (command && command.name == :signin)
296
- raise "No credentials found. Please run 'ubalo signin'."
293
+ unless token or (command && command.name == :login)
294
+ raise "No credentials found. Please run 'ubalo login'."
297
295
  end
298
296
 
299
- @ubalo ||= Ubalo.signin(token, connect_url)
297
+ @ubalo ||= Ubalo.login(token, connect_url)
298
+
299
+ @debug = global.debug
300
300
 
301
301
  true
302
302
  end
303
303
 
304
304
  on_error do |exception|
305
+ puts
305
306
  case exception
306
307
  when RestClient::BadRequest
307
308
  $stderr.puts exception.inspect.sub('400 Bad Request', 'Error')
@@ -310,6 +311,7 @@ on_error do |exception|
310
311
  # Normal exit, preserving the correct exit code.
311
312
  exit exception.message
312
313
  else
314
+ raise if @debug
313
315
  true
314
316
  end
315
317
  end
data/lib/ubalo.rb CHANGED
@@ -47,7 +47,7 @@ end
47
47
  class Ubalo
48
48
  class << self
49
49
  def format_task task
50
- "#{task['id'].to_s[0,6]} #{task['state'].lfit(8)} #{task['pod_name'].lfit(25)} #{task['arg'].to_s.lfit(40)}"
50
+ "#{task['label']} #{task['state'].lfit(8)} #{task['pod_name'].lfit(25)} #{task['arg'].to_s.lfit(40)}"
51
51
  end
52
52
 
53
53
  def format_pod pod, with_username
@@ -63,7 +63,7 @@ class Ubalo
63
63
  attr_reader :base_url
64
64
  attr_accessor :token
65
65
 
66
- def self.signin token, base_url=nil
66
+ def self.login token, base_url=nil
67
67
  new(token, base_url)
68
68
  end
69
69
 
@@ -78,35 +78,32 @@ class Ubalo
78
78
  params.merge!({:auth_token => token})
79
79
  end
80
80
  response = RestClient.get url, :params => params
81
- response
81
+ parse(response)
82
82
  end
83
83
 
84
84
  def post(action, params={})
85
85
  url = "#{base_url}/#{action}"
86
- RestClient.post url, {:auth_token => token}.merge(params)
87
- end
88
-
89
- def username
90
- username, role = whoami
91
- username
86
+ response = RestClient.post url, {:auth_token => token}.merge(params)
87
+ parse(response)
92
88
  end
93
89
 
94
90
  def whoami
95
- get(:whoami)
91
+ response = get(:whoami)
92
+ "You are #{response['username']}, with role #{response['role']}. You have #{response['pod_count']} pods."
96
93
  end
97
94
 
98
95
  def tasks state, count
99
- parse(get(:tasks, :count => count, :state => state))
96
+ get(:tasks, :count => count, :state => state)
100
97
  end
101
98
 
102
99
  def submit_task(pod_name, arg)
103
- parse(post(:submit_task, {:pod_name => pod_name, :arg => arg}))
100
+ post(:submit_task, {:pod_name => pod_name, :arg => arg})
104
101
  end
105
102
 
106
- def check_task(id, blocking=false)
103
+ def check_task(label, blocking=false)
107
104
  if blocking
108
105
  60.times do
109
- h = check_task_once(id)
106
+ h = check_task_once(label)
110
107
  if %w{complete failed}.include?(h['state'])
111
108
  $stderr.puts " done."
112
109
  return h
@@ -118,7 +115,7 @@ class Ubalo
118
115
  $stderr.puts
119
116
  raise "timed-out waiting for task"
120
117
  else
121
- check_task_once(id)
118
+ check_task_once(label)
122
119
  end
123
120
  end
124
121
 
@@ -130,8 +127,8 @@ class Ubalo
130
127
  post(:clear_keys)
131
128
  end
132
129
 
133
- def cat_code(name)
134
- get(:cat_code, :pod_name => name)
130
+ def download(name)
131
+ get(:download, :pod_name => name)
135
132
  end
136
133
 
137
134
  def upload_code(name, code)
@@ -139,12 +136,12 @@ class Ubalo
139
136
  end
140
137
 
141
138
  def ssh_path(name)
142
- h = parse(get(:ssh_path, :pod_name => name))
139
+ h = get(:ssh_path, :pod_name => name)
143
140
  [h['ssh_path'], h['environ'], h['environ_fullname']]
144
141
  end
145
142
 
146
143
  def pods
147
- parse(get(:pods))
144
+ get(:pods)
148
145
  end
149
146
 
150
147
  def ssh(pod_name)
@@ -173,8 +170,8 @@ class Ubalo
173
170
  if json
174
171
  puts outputs
175
172
  else
176
- puts " id: #{result['id']}"
177
- puts " name: #{result['pod_name']}"
173
+ puts " label: #{result['label']}"
174
+ puts " pod: #{result['pod_name']}"
178
175
  puts " arg: #{result['arg']}"
179
176
  puts " state: #{result['state']}"
180
177
  puts "status: #{result['status']}" if result['status']
@@ -187,19 +184,27 @@ class Ubalo
187
184
  puts result['stderr'].indent
188
185
  end
189
186
  if outputs
190
- puts "outputs:"
187
+ puts "output:"
191
188
  puts outputs.indent
192
189
  end
193
190
  end
194
191
  end
195
192
 
196
193
  def get_api_token login, password
197
- parse(post(:get_api_token, :user => {:login => login, :password => password}))['api_token']
194
+ post(:get_api_token, :user => {:login => login, :password => password})
195
+ end
196
+
197
+ def available_templates
198
+ get(:available_templates)['templates']
199
+ end
200
+
201
+ def create_pod name, type
202
+ post(:create_pod, template: type, pod_name: name)
198
203
  end
199
204
 
200
205
  private
201
- def check_task_once id
202
- parse(get(:check_task, :id => id))
206
+ def check_task_once label
207
+ get(:check_task, :label => label)
203
208
  end
204
209
 
205
210
  def parse(result)
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.6
4
+ version: 0.0.7
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-01 00:00:00.000000000Z
12
+ date: 2011-12-02 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gli
16
- requirement: &2153089760 !ruby/object:Gem::Requirement
16
+ requirement: &2161042040 !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: *2153089760
24
+ version_requirements: *2161042040
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: highline
27
- requirement: &2153089320 !ruby/object:Gem::Requirement
27
+ requirement: &2161041600 !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: *2153089320
35
+ version_requirements: *2161041600
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rest-client
38
- requirement: &2153088800 !ruby/object:Gem::Requirement
38
+ requirement: &2161041080 !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: *2153088800
46
+ version_requirements: *2161041080
47
47
  description: CLI and API client for Ubalo
48
48
  email: dev@ubalo.com
49
49
  executables: