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.
- data/bin/ubalo +106 -104
- data/lib/ubalo.rb +30 -25
- 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.
|
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
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
-
|
118
|
+
if Dir.exist?(destination_path)
|
119
|
+
raise "directory #{destination_path.inspect} already exists"
|
120
|
+
end
|
115
121
|
|
116
|
-
|
117
|
-
|
122
|
+
FileUtils.mkdir(destination_path)
|
123
|
+
FileUtils.mkdir(File.join(destination_path, ".ubalo"))
|
118
124
|
|
119
|
-
|
125
|
+
File.open(File.join(destination_path, ".ubalo", "name"), "w") do |f|
|
126
|
+
f.puts name
|
120
127
|
end
|
121
|
-
end
|
122
128
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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 '
|
138
|
+
desc 'Download a pod to your computer'
|
131
139
|
arg_name '<pod name>'
|
132
|
-
command :
|
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
|
-
|
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 '
|
157
|
+
desc 'Create a new pod'
|
144
158
|
arg_name '<pod name>'
|
145
|
-
command :
|
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
|
-
|
153
|
-
|
154
|
-
|
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
|
-
|
161
|
-
|
162
|
-
|
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
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
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
|
-
|
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
|
-
|
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 '
|
204
|
+
desc 'Run a pod'
|
179
205
|
arg_name '<pod name>'
|
180
|
-
command :
|
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
|
-
|
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
|
-
|
201
|
-
|
202
|
-
|
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.
|
218
|
+
result = ubalo.check_task(task_label, true)
|
219
|
+
ubalo.show_result(result)
|
217
220
|
end
|
218
221
|
end
|
219
222
|
|
220
|
-
desc '
|
223
|
+
desc 'Submit a pod for running in the background'
|
221
224
|
arg_name '<pod name>'
|
222
|
-
command :
|
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 "
|
231
|
-
|
232
|
-
|
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
|
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
|
-
|
253
|
-
unless
|
246
|
+
task_label = args.first
|
247
|
+
unless task_label
|
254
248
|
raise "please specify a task"
|
255
249
|
end
|
256
250
|
|
257
|
-
|
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 '
|
263
|
-
command :
|
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
|
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
|
-
|
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 "
|
272
|
-
puts ubalo.whoami
|
270
|
+
puts "Success! Ready to use as #{username}."
|
273
271
|
end
|
274
272
|
end
|
275
273
|
|
276
|
-
desc '
|
277
|
-
command :
|
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
|
289
|
-
unless command && command.name == :
|
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 == :
|
296
|
-
raise "No credentials found. Please run 'ubalo
|
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.
|
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['
|
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.
|
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
|
-
|
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
|
-
|
96
|
+
get(:tasks, :count => count, :state => state)
|
100
97
|
end
|
101
98
|
|
102
99
|
def submit_task(pod_name, arg)
|
103
|
-
|
100
|
+
post(:submit_task, {:pod_name => pod_name, :arg => arg})
|
104
101
|
end
|
105
102
|
|
106
|
-
def check_task(
|
103
|
+
def check_task(label, blocking=false)
|
107
104
|
if blocking
|
108
105
|
60.times do
|
109
|
-
h = check_task_once(
|
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(
|
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
|
134
|
-
get(:
|
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 =
|
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
|
-
|
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 "
|
177
|
-
puts "
|
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 "
|
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
|
-
|
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
|
202
|
-
|
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.
|
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-
|
12
|
+
date: 2011-12-02 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: gli
|
16
|
-
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: *
|
24
|
+
version_requirements: *2161042040
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: highline
|
27
|
-
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: *
|
35
|
+
version_requirements: *2161041600
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rest-client
|
38
|
-
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: *
|
46
|
+
version_requirements: *2161041080
|
47
47
|
description: CLI and API client for Ubalo
|
48
48
|
email: dev@ubalo.com
|
49
49
|
executables:
|