zillabyte-cli 0.0.24 → 0.1.0
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.
- checksums.yaml +6 -14
- data/lib/#zillabyte-cli.rb# +5 -0
- data/lib/zillabyte/api/apps.rb +16 -132
- data/lib/zillabyte/api/components.rb +115 -0
- data/lib/zillabyte/api/flows.rb +121 -0
- data/lib/zillabyte/api/keys.rb +70 -0
- data/lib/zillabyte/api.rb +15 -2
- data/lib/zillabyte/auth.rb +43 -16
- data/lib/zillabyte/cli/#logs.rb# +12 -0
- data/lib/zillabyte/cli/#repl.rb# +43 -0
- data/lib/zillabyte/cli/apps.rb +52 -893
- data/lib/zillabyte/cli/auth.rb +3 -8
- data/lib/zillabyte/cli/base.rb +28 -7
- data/lib/zillabyte/cli/components.rb +245 -0
- data/lib/zillabyte/cli/flows.rb +549 -0
- data/lib/zillabyte/cli/git.rb +38 -0
- data/lib/zillabyte/cli/help.rb +11 -4
- data/lib/zillabyte/cli/keys.rb +177 -0
- data/lib/zillabyte/cli/query.rb +0 -1
- data/lib/zillabyte/cli/relations.rb +2 -1
- data/lib/zillabyte/cli/templates/{js → apps/js}/simple_function.js +0 -0
- data/lib/zillabyte/cli/templates/{js → apps/js}/zillabyte.conf.yaml +0 -0
- data/lib/zillabyte/cli/templates/apps/python/app.py +17 -0
- data/lib/zillabyte/cli/templates/{python → apps/python}/requirements.txt +0 -0
- data/lib/zillabyte/cli/templates/{python → apps/python}/zillabyte.conf.yaml +1 -1
- data/lib/zillabyte/cli/templates/{ruby → apps/ruby}/Gemfile +0 -0
- data/lib/zillabyte/cli/templates/{ruby → apps/ruby}/app.rb +1 -1
- data/lib/zillabyte/cli/templates/{ruby → apps/ruby}/zillabyte.conf.yaml +0 -0
- data/lib/zillabyte/cli/templates/python/{simple_function.py → #simple_function.py#} +3 -6
- data/lib/zillabyte/common/session.rb +3 -1
- data/lib/zillabyte/helpers.rb +64 -1
- data/lib/zillabyte/runner/app_runner.rb +226 -0
- data/lib/zillabyte/runner/component_operation.rb +529 -0
- data/lib/zillabyte/runner/component_runner.rb +244 -0
- data/lib/zillabyte/runner/multilang_operation.rb +1133 -0
- data/lib/zillabyte/runner/operation.rb +11 -0
- data/lib/zillabyte/runner.rb +6 -0
- data/lib/zillabyte-cli/version.rb +1 -1
- data/zillabyte-cli.gemspec +1 -0
- metadata +83 -52
@@ -0,0 +1,549 @@
|
|
1
|
+
require "zillabyte/cli/base"
|
2
|
+
require "zillabyte/cli/config"
|
3
|
+
require "zillabyte/common"
|
4
|
+
require "pty"
|
5
|
+
require 'indentation'
|
6
|
+
require 'open3'
|
7
|
+
require 'securerandom'
|
8
|
+
require 'colorize'
|
9
|
+
require 'time_difference'
|
10
|
+
require 'net/http'
|
11
|
+
require "zillabyte/runner/component_runner"
|
12
|
+
require "zillabyte/runner/app_runner"
|
13
|
+
|
14
|
+
|
15
|
+
# HIDDEN: superclass for components and apps
|
16
|
+
#
|
17
|
+
class Zillabyte::Command::Flows < Zillabyte::Command::Base
|
18
|
+
|
19
|
+
# flows:status [DIR]
|
20
|
+
#
|
21
|
+
# fetches detailed status of the flow
|
22
|
+
#
|
23
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
24
|
+
# --directory DIR # Directory of the flow
|
25
|
+
#
|
26
|
+
def status
|
27
|
+
|
28
|
+
id = options[:id] || shift_argument
|
29
|
+
type = options[:output_type]
|
30
|
+
|
31
|
+
if id.nil?
|
32
|
+
id = read_name_from_conf(options)
|
33
|
+
options[:is_name] = true
|
34
|
+
elsif !(id =~ /^\d*$/)
|
35
|
+
options[:is_name] = true
|
36
|
+
end
|
37
|
+
|
38
|
+
res = api.request(
|
39
|
+
:expects => 200,
|
40
|
+
:method => :get,
|
41
|
+
:path => "/flows/#{id}"
|
42
|
+
)
|
43
|
+
|
44
|
+
res.body
|
45
|
+
if type == "json"
|
46
|
+
display res.body.to_json
|
47
|
+
else
|
48
|
+
# TODO
|
49
|
+
display res.body.to_json
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
# flows:pull ID DIR
|
55
|
+
#
|
56
|
+
# pulls a flow source to a directory.
|
57
|
+
#
|
58
|
+
# --force # pulls even if the directory exists
|
59
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
60
|
+
# --directory DIR # Directory of the flow
|
61
|
+
#
|
62
|
+
# Examples:
|
63
|
+
#
|
64
|
+
# $ zillabyte flows:pull .
|
65
|
+
#
|
66
|
+
def pull
|
67
|
+
|
68
|
+
flow_id = options[:id] || shift_argument
|
69
|
+
type = options[:output_type]
|
70
|
+
|
71
|
+
if !(flow_id =~ /^\d*$/)
|
72
|
+
options[:is_name] = true
|
73
|
+
end
|
74
|
+
|
75
|
+
dir = options[:directory] || shift_argument
|
76
|
+
error("no directory given", type) if dir.nil?
|
77
|
+
dir = File.expand_path(dir)
|
78
|
+
|
79
|
+
error("no id given", type) if flow_id.nil?
|
80
|
+
|
81
|
+
# Create if not exists..
|
82
|
+
if File.exists?(dir)
|
83
|
+
if Dir.entries(dir).size != 2 and options[:force].nil?
|
84
|
+
error("target directory not empty. use --force to override", type)
|
85
|
+
end
|
86
|
+
else
|
87
|
+
FileUtils.mkdir_p(dir)
|
88
|
+
end
|
89
|
+
|
90
|
+
res = api.flows.pull_to_directory flow_id, dir, session, options
|
91
|
+
|
92
|
+
if res['error']
|
93
|
+
error("error: #{res['error_message']}", type)
|
94
|
+
else
|
95
|
+
if type == "json"
|
96
|
+
display "{}"
|
97
|
+
else
|
98
|
+
display "flow ##{res['id']} pulled to #{dir}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
alias_command "pull", "flows:pull"
|
104
|
+
|
105
|
+
# flows:prep [DIR]
|
106
|
+
#
|
107
|
+
# performs any necessary initialization for the flow
|
108
|
+
#
|
109
|
+
# --directory DIR # flow directory
|
110
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
111
|
+
#
|
112
|
+
def prep
|
113
|
+
|
114
|
+
type = options[:output_type]
|
115
|
+
dir = options[:directory] || shift_argument
|
116
|
+
if dir.nil?
|
117
|
+
dir = Dir.pwd
|
118
|
+
else
|
119
|
+
dir = File.expand_path(dir)
|
120
|
+
end
|
121
|
+
options[:directory] = dir
|
122
|
+
meta = Zillabyte::CLI::Config.get_config_info(dir)
|
123
|
+
|
124
|
+
if meta.nil?
|
125
|
+
error("The specified directory (#{dir}) does not appear to contain a valid Zillabyte configuration file.", type)
|
126
|
+
end
|
127
|
+
|
128
|
+
case meta["language"]
|
129
|
+
when "ruby"
|
130
|
+
|
131
|
+
# Execute in the bundler context
|
132
|
+
full_script = File.join(dir, meta["script"])
|
133
|
+
cmd = "cd \"#{meta['home_dir']}\"; unset BUNDLE_GEMFILE; unset RUBYOPT; bundle install"
|
134
|
+
exec(cmd)
|
135
|
+
|
136
|
+
when "python"
|
137
|
+
vDir = "#{meta['home_dir']}/vEnv"
|
138
|
+
lock_file = meta['home_dir']+"/zillabyte_thread_lock_file"
|
139
|
+
if File.exists?(lock_file)
|
140
|
+
sleep(1) while File.exists?(lock_file)
|
141
|
+
else
|
142
|
+
begin
|
143
|
+
cmd = "touch #{lock_file}; virtualenv --clear --system-site-packages #{vDir}; PYTHONPATH=~/zb1/multilang/python/Zillabyte #{vDir}/bin/pip install -r #{meta['home_dir']}/requirements.txt"
|
144
|
+
system cmd, :out => :out
|
145
|
+
ensure
|
146
|
+
File.delete(lock_file)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
when "js"
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
alias_command "prep", "flows:prep"
|
155
|
+
|
156
|
+
# flows:logs ID [OPERATION_NAME]
|
157
|
+
#
|
158
|
+
# streams logs from the distributed workers
|
159
|
+
#
|
160
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
161
|
+
# --operation OPERATION_NAME # specify the operation to show logs for
|
162
|
+
# -v, --verbose LEVEL # sets the verbosity (error, info, debug) (default: info)
|
163
|
+
#
|
164
|
+
def logs
|
165
|
+
|
166
|
+
flow_id = options[:id] || shift_argument
|
167
|
+
if flow_id.nil?
|
168
|
+
flow_id = read_name_from_conf(options)
|
169
|
+
options[:is_name] = true
|
170
|
+
elsif !(flow_id =~ /^\d*$/)
|
171
|
+
options[:is_name] = true
|
172
|
+
end
|
173
|
+
|
174
|
+
operation_id = options[:operation] || shift_argument || '_ALL_'
|
175
|
+
category = options[:verbose] || '_ALL_'
|
176
|
+
type = options[:output_type]
|
177
|
+
|
178
|
+
carry_settings = {
|
179
|
+
:category => category
|
180
|
+
}
|
181
|
+
|
182
|
+
display "Retrieving logs for flow ##{flow_id}...please wait..." if type.nil?
|
183
|
+
hash = self.api.logs.get(flow_id, operation_id, options)
|
184
|
+
|
185
|
+
fetch_logs(hash, operation_id)
|
186
|
+
|
187
|
+
end
|
188
|
+
alias_command "logs", "flows:logs"
|
189
|
+
|
190
|
+
|
191
|
+
# flows:errors ID
|
192
|
+
#
|
193
|
+
# show recent errors generated by the flow
|
194
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
195
|
+
#
|
196
|
+
def errors
|
197
|
+
|
198
|
+
# Init
|
199
|
+
flow_id = options[:id] || shift_argument
|
200
|
+
|
201
|
+
# No name?
|
202
|
+
if flow_id.nil?
|
203
|
+
flow_id = read_name_from_conf(options)
|
204
|
+
options[:is_name] = true
|
205
|
+
elsif !(flow_id =~ /^\d*$/)
|
206
|
+
options[:is_name] = true
|
207
|
+
end
|
208
|
+
|
209
|
+
type = options[:output_type]
|
210
|
+
|
211
|
+
# Make the request
|
212
|
+
res = api.request(
|
213
|
+
:expects => 200,
|
214
|
+
:method => :get,
|
215
|
+
:body => options.to_json,
|
216
|
+
:path => "/flows/#{CGI.escape(flow_id)}/errors"
|
217
|
+
)
|
218
|
+
|
219
|
+
# Render
|
220
|
+
display "Recent errors:" if type.nil?
|
221
|
+
headings = ["operation", "date", "error"]
|
222
|
+
rows = (res.body["recent_errors"] || []).map do |row|
|
223
|
+
if row['date']
|
224
|
+
d = Time.at(row['date']/1000)
|
225
|
+
else
|
226
|
+
d = nil
|
227
|
+
end
|
228
|
+
[row['name'], d, row['message']]
|
229
|
+
end
|
230
|
+
rows.sort! do |a,b|
|
231
|
+
a[1] <=> b[1]
|
232
|
+
end
|
233
|
+
color_map = {}
|
234
|
+
colors = LogFormatter::COLORS.clone
|
235
|
+
rows.each do |row|
|
236
|
+
name = row[0]
|
237
|
+
time = row[1]
|
238
|
+
message = row[2].strip
|
239
|
+
color_map[name] ||= colors.shift
|
240
|
+
if time
|
241
|
+
display "#{"* #{name} - #{time_ago_in_words(time)} ago".colorize(color_map[name])}:" if type.nil?
|
242
|
+
else
|
243
|
+
display "#{"* #{name}".colorize(color_map[name])}:" if type.nil?
|
244
|
+
end
|
245
|
+
message.split('\n').each do |sub_line|
|
246
|
+
display " #{sub_line}" if type.nil?
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
alias_command "errors", "flows:errors"
|
252
|
+
|
253
|
+
|
254
|
+
# flows:live_run [OPERATION_NAME] [PIPE_NAME] [DIR]
|
255
|
+
#
|
256
|
+
# runs a local flow with live data
|
257
|
+
#
|
258
|
+
# --config CONFIG_FILE # use the given config file
|
259
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
260
|
+
# --directory DIR # Directory of the flow
|
261
|
+
#
|
262
|
+
def live_run
|
263
|
+
|
264
|
+
name = options[:name] || shift_argument
|
265
|
+
type = options[:output_type]
|
266
|
+
|
267
|
+
thread_id = options[:thread] || shift_argument || ""
|
268
|
+
dir = options[:directory] || shift_argument
|
269
|
+
if dir.nil?
|
270
|
+
dir = Dir.pwd
|
271
|
+
else
|
272
|
+
dir = File.expand_path(dir)
|
273
|
+
end
|
274
|
+
options[:directory] = dir
|
275
|
+
|
276
|
+
meta = Zillabyte::CLI::Config.get_config_info(dir, options)
|
277
|
+
|
278
|
+
if meta.nil?
|
279
|
+
error("could not find meta information for: #{dir}", type)
|
280
|
+
end
|
281
|
+
|
282
|
+
if(thread_id == "")
|
283
|
+
exec(command("--execute_live --name #{name.to_s}",type, dir))
|
284
|
+
else
|
285
|
+
exec(command("--execute_live --name #{name.to_s} --pipe #{dir}/#{thread_id}",type, dir))
|
286
|
+
end
|
287
|
+
end
|
288
|
+
alias_command "live_run", "flows:live_run"
|
289
|
+
|
290
|
+
# flows:info [DIR]
|
291
|
+
#
|
292
|
+
# outputs the info for the flow in the dir.
|
293
|
+
#
|
294
|
+
# --pretty # Pretty prints the info output
|
295
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
296
|
+
# --directory DIR # Directory of the flow
|
297
|
+
#
|
298
|
+
def info
|
299
|
+
|
300
|
+
dir = options[:directory] || shift_argument
|
301
|
+
if dir.nil?
|
302
|
+
dir = Dir.pwd
|
303
|
+
else
|
304
|
+
dir = File.expand_path(dir)
|
305
|
+
end
|
306
|
+
options[:directory] = dir
|
307
|
+
|
308
|
+
info_file = "#{dir}/#{SecureRandom.uuid}"
|
309
|
+
type = options[:output_type]
|
310
|
+
|
311
|
+
cmd = command("--info --file #{info_file}", type, dir)
|
312
|
+
flow_info = Zillabyte::Command::Apps.get_info(cmd, info_file, dir, options)
|
313
|
+
|
314
|
+
if type == "json"
|
315
|
+
puts flow_info
|
316
|
+
else
|
317
|
+
if options[:pretty]
|
318
|
+
puts JSON.pretty_generate(JSON.parse(flow_info))
|
319
|
+
else
|
320
|
+
puts flow_info
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
exit
|
325
|
+
end
|
326
|
+
alias_command "info", "flows:info"
|
327
|
+
|
328
|
+
# flows:delete ID
|
329
|
+
#
|
330
|
+
# deletes a flow. if the flow is running, this command will kill it.
|
331
|
+
#
|
332
|
+
# -f, --force # don't ask for confirmation
|
333
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
334
|
+
#
|
335
|
+
def delete
|
336
|
+
flow_id = options[:id] || shift_argument
|
337
|
+
|
338
|
+
if flow_id.nil?
|
339
|
+
flow_id = read_name_from_conf(options)
|
340
|
+
options[:is_name] = true
|
341
|
+
elsif !(flow_id =~ /^\d*$/)
|
342
|
+
options[:is_name] = true
|
343
|
+
end
|
344
|
+
forced = options[:force]
|
345
|
+
type = options[:output_type]
|
346
|
+
|
347
|
+
if not forced
|
348
|
+
|
349
|
+
if !type.nil?
|
350
|
+
error("specify -f, --force to confirm deletion", type)
|
351
|
+
end
|
352
|
+
|
353
|
+
while true
|
354
|
+
display "This operation cannot be undone. Are you sure you want to delete this flow? (yes/no):", false
|
355
|
+
confirm = ask
|
356
|
+
break if confirm == "yes" || confirm == "no"
|
357
|
+
display "Please enter 'yes' to delete the flow or 'no' to exit"
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
confirmed = forced || confirm == "yes"
|
363
|
+
|
364
|
+
if confirmed
|
365
|
+
response = api.flows.delete(flow_id, options)
|
366
|
+
if type == "json"
|
367
|
+
display "{}"
|
368
|
+
else
|
369
|
+
display response["body"]
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
374
|
+
|
375
|
+
|
376
|
+
#
|
377
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
378
|
+
#
|
379
|
+
def self.get_info(cmd, info_file, dir, options = {})
|
380
|
+
type = options[:output_type]
|
381
|
+
|
382
|
+
response = `#{cmd}`
|
383
|
+
if($?.exitstatus == 1)
|
384
|
+
|
385
|
+
File.delete("#{info_file}") if File.exists?(info_file)
|
386
|
+
|
387
|
+
if options[:output_type].nil?
|
388
|
+
exit(1)
|
389
|
+
else
|
390
|
+
Zillabyte::Helpers.error("error: #{response}", type)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
flow_info = {}
|
395
|
+
File.open("#{info_file}", "r+").each do |line|
|
396
|
+
line = JSON.parse(line)
|
397
|
+
if(line["class"] == "node")
|
398
|
+
flow_info["nodes"] << line["info"]
|
399
|
+
elsif(line["class"] == "arc")
|
400
|
+
flow_info["arcs"] << line["info"]
|
401
|
+
else
|
402
|
+
flow_info = line
|
403
|
+
flow_info["nodes"] = []
|
404
|
+
flow_info["arcs"] = []
|
405
|
+
end
|
406
|
+
end
|
407
|
+
File.delete("#{info_file}")
|
408
|
+
|
409
|
+
flow_info = flow_info.to_json
|
410
|
+
if(File.exists?("#{dir}/info_to_java.in"))
|
411
|
+
java_pipe = open("#{dir}/info_to_java.in","w+")
|
412
|
+
java_pipe.puts(flow_info+"\n")
|
413
|
+
java_pipe.flush
|
414
|
+
java_pipe.close()
|
415
|
+
end
|
416
|
+
|
417
|
+
flow_info
|
418
|
+
end
|
419
|
+
|
420
|
+
|
421
|
+
|
422
|
+
|
423
|
+
# flows:test
|
424
|
+
#
|
425
|
+
# tests a local flow with sample data
|
426
|
+
#
|
427
|
+
# --config CONFIG_FILE # use the given config file
|
428
|
+
# --input INPUT_FILE # writes sink output to a file
|
429
|
+
# --output OUTPUT_FILE # writes sink output to a file
|
430
|
+
# --cycles CYCLES # number of cycles to emit (default 1)
|
431
|
+
# --directory DIR # app directory
|
432
|
+
# -i, --interactive # allow user to control input and read output
|
433
|
+
#
|
434
|
+
def test
|
435
|
+
dir = options[:directory]
|
436
|
+
if dir.nil?
|
437
|
+
dir = Dir.pwd
|
438
|
+
else
|
439
|
+
dir = File.expand_path(dir)
|
440
|
+
end
|
441
|
+
options[:directory] = dir
|
442
|
+
|
443
|
+
|
444
|
+
# Get the class
|
445
|
+
flow_class = read_class_from_conf(options)
|
446
|
+
|
447
|
+
case flow_class
|
448
|
+
when "component"
|
449
|
+
runner = Zillabyte::Runner::ComponentRunner.new()
|
450
|
+
when "app"
|
451
|
+
runner = Zillabyte::Runner::AppRunner.new()
|
452
|
+
else
|
453
|
+
# Default to App
|
454
|
+
runner = Zillabyte::Runner::AppRunner.new()
|
455
|
+
end
|
456
|
+
|
457
|
+
# Start Runner
|
458
|
+
runner.run(dir, self, options)
|
459
|
+
|
460
|
+
end
|
461
|
+
alias_command "test", "flows:test"
|
462
|
+
|
463
|
+
|
464
|
+
private
|
465
|
+
|
466
|
+
#
|
467
|
+
# --output_type OUTPUT_TYPE # specify an output type i.e. json
|
468
|
+
#
|
469
|
+
def command(arg="--execute_live", type = nil, dir = Dir.pwd, ignore_stderr = false)
|
470
|
+
meta = Zillabyte::CLI::Config.get_config_info(dir, self, options)
|
471
|
+
|
472
|
+
#meta = Zillabyte::API::Functions.get_rich_meta_info_from_script(dir, self)
|
473
|
+
error("could not extract meta information. missing zillabyte.conf.yml?", type) if meta.nil?
|
474
|
+
error(meta["error_message"], type) if meta['status'] == "error"
|
475
|
+
full_script = File.join(dir, meta["script"])
|
476
|
+
stderr_opt = "2> /dev/null" if ignore_stderr
|
477
|
+
|
478
|
+
case meta["language"]
|
479
|
+
when "ruby"
|
480
|
+
# Execute in the bundler context
|
481
|
+
cmd = "cd \"#{dir}\"; unset BUNDLE_GEMFILE; ZILLABYTE_HARNESS=1 bundle exec ruby \"#{full_script}\" #{arg} #{stderr_opt}"
|
482
|
+
|
483
|
+
when "python"#{
|
484
|
+
if(File.directory?("#{dir}/vEnv"))
|
485
|
+
cmd = "cd \"#{dir}\"; PYTHONPATH=~/zb1/multilang/python/Zillabyte #{dir}/vEnv/bin/python \"#{full_script}\" #{arg} #{stderr_opt}"
|
486
|
+
else
|
487
|
+
cmd = "cd \"#{dir}\"; PYTHONPATH=~/zb1/multilang/python/Zillabyte python \"#{full_script}\" #{arg} #{stderr_opt}"
|
488
|
+
end
|
489
|
+
|
490
|
+
when "js"
|
491
|
+
# cmd = "#{Zillabyte::API::CASPERJS_BIN} #{Zillabyte::API::API_CLIENT_JS} \"#{full_script}\" #{arg}"
|
492
|
+
cmd = "cd \"#{dir}\"; NODE_PATH=~/zb1/multilang/js/src/lib #{Zillabyte::API::NODEJS_BIN} \"#{full_script}\" #{arg} #{stderr_opt}"
|
493
|
+
|
494
|
+
else
|
495
|
+
error("no language specified", type)
|
496
|
+
end
|
497
|
+
|
498
|
+
return cmd
|
499
|
+
|
500
|
+
end
|
501
|
+
|
502
|
+
def read_name_from_conf(options = {})
|
503
|
+
type = options[:output_type]
|
504
|
+
hash = Zillabyte::API::Apps.get_rich_meta_info_from_script Dir.pwd, options
|
505
|
+
error("No id given and current directory does not contain a valid Zillabyte configuration file. Please specify a flow id or run command from the directory containing the flow.",type) if hash["error"]
|
506
|
+
hash["name"]
|
507
|
+
end
|
508
|
+
|
509
|
+
def read_class_from_conf(options = {})
|
510
|
+
type = options[:output_type]
|
511
|
+
hash = Zillabyte::API::Apps.get_rich_meta_info_from_script Dir.pwd, options
|
512
|
+
error("No id given and current directory does not contain a valid Zillabyte configuration file. Please specify a flow id or run command from the directory containing the flow.",type) if hash["error"]
|
513
|
+
hash["class"]
|
514
|
+
end
|
515
|
+
|
516
|
+
def fetch_logs(hash, operation=nil, exit_on=nil)
|
517
|
+
def color_for(operation_name)
|
518
|
+
@color_map[operation_name] ||= @all_colors[ @color_map.size % @all_colors.size ]
|
519
|
+
@color_map[operation_name]
|
520
|
+
end
|
521
|
+
|
522
|
+
@color_map = {}
|
523
|
+
@all_colors = [:green, :yellow, :magenta, :cyan, :light_black, :light_green, :light_yellow, :light_blue, :light_magenta, :light_cyan]
|
524
|
+
if(hash["server"] == "localhost")
|
525
|
+
cmd = "tail -n 500 -f /tmp/flows/f#{hash["flow"]}/flow_logs/flow_#{hash["flow"]}.log"
|
526
|
+
else
|
527
|
+
cmd = "curl -G http://#{hash["flow"]}:#{hash["token"]}@#{hash["server"]}:#{hash["port"]}/getLogs?flow=#{hash["flow"]}"
|
528
|
+
end
|
529
|
+
|
530
|
+
begin
|
531
|
+
PTY.spawn( cmd ) do |r, w, pid|
|
532
|
+
r.each do |line|
|
533
|
+
begin
|
534
|
+
op = line.match(/\[(.*?)\]/)[0].to_s[1...-1]
|
535
|
+
op_name = op.split(".")[0]
|
536
|
+
next if op_name != operation and operation != "_ALL_"
|
537
|
+
line_split = line.split("[")
|
538
|
+
print line_split[0] + "[" + op.colorize(color_for(op)) + line_split[1..-1].join("[")[op.length..-1]
|
539
|
+
break if exit_on and line.include? exit_on
|
540
|
+
rescue Exception => e
|
541
|
+
next
|
542
|
+
end
|
543
|
+
end
|
544
|
+
end
|
545
|
+
rescue PTY::ChildExited => e
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "zillabyte/cli/base"
|
2
|
+
|
3
|
+
# manage git for apps
|
4
|
+
#
|
5
|
+
class Zillabyte::Command::Git < Zillabyte::Command::Base
|
6
|
+
|
7
|
+
# git:remote [OPTIONS]
|
8
|
+
#
|
9
|
+
# adds a git remote to an app repo
|
10
|
+
#
|
11
|
+
# if OPTIONS are specified they will be passed to git remote add
|
12
|
+
#
|
13
|
+
# -r, --remote REMOTE # the git remote to create, default "Zillabyte"
|
14
|
+
# -n, --name NAME # the name of the app, default current directory's name
|
15
|
+
#
|
16
|
+
#Examples:
|
17
|
+
#
|
18
|
+
# $ zillabyte git:remote -a example
|
19
|
+
# Git remote zillabyte added
|
20
|
+
#
|
21
|
+
# $ zillabyte git:remote -a example
|
22
|
+
# ! Git remote zillabyte already exists
|
23
|
+
#
|
24
|
+
def remote
|
25
|
+
git_options = args.join(" ")
|
26
|
+
remote = options[:remote] || 'zillabyte'
|
27
|
+
app_name = options[:name] || File.basename(Dir.pwd)
|
28
|
+
|
29
|
+
if git('remote').split("\n").include?(remote)
|
30
|
+
# already exists.. remove it.
|
31
|
+
git("remote remove #{remote}")
|
32
|
+
end
|
33
|
+
|
34
|
+
git_url = "git@#{Zillabyte::Auth.git_host}:#{Zillabyte::Auth.user}/#{app_name}"
|
35
|
+
create_git_remote(remote, git_url)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/zillabyte/cli/help.rb
CHANGED
@@ -4,7 +4,7 @@ require "zillabyte/cli/base"
|
|
4
4
|
#
|
5
5
|
class Zillabyte::Command::Help < Zillabyte::Command::Base
|
6
6
|
|
7
|
-
PRIMARY_NAMESPACES = %w( relations query apps logs )
|
7
|
+
PRIMARY_NAMESPACES = %w( relations query apps components logs )
|
8
8
|
|
9
9
|
# help
|
10
10
|
def index(*direct_args)
|
@@ -85,13 +85,20 @@ private
|
|
85
85
|
|
86
86
|
def summary_for_aliases(command_aliases)
|
87
87
|
used_aliases = command_aliases.select{|c,a| !c.include?("-") and !c.include?(":") and !skip_command?(commands[a])}
|
88
|
-
a_size = longest(used_aliases.map { |al,al_to| al }) +
|
89
|
-
a_to_size = longest(used_aliases.map { |al,al_to| al_to }) +
|
88
|
+
a_size = longest(used_aliases.map { |al,al_to| al }) + 4
|
89
|
+
a_to_size = longest(used_aliases.map { |al,al_to| al_to }) + 4
|
90
90
|
used_aliases.sort_by{|k,v| v}.each do |command_alias, alias_to|
|
91
|
+
|
91
92
|
if command_alias.include?("-") or command_alias.include?(":")
|
92
93
|
next #skip -h, -help and live-run etc.
|
93
94
|
end
|
94
|
-
|
95
|
+
|
96
|
+
if alias_to.include?("flows")
|
97
|
+
puts "#{command_alias.ljust(a_size)} --> #{alias_to.gsub("flows", "apps").ljust(a_to_size)} # #{commands[alias_to][:summary].gsub("flow", "app")}"
|
98
|
+
puts "#{" ".ljust(a_size)} --> #{alias_to.gsub("flows", "components").ljust(a_to_size)} # #{commands[alias_to][:summary].gsub("flow", "component")}"
|
99
|
+
else
|
100
|
+
puts "#{command_alias.ljust(a_size)} --> #{alias_to.ljust(a_to_size)} # #{commands[alias_to][:summary]}"
|
101
|
+
end
|
95
102
|
end
|
96
103
|
end
|
97
104
|
|