zillabyte-cli 0.0.16 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +9 -9
  2. data/lib/#zillabyte-cli.rb# +5 -0
  3. data/lib/zillabyte/api/{flows.rb → apps.rb} +35 -23
  4. data/lib/zillabyte/api/data.rb +12 -1
  5. data/lib/zillabyte/api/logs.rb +4 -4
  6. data/lib/zillabyte/api/queries.rb +15 -6
  7. data/lib/zillabyte/api/zillalogs.rb +1 -1
  8. data/lib/zillabyte/api.rb +40 -38
  9. data/lib/zillabyte/auth.rb +19 -11
  10. data/lib/zillabyte/cli/#logs.rb# +12 -0
  11. data/lib/zillabyte/cli/{flows.rb → apps.rb} +407 -177
  12. data/lib/zillabyte/cli/auth.rb +1 -1
  13. data/lib/zillabyte/cli/base.rb +5 -4
  14. data/lib/zillabyte/cli/config.rb +3 -2
  15. data/lib/zillabyte/cli/counters.rb +1 -1
  16. data/lib/zillabyte/cli/help.rb +1 -1
  17. data/lib/zillabyte/cli/helpers/data_schema_builder.rb +1 -1
  18. data/lib/zillabyte/cli/helpers/table_output_builder.rb +25 -0
  19. data/lib/zillabyte/cli/log_formatter.rb +4 -3
  20. data/lib/zillabyte/cli/query.rb +107 -26
  21. data/lib/zillabyte/cli/relations.rb +226 -78
  22. data/lib/zillabyte/cli/sources.rb +1 -1
  23. data/lib/zillabyte/cli/templates/js/simple_function.js +5 -0
  24. data/lib/zillabyte/cli/templates/python/#simple_function.py# +27 -0
  25. data/lib/zillabyte/cli/templates/python/simple_function.py +3 -0
  26. data/lib/zillabyte/cli/templates/ruby/{simple_function.rb → simple_app.rb} +6 -6
  27. data/lib/zillabyte/cli/templates/ruby/zillabyte.conf.yaml +1 -1
  28. data/lib/zillabyte/cli/version.rb +1 -1
  29. data/lib/zillabyte/cli/zillalogs.rb +1 -1
  30. data/lib/zillabyte/command.rb +10 -2
  31. data/lib/zillabyte/common/{progress.rb → session.rb} +1 -1
  32. data/lib/zillabyte/helpers.rb +9 -4
  33. data/lib/zillabyte-cli/version.rb +1 -1
  34. data/zillabyte-cli.gemspec +2 -0
  35. metadata +25 -7
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MDRiNDYwNjlhZDQwYjc4NGNiNDZlNDkzYjE2NGNjZDhjYzMyNTdlMA==
4
+ ODVkNDFiMGFlMjc2OWM5MzU2NmY3MzdjZWJiYzIwY2RkNWU2MTdlYQ==
5
5
  data.tar.gz: !binary |-
6
- YTUzMjI0MGQxYTkyZjE4ODQ0MDU4ODg3MTBkNWM0ZDliNGEwNWQ2NA==
7
- !binary "U0hBNTEy":
6
+ ZGI4OTFhZTY3N2E2NDhhZDNmNjBhNTFhNTExZTg4ODgzMTcwYjk3Zg==
7
+ SHA512:
8
8
  metadata.gz: !binary |-
9
- MmE4Y2RhZWY0ODE2ZTQ2MWIzMTgxMjk1Yzg4NzU0NzhhZWE2YzE2MWJhYzU5
10
- ZTJmZjE0NGJmNTBlMjBhOTQ2YTVjNTZlNGQ1ODMzOGMwYTU4N2M4MjhiZTIy
11
- MzlkYjc2ZmU2OTM2MjJlMTU1NTQxMDRiMzRmMTYwYTY2YTVhY2U=
9
+ YWJkZDg3ZGQ2N2E4N2UxNDY4MTRmMDUwNjZhMWY2NjEyNzE1NDE5YWFjNzY0
10
+ MTRkZTQwZjU1NDUxMmVkMTM2ODE5YWMwNzQ4MzU1ZDE3MWE5ZjQ2MTNjZGY0
11
+ YmFlOTc5YmJjNzg3OTY4NGVjNGM0YTc3YjU4NTE4YmI1YjIyMmM=
12
12
  data.tar.gz: !binary |-
13
- ZjAxMzlmOTEyYjI4ZTk2MmU2MWE1NThjMTQ5ODg4MmUxMjc1NDMzMmYxMjYz
14
- ZmFlYWEyZjFlNTFmOGIwYTBhZDVkZWI5ZjZkNjI5NDBiMWExOGIzNDY3MTk0
15
- ZGY5Yzc4Y2FjMTZhNDY0NTg2M2Q3ZTIwZjg1ZjA3MzA3Y2Y1YmQ=
13
+ ZmMyZDU5Yzg5NjNlOWQyM2UyZTBlMjA3MThhN2M2M2VkMWI3YzYyOGRhMGQz
14
+ ZmI5OWM4NDNlNGYyOWFjMDdkNjRlYzM5NTA5MjFjNzlkZGI5MDdlODk1NTA3
15
+ MzI0N2RjMjQzMWZmNzJkMjA1MTUzYzlhODgwMGE5OWY4ZGMxZWQ=
@@ -0,0 +1,5 @@
1
+ require "zillabyte-cli/version"
2
+ require "zillabyte/api"
3
+ require "zillabyte/cli"
4
+ require "zillabyte/common"
5
+ require "zillabyte/queries"
@@ -1,10 +1,10 @@
1
1
  require 'net/http'
2
2
  require 'zillabyte/cli/config'
3
3
 
4
- class Zillabyte::API::Flows < Zillabyte::API::Base
4
+ class Zillabyte::API::Apps < Zillabyte::API::Base
5
5
 
6
6
 
7
- # GET /flows
7
+ # GET /apps
8
8
  def list(options = {})
9
9
 
10
10
  options = {
@@ -93,7 +93,7 @@ class Zillabyte::API::Flows < Zillabyte::API::Base
93
93
  )
94
94
  res.body
95
95
  end
96
-
96
+
97
97
  def run_forever(id, options ={})
98
98
  res = @api.request(
99
99
  :expects => 200,
@@ -104,14 +104,22 @@ class Zillabyte::API::Flows < Zillabyte::API::Base
104
104
  res.body
105
105
  end
106
106
 
107
-
107
+ def cycles_poll(id, options={})
108
+ res = @api.request(
109
+ :expects => 200,
110
+ :method => :get,
111
+ :path => "/flows/#{id}/cycles/cycles_poll",
112
+ :body => options.to_json
113
+ )
114
+ res.body
115
+ end
108
116
 
109
117
 
110
118
  # GET /flows/id
111
- def pull_to_directory(id, dir, progress = nil, options = {})
119
+ def pull_to_directory(id, dir, session = nil, options = {})
112
120
 
113
121
  # Get the resource. note query params
114
- progress.display "downloading ##{id}" if progress
122
+ session.display "downloading ##{id}" if session
115
123
  res = @api.request(
116
124
  :expects => 200,
117
125
  :method => :get,
@@ -123,13 +131,13 @@ class Zillabyte::API::Flows < Zillabyte::API::Base
123
131
  hash = res.body
124
132
  unless hash['status'] == 'error'
125
133
  if(hash['tar'])
126
- progress.display "unpacking to #{dir}" if progress
134
+ session.display "unpacking to #{dir}" if session
127
135
  tar = StringIO.new(Base64.decode64(hash['tar']))
128
136
  hash.delete('tar')
129
137
  Zillabyte::Common::Tar.untar(tar, dir)
130
138
  #If you get an uri instead of the tar, then download the file directly from s3
131
139
  elsif(hash['uri'])
132
- progress.display "downloading ##{id} to #{dir}" if progress
140
+ session.display "downloading ##{id} to #{dir}" if session
133
141
  uri = URI(hash['uri'])
134
142
  try_again = 1
135
143
  while(try_again)
@@ -155,16 +163,18 @@ class Zillabyte::API::Flows < Zillabyte::API::Base
155
163
 
156
164
 
157
165
 
158
- # POST /flows
159
- def push_directory(dir, progress = nil, options = {})
166
+ # POST /apps
167
+ #
168
+ def push_directory(dir, session = nil, options = {})
160
169
 
170
+ type = options[:type]
161
171
  # Get the meta info
162
172
  options[:local_flag] = 1
163
- hash = Zillabyte::API::Flows.get_rich_meta_info_from_script(dir, progress, options)
173
+ hash = Zillabyte::API::Apps.get_rich_meta_info_from_script(dir, session, options)
164
174
  if hash.nil?
165
- error "unable to extract flow meta information"
175
+ error("unable to extract app meta information", type)
166
176
  end
167
-
177
+
168
178
  # Tar up everything...
169
179
  hash['ignore_files'] ||= []
170
180
  hash['ignore_files'] << "info_to_ruby.in"
@@ -172,9 +182,9 @@ class Zillabyte::API::Flows < Zillabyte::API::Base
172
182
 
173
183
  top_dir = hash['top_dir'] || "."
174
184
  ignore_files = hash['ignore_files'] || []
175
- progress.display("packaging directory... ", false) if progress
185
+ session.display("packaging directory... ", false) if session && type.nil?
176
186
  tar = Zillabyte::Common::Tar.tar(top_dir, ignore_files)
177
- progress.display("done") if progress
187
+ session.display("done") if session && type.nil?
178
188
 
179
189
  hash.delete('pwd')
180
190
 
@@ -184,7 +194,7 @@ class Zillabyte::API::Flows < Zillabyte::API::Base
184
194
  # :tar => Base64.encode64(tar.read)
185
195
  }.merge(options)
186
196
 
187
- progress.display("uploading #{tar.size} bytes... ", false) if progress
197
+ session.display("uploading #{tar.size} bytes... ", false) if session && type.nil?
188
198
  res = @api.request(
189
199
  :expects => 200,
190
200
  :method => :post,
@@ -211,24 +221,26 @@ class Zillabyte::API::Flows < Zillabyte::API::Base
211
221
  end
212
222
  res.body.delete('uri')
213
223
  end
214
- progress.display("done")
224
+ session.display("done")if session && type.nil?
215
225
  res.body
216
226
 
217
227
  end
218
228
 
219
229
  ####################################################IMPORTANT####################################################
220
230
  # #
221
- # get_rich_meta_info_from_script only works with zillabyte flows:push now! The pipe "info_to_ruby.in" is #
231
+ # get_rich_meta_info_from_script only works with zillabyte apps:push now! The pipe "info_to_ruby.in" is #
222
232
  # hardcoded as the meta info passing pipe, so if 2 processes are trying to access it simultaneously there might #
223
233
  # be problems since it gets created/destroyed within this script (attempting to create a fifo that already #
224
234
  # exists or deleting a fifo that still has information in it may occur). #
225
235
  # #
226
236
  ####################################################IMPORTANT####################################################
227
- def self.get_rich_meta_info_from_script(dir, progress = nil, options = {})
228
- hash = Zillabyte::CLI::Config.get_config_info(dir, progress, options)
237
+ def self.get_rich_meta_info_from_script(dir, session = nil, options = {})
238
+ hash = Zillabyte::CLI::Config.get_config_info(dir, session, options)
229
239
  if hash.nil?
230
240
  return {"status" => "error", "error" => "invalid_directory", "error_message" => "The specified directory (#{dir}) does not appear to contain a valid Zillabyte configuration file."}
231
241
  end
242
+
243
+ type = options[:type]
232
244
 
233
245
  full_script = File.join(dir, hash['script'])
234
246
  command = nil
@@ -250,16 +262,16 @@ class Zillabyte::API::Flows < Zillabyte::API::Base
250
262
  # command = "#{Zillabyte::API::CASPERJS_BIN} #{Zillabyte::API::API_CLIENT_JS} \"#{full_script}\" --info"
251
263
  command = "cd \"#{dir}\"; NODE_PATH=~/zb1/multilang/js/src/lib #{Zillabyte::API::NODEJS_BIN} \"#{full_script}\" #{arg}"
252
264
  else
253
- progress.error "unsupported language: #{hash["language"]}" if progress
265
+ session.error "unsupported language: #{hash["language"]}" if session
254
266
  return nil
255
267
  end
256
268
 
257
- results = Zillabyte::Command::Flows.get_info(command, info_file, options)
269
+ results = Zillabyte::Command::Apps.get_info(command, info_file, options)
258
270
 
259
271
  begin
260
272
  meta = JSON.parse(results.split("\n").first.strip) # Throws error if invalid json
261
273
  rescue Exception => e
262
- progress.error "the underlying flow did not return a valid result. command: #{command} error: #{e.message}" if progress
274
+ session.error("the underlying app did not return a valid result. command: #{command} error: #{e.message}", type) if session
263
275
  exit
264
276
  end
265
277
 
@@ -12,7 +12,18 @@ class Zillabyte::API::Data < Zillabyte::API::Base
12
12
  )
13
13
  res.body
14
14
  end
15
-
15
+
16
+ def show(id, method, options = {})
17
+ res = @api.request(
18
+ :expects => 200,
19
+ :method => method,
20
+ :path => "/relations/#{CGI.escape(id)}/samples",
21
+ :body => options.to_json
22
+ )
23
+
24
+ res.body
25
+ end
26
+
16
27
  def pull(id, options = {})
17
28
  res = @api.request(
18
29
  :expects => 200,
@@ -5,7 +5,7 @@ class Zillabyte::API::Logs < Zillabyte::API::Base
5
5
 
6
6
 
7
7
  # GET /flows/ID/logs
8
- def get(flow_id, operation_id, options = {}, &block)
8
+ def get(app_id, operation_id, options = {}, &block)
9
9
 
10
10
  options = {
11
11
  }.merge(options)
@@ -13,7 +13,7 @@ class Zillabyte::API::Logs < Zillabyte::API::Base
13
13
  res = @api.request({
14
14
  :expects => 200,
15
15
  :method => :get,
16
- :path => "/flows/#{flow_id}/logs/#{operation_id}/stream",
16
+ :path => "/flows/#{app_id}/logs/#{operation_id}/stream",
17
17
  :body => options.to_json
18
18
  }, &block)
19
19
 
@@ -23,7 +23,7 @@ class Zillabyte::API::Logs < Zillabyte::API::Base
23
23
 
24
24
 
25
25
 
26
- def get_startup(flow_id, operation_id, options = {}, &block)
26
+ def get_startup(app_id, operation_id, options = {}, &block)
27
27
 
28
28
  options = {
29
29
  }.merge(options)
@@ -31,7 +31,7 @@ class Zillabyte::API::Logs < Zillabyte::API::Base
31
31
  res = @api.request({
32
32
  :expects => 200,
33
33
  :method => :get,
34
- :path => "/flows/#{flow_id}/logs/#{operation_id}/startup",
34
+ :path => "/flows/#{app_id}/logs/#{operation_id}/startup",
35
35
  :body => options.to_json
36
36
  }, &block)
37
37
 
@@ -2,7 +2,7 @@ class Zillabyte::API::Queries < Zillabyte::API::Base
2
2
 
3
3
 
4
4
  # GET /sxp
5
- def sxp(expression, options = {})
5
+ def sxp(expression, method, options = {})
6
6
 
7
7
  options = {
8
8
  'sxp' => expression
@@ -10,7 +10,7 @@ class Zillabyte::API::Queries < Zillabyte::API::Base
10
10
 
11
11
  res = request(
12
12
  :expects => 200,
13
- :method => :post,
13
+ :method => method,
14
14
  :path => "/query_sxp",
15
15
  :body => options.to_json
16
16
  )
@@ -35,7 +35,7 @@ class Zillabyte::API::Queries < Zillabyte::API::Base
35
35
 
36
36
 
37
37
  # GET /sql
38
- def sql(expression, options = {})
38
+ def sql(expression, method, options = {})
39
39
 
40
40
  options = {
41
41
  'sql' => expression
@@ -43,7 +43,7 @@ class Zillabyte::API::Queries < Zillabyte::API::Base
43
43
 
44
44
  res = request(
45
45
  :expects => 200,
46
- :method => :post,
46
+ :method => method,
47
47
  :path => "/query_sql",
48
48
  :body => options.to_json
49
49
  )
@@ -57,12 +57,21 @@ class Zillabyte::API::Queries < Zillabyte::API::Base
57
57
  def agnostic(expression, options = {})
58
58
  case expression
59
59
  when Array
60
- return sxp(expression, options)
60
+ res = sxp(expression, :post, options)
61
61
  when String
62
- return sql(expression, options)
62
+ res = sql(expression, :post, options)
63
+ col_aliases = res["column_aliases"] #save the column aliases
63
64
  else
64
65
  throw "unknown expression type: #{expression}"
65
66
  end
67
+
68
+ options[:job_id] = res["job_id"]
69
+ res = {'status' => nil}
70
+ while(res['status'] != 'completed')
71
+ res = sql(expression, :get, options)
72
+ end
73
+ res["return"]["column_aliases"] = col_aliases if col_aliases #send the column aliases back too
74
+ res["return"]
66
75
  end
67
76
 
68
77
 
@@ -21,7 +21,7 @@ class Zillabyte::API::Zillalogs < Zillabyte::API::Base
21
21
 
22
22
 
23
23
  # GET /zillalogs/id
24
- def find(id, progress = nil, options = {})
24
+ def find(id, session = nil, options = {})
25
25
 
26
26
  # Get the resource
27
27
  res = @api.request(
data/lib/zillabyte/api.rb CHANGED
@@ -39,8 +39,7 @@ class Zillabyte::API
39
39
 
40
40
  def initialize(options={})
41
41
  options = OPTIONS.merge(options)
42
-
43
- @progress = options.delete(:progress)
42
+ @session = options.delete(:session)
44
43
  @api_key = options.delete(:api_key) || ENV['ZILLABYTE_API_KEY']
45
44
 
46
45
  options[:headers] = HEADERS.merge({
@@ -49,7 +48,6 @@ class Zillabyte::API
49
48
 
50
49
  @options = options.clone
51
50
  @options[:bubble_exceptions] = ENV['BUBBLE_EXCEPTIONS'] || false
52
-
53
51
  @connection = Excon.new("#{options[:scheme]}://#{options[:host]}", options)
54
52
 
55
53
  end
@@ -61,6 +59,17 @@ class Zillabyte::API
61
59
 
62
60
 
63
61
  def request(params, &block)
62
+
63
+ if @session.nil?
64
+ error "no session associated with request"
65
+ end
66
+
67
+ type = nil
68
+ if @options
69
+ type = @options[:type]
70
+ end
71
+
72
+
64
73
  begin
65
74
 
66
75
  # If a block is given, then we assume we're streaming (i.e. for logs)
@@ -88,16 +97,14 @@ class Zillabyte::API
88
97
  next if json_record.strip == ""
89
98
 
90
99
  if json_record.start_with?("HTTP/1.1 50")
91
- puts "internal server error (code 500)"
92
- exit(1)
100
+ @session.error("internal server error (code 500)", type)
93
101
  end
94
102
 
95
103
  # Offer all the json records to the listening block
96
104
  begin
97
105
  block.call(JSON.parse(json_record))
98
106
  rescue JSON::ParserError => e
99
- error "unable to parse logs"
100
- exit(1)
107
+ @session.error("unable to parse logs", type)
101
108
  end
102
109
 
103
110
  end
@@ -107,47 +114,46 @@ class Zillabyte::API
107
114
 
108
115
  # Execute the request
109
116
  response = @connection.request(params)
110
-
117
+
118
+
111
119
  rescue Excon::Errors::HTTPStatusError => error
112
- if @progress
120
+
113
121
 
114
- # Show helpful error message
115
- if error.response.body
116
- begin
117
- hash = JSON.parse(error.response.body)
118
- if hash['error_message']
119
- @progress.error hash['error_message']
120
- end
121
- rescue JSON::ParserError => e
122
- # Trickle to generic message below
122
+ # Show helpful error message
123
+ if error.response.body
124
+ begin
125
+ hash = JSON.parse(error.response.body)
126
+ if hash['error_message']
127
+ @session.error(hash['error_message'], type)
123
128
  end
129
+ rescue JSON::ParserError => e
130
+ # Trickle to generic message below
124
131
  end
125
-
126
- @progress.error "internal server error"
127
-
128
132
  end
133
+
134
+
135
+ @session.error("internal server error:: #{error}", type)
136
+
129
137
  raise error
130
138
  end
131
-
139
+
132
140
  if response.body && !response.body.empty?
133
141
  # decompress_response!(response)
134
142
  begin
135
143
  response.body = JSON.parse(response.body)
136
144
  rescue Exception => e
137
145
  raise e if @options[:bubble_exceptions]
138
- @progress.error "unknown server response: \n #{response.body}" if @progress
146
+ @session.error("unknown server response: \n #{response.body}", type)
139
147
  end
140
148
  end
141
149
 
142
150
  # Errors?
143
151
  if response.body.is_a?(Hash)
144
152
  if response.body["status"] == "error"
145
- if @progress
146
- if response.body["error"] == "authentication_error"
147
- @progress.error "authentication error. run 'zillabyte login'"
148
- else
149
- @progress.error response.body["error_message"]
150
- end
153
+ if response.body["error"] == "authentication_error"
154
+ @session.error("authentication error. run 'zillabyte login'", type)
155
+ else
156
+ @session.error(response.body["error_message"],type)
151
157
  end
152
158
  end
153
159
  end
@@ -174,10 +180,10 @@ class Zillabyte::API
174
180
  end
175
181
  alias_method :query, :queries
176
182
 
177
- def flows
178
- @_flows ||= ::Zillabyte::API::Flows.new(self)
183
+ def apps
184
+ @_apps ||= ::Zillabyte::API::Apps.new(self)
179
185
  end
180
- alias_method :flow, :flows
186
+ alias_method :app, :apps
181
187
 
182
188
  def metrics
183
189
  @_metrics ||= ::Zillabyte::API::Metrics.new(self)
@@ -194,7 +200,6 @@ class Zillabyte::API
194
200
  end
195
201
  alias_method :source, :sources
196
202
 
197
-
198
203
  def collectors
199
204
  @_collectors ||= ::Zillabyte::API::Collectors.new(self)
200
205
  end
@@ -204,12 +209,9 @@ class Zillabyte::API
204
209
  @_rules ||= ::Zillabyte::API::SemanticTags.new(self)
205
210
  end
206
211
  alias_method :zillalog, :zillalogs
207
-
208
-
209
-
210
-
211
-
212
+
212
213
  def self.load
214
+ require File.join(File.dirname(__FILE__), "api", "base.rb")
213
215
  Dir[File.join(File.dirname(__FILE__), "api", "*.rb")].sort.each do |file|
214
216
  require file
215
217
  end
@@ -136,7 +136,7 @@ class Zillabyte::Auth
136
136
  end
137
137
 
138
138
  def valid_credentials?(auth_token)
139
- api = Zillabyte::API.new(:api_key => auth_token, :progress => self)
139
+ api = Zillabyte::API.new(:api_key => auth_token, :session => self)
140
140
  response = api.request(
141
141
  :expects => 200,
142
142
  :method => :get,
@@ -148,24 +148,32 @@ class Zillabyte::Auth
148
148
 
149
149
  def ask_for_and_save_credentials
150
150
  if not read_credentials.nil?
151
- display "Your credentials already exist. Re-enter them? [Y/n]"
152
- $stdout.flush()
153
- if ask == 'Y'
154
-
155
- else
151
+ display "Your credentials already exist. Re-enter them? [y/N] ", false
152
+
153
+ input = ask
154
+
155
+ if !(input.downcase == "y" || input.downcase == "yes")
156
156
  exit 1
157
157
  end
158
158
  end
159
- begin
160
- puts "Enter your Zillabyte credentials."
159
+
160
+ begin
161
+ current_command = Zillabyte::Command.current_command
162
+ msg = "Enter your Zillabyte credentials"
163
+ msg += " (or press enter to continue as an anonymous user)." if current_command == "relations"
164
+ puts msg
161
165
  print "Auth Token: "
162
166
  $stdout.flush()
163
167
  auth_token = ask
164
168
  print "\n"
165
- if not valid_credentials?(auth_token)
166
- raise Zillabyte::Auth::InvalidCredentialsException
169
+ if current_command == "relations" and auth_token == ""
170
+ display "No auth token provided, continuing as anonymous user. Note that you will only be shown publicly available listings."
167
171
  else
168
- write_credentials(auth_token)
172
+ if not valid_credentials?(auth_token)
173
+ raise Zillabyte::Auth::InvalidCredentialsException
174
+ else
175
+ write_credentials(auth_token)
176
+ end
169
177
  end
170
178
  rescue Zillabyte::Auth::InvalidCredentialsException => e
171
179
  display "Authentication failed."
@@ -0,0 +1,12 @@
1
+ require "zillabyte/cli/base"
2
+
3
+ # manage custom logs
4
+ #
5
+ class Zillabyte::Command::Logs < Zillabyte::Command::Base
6
+
7
+
8
+
9
+
10
+
11
+
12
+ end