zillabyte-cli 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +29 -0
- data/bin/zillabyte +18 -0
- data/lib/zillabyte/api/base.rb +11 -0
- data/lib/zillabyte/api/data.rb +126 -0
- data/lib/zillabyte/api/flows.rb +239 -0
- data/lib/zillabyte/api/locks.rb +4 -0
- data/lib/zillabyte/api/logs.rb +32 -0
- data/lib/zillabyte/api/metrics.rb +48 -0
- data/lib/zillabyte/api/queries.rb +58 -0
- data/lib/zillabyte/api/semantic_tags.rb +24 -0
- data/lib/zillabyte/api/settings.rb +8 -0
- data/lib/zillabyte/api/sources.rb +28 -0
- data/lib/zillabyte/api/zillalogs.rb +66 -0
- data/lib/zillabyte/api.rb +170 -0
- data/lib/zillabyte/auth.rb +155 -0
- data/lib/zillabyte/cli/auth.rb +33 -0
- data/lib/zillabyte/cli/base.rb +161 -0
- data/lib/zillabyte/cli/config.rb +63 -0
- data/lib/zillabyte/cli/counters.rb +61 -0
- data/lib/zillabyte/cli/flows.rb +702 -0
- data/lib/zillabyte/cli/help.rb +137 -0
- data/lib/zillabyte/cli/helpers/data_schema_builder.rb +3 -0
- data/lib/zillabyte/cli/host.rb +21 -0
- data/lib/zillabyte/cli/logs.rb +118 -0
- data/lib/zillabyte/cli/query.rb +172 -0
- data/lib/zillabyte/cli/relations.rb +326 -0
- data/lib/zillabyte/cli/sources.rb +37 -0
- data/lib/zillabyte/cli/templates/js/simple_function.js +33 -0
- data/lib/zillabyte/cli/templates/js/zillabyte.conf.yaml +2 -0
- data/lib/zillabyte/cli/templates/python/requirements.txt +7 -0
- data/lib/zillabyte/cli/templates/python/simple_function.py +27 -0
- data/lib/zillabyte/cli/templates/python/zillabyte.conf.yaml +4 -0
- data/lib/zillabyte/cli/templates/ruby/Gemfile +3 -0
- data/lib/zillabyte/cli/templates/ruby/simple_function.rb +36 -0
- data/lib/zillabyte/cli/templates/ruby/zillabyte.conf.yaml +2 -0
- data/lib/zillabyte/cli/version.rb +11 -0
- data/lib/zillabyte/cli/zillalogs.rb +86 -0
- data/lib/zillabyte/cli.rb +37 -0
- data/lib/zillabyte/command.rb +254 -0
- data/lib/zillabyte/common/progress.rb +17 -0
- data/lib/zillabyte/common/tar.rb +102 -0
- data/lib/zillabyte/common.rb +13 -0
- data/lib/zillabyte/helpers.rb +49 -0
- data/lib/zillabyte/queries.rb +39 -0
- data/lib/zillabyte-cli/version.rb +5 -0
- data/lib/zillabyte-cli.rb +5 -0
- data/zillabyte-cli.gemspec +42 -0
- data/zillabyte_emails.csv +1 -0
- data/zillaconf.json +3 -0
- metadata +278 -0
@@ -0,0 +1,254 @@
|
|
1
|
+
require 'zillabyte/helpers'
|
2
|
+
require "optparse"
|
3
|
+
|
4
|
+
module Zillabyte
|
5
|
+
module Command
|
6
|
+
class CommandFailed < RuntimeError; end
|
7
|
+
|
8
|
+
extend Zillabyte::Helpers
|
9
|
+
|
10
|
+
def self.load
|
11
|
+
Dir[File.join(File.dirname(__FILE__), "cli", "*.rb")].each do |file|
|
12
|
+
require file
|
13
|
+
end
|
14
|
+
Dir[File.join(File.dirname(__FILE__), "cli", "helpers", "*.rb")].each do |file|
|
15
|
+
require file
|
16
|
+
end
|
17
|
+
unregister_commands_made_private_after_the_fact
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.commands
|
21
|
+
@@commands ||= {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.command_aliases
|
25
|
+
@@command_aliases ||= {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.files
|
29
|
+
@@files ||= Hash.new {|hash,key| hash[key] = File.readlines(key).map {|line| line.strip}}
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.namespaces
|
33
|
+
@@namespaces ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.register_command(command)
|
37
|
+
commands[command[:command]] = command
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.unregister_commands_made_private_after_the_fact
|
41
|
+
commands.values \
|
42
|
+
.select { |c| c[:klass].private_method_defined? c[:method] } \
|
43
|
+
.each { |c| commands.delete c[:command] }
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.register_namespace(namespace)
|
47
|
+
namespaces[namespace[:name]] = namespace
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.current_command
|
51
|
+
@current_command
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.current_command=(new_current_command)
|
55
|
+
@current_command = new_current_command
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.current_args
|
59
|
+
@current_args
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.current_options
|
63
|
+
@current_options ||= {}
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.global_options
|
67
|
+
@global_options ||= []
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.invalid_arguments
|
71
|
+
@invalid_arguments
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.shift_argument
|
75
|
+
# dup argument to get a non-frozen string
|
76
|
+
@invalid_arguments.shift.dup rescue nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.validate_arguments!
|
80
|
+
unless invalid_arguments.empty?
|
81
|
+
arguments = invalid_arguments.map {|arg| "\"#{arg}\""}
|
82
|
+
if arguments.length == 1
|
83
|
+
message = "Invalid argument: #{arguments.first}"
|
84
|
+
elsif arguments.length > 1
|
85
|
+
message = "Invalid arguments: "
|
86
|
+
message << arguments[0...-1].join(", ")
|
87
|
+
message << " and "
|
88
|
+
message << arguments[-1]
|
89
|
+
end
|
90
|
+
$stderr.puts(format_with_bang(message))
|
91
|
+
run(current_command, ["--help"])
|
92
|
+
exit(1)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.warnings
|
97
|
+
@warnings ||= []
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.display_warnings
|
101
|
+
unless warnings.empty?
|
102
|
+
$stderr.puts(warnings.map {|warning| " ! #{warning}"}.join("\n"))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.global_option(name, *args, &blk)
|
107
|
+
# args.sort.reverse gives -l, --long order
|
108
|
+
global_options << { :name => name.to_s, :args => args.sort.reverse, :proc => blk }
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
global_option :help, "-h", "--help"
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
def self.prepare_run(cmd, args=[])
|
117
|
+
command = parse(cmd)
|
118
|
+
|
119
|
+
if args.include?('-h') || args.include?('--help')
|
120
|
+
args.unshift(cmd) unless cmd =~ /^-.*/
|
121
|
+
cmd = 'help'
|
122
|
+
command = parse(cmd)
|
123
|
+
end
|
124
|
+
|
125
|
+
if cmd == '--version' or cmd == '-version'
|
126
|
+
cmd = 'version'
|
127
|
+
command = parse(cmd)
|
128
|
+
end
|
129
|
+
|
130
|
+
@current_command = cmd
|
131
|
+
@anonymized_args, @normalized_args = [], []
|
132
|
+
|
133
|
+
opts = {}
|
134
|
+
invalid_options = []
|
135
|
+
|
136
|
+
parser = OptionParser.new do |parser|
|
137
|
+
# remove OptionParsers Officious['version'] to avoid conflicts
|
138
|
+
# see: https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L814
|
139
|
+
parser.base.long.delete('version')
|
140
|
+
(global_options + (command && command[:options] || [])).each do |option|
|
141
|
+
parser.on(*option[:args]) do |value|
|
142
|
+
if option[:proc]
|
143
|
+
option[:proc].call(value)
|
144
|
+
end
|
145
|
+
opts[option[:name].gsub('-', '_').to_sym] = value
|
146
|
+
ARGV.join(' ') =~ /(#{option[:args].map {|arg| arg.split(' ', 2).first}.join('|')})/
|
147
|
+
@anonymized_args << "#{$1} _"
|
148
|
+
@normalized_args << "#{option[:args].last.split(' ', 2).first} _"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
begin
|
154
|
+
parser.order!(args) do |nonopt|
|
155
|
+
invalid_options << nonopt
|
156
|
+
@anonymized_args << '!'
|
157
|
+
@normalized_args << '!'
|
158
|
+
end
|
159
|
+
rescue OptionParser::InvalidOption => ex
|
160
|
+
invalid_options << ex.args.first
|
161
|
+
@anonymized_args << '!'
|
162
|
+
@normalized_args << '!'
|
163
|
+
retry
|
164
|
+
end
|
165
|
+
|
166
|
+
args.concat(invalid_options)
|
167
|
+
|
168
|
+
@current_args = args
|
169
|
+
@current_options = opts
|
170
|
+
@invalid_arguments = invalid_options
|
171
|
+
|
172
|
+
@anonymous_command = [ARGV.first, *@anonymized_args].join(' ')
|
173
|
+
begin
|
174
|
+
usage_directory = "#{home_directory}/.zillabyte/usage"
|
175
|
+
FileUtils.mkdir_p(usage_directory)
|
176
|
+
usage_file = usage_directory << "/#{Zillabyte::CLI::VERSION}"
|
177
|
+
usage = if File.exists?(usage_file)
|
178
|
+
json_decode(File.read(usage_file))
|
179
|
+
else
|
180
|
+
{}
|
181
|
+
end
|
182
|
+
usage[@anonymous_command] ||= 0
|
183
|
+
usage[@anonymous_command] += 1
|
184
|
+
File.write(usage_file, json_encode(usage) + "\n")
|
185
|
+
rescue
|
186
|
+
# usage writing is not important, allow failures
|
187
|
+
end
|
188
|
+
|
189
|
+
if command
|
190
|
+
command_instance = command[:klass].new(args.dup, opts.dup)
|
191
|
+
|
192
|
+
if !@normalized_args.include?('--app _') && (implied_app = command_instance.app rescue nil)
|
193
|
+
@normalized_args << '--app _'
|
194
|
+
end
|
195
|
+
@normalized_command = [ARGV.first, @normalized_args.sort_by {|arg| arg.gsub('-', '')}].join(' ')
|
196
|
+
|
197
|
+
[ command_instance, command[:method] ]
|
198
|
+
else
|
199
|
+
error([
|
200
|
+
"`#{cmd}` is not a zillabyte command.",
|
201
|
+
"See `zillabyte help` for a list of available commands."
|
202
|
+
].compact.join("\n"))
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.run(cmd, arguments=[])
|
207
|
+
begin
|
208
|
+
object, method = prepare_run(cmd, arguments.dup)
|
209
|
+
object.send(method)
|
210
|
+
rescue Excon::Errors::SocketError => e
|
211
|
+
error "remote server error: #{e.message}"
|
212
|
+
rescue Errno::ECONNREFUSED => e
|
213
|
+
error "remote server error: #{e.message}"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.parse(cmd)
|
218
|
+
commands[cmd] || commands[command_aliases[cmd]]
|
219
|
+
end
|
220
|
+
|
221
|
+
def self.extract_error(body, options={})
|
222
|
+
default_error = block_given? ? yield : "Internal server error.\nRun `zillabyte status` to check for known platform issues."
|
223
|
+
parse_error_xml(body) || parse_error_json(body) || parse_error_plain(body) || default_error
|
224
|
+
end
|
225
|
+
|
226
|
+
def self.parse_error_xml(body)
|
227
|
+
xml_errors = REXML::Document.new(body).elements.to_a("//errors/error")
|
228
|
+
msg = xml_errors.map { |a| a.text }.join(" / ")
|
229
|
+
return msg unless msg.empty?
|
230
|
+
rescue Exception
|
231
|
+
end
|
232
|
+
|
233
|
+
def self.parse_error_json(body)
|
234
|
+
json = json_decode(body.to_s) rescue false
|
235
|
+
case json
|
236
|
+
when Array
|
237
|
+
json.first.join(' ') # message like [['base', 'message']]
|
238
|
+
when Hash
|
239
|
+
json['error'] # message like {'error' => 'message'}
|
240
|
+
else
|
241
|
+
nil
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def self.parse_error_plain(body)
|
246
|
+
return unless body.respond_to?(:headers) && body.headers[:content_type].to_s.include?("text/plain")
|
247
|
+
body.to_s
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
end
|
254
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# https://gist.github.com/sinisterchipmunk/1335041
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubygems/package'
|
5
|
+
require 'zlib'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module Zillabyte::Common
|
9
|
+
class Tar
|
10
|
+
|
11
|
+
# Creates a tar file in memory recursively
|
12
|
+
# from the given path.
|
13
|
+
#
|
14
|
+
# Optional second argument (ignore_files) allows file
|
15
|
+
# exclusion.
|
16
|
+
#
|
17
|
+
# Returns a StringIO whose underlying String
|
18
|
+
# is the contents of the tar file.
|
19
|
+
def self.tar(path, ignore_files = [])
|
20
|
+
tarfile = StringIO.new("")
|
21
|
+
ignore_regexp = if ignore_files.empty?()
|
22
|
+
[]
|
23
|
+
else
|
24
|
+
/^(#{ignore_files.map { |ignore_file|
|
25
|
+
Regexp::escape(ignore_file)
|
26
|
+
}.join("|")})(?:\/|$)/
|
27
|
+
end
|
28
|
+
Gem::Package::TarWriter.new(tarfile) do |tar|
|
29
|
+
# If the path is a directory, then tar up the dir
|
30
|
+
if(File.directory?(path))
|
31
|
+
Dir[File.join(path, "**/*")].each do |file|
|
32
|
+
mode = File.stat(file).mode
|
33
|
+
relative_file = file.sub /^#{Regexp::escape path}\/?/, ''
|
34
|
+
is_directory = File.directory?(file)
|
35
|
+
# Skip ignored files.
|
36
|
+
next if relative_file =~ ignore_regexp
|
37
|
+
if File.directory?(file)
|
38
|
+
tar.mkdir relative_file, mode
|
39
|
+
else
|
40
|
+
tar.add_file relative_file, mode do |tf|
|
41
|
+
File.open(file, "rb") { |f| tf.write f.read }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
# If the path is just a single file, then just tar it up
|
46
|
+
elsif !(path =~ ignore_regexp)
|
47
|
+
mode = File.stat(path).mode
|
48
|
+
tar.add_file path, mode do |tf|
|
49
|
+
File.open(path, "rb") { |f| tf.write f.read }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
tarfile.rewind
|
55
|
+
tarfile
|
56
|
+
end
|
57
|
+
|
58
|
+
# gzips the underlying string in the given StringIO,
|
59
|
+
# returning a new StringIO representing the
|
60
|
+
# compressed file.
|
61
|
+
def self.gzip(tarfile)
|
62
|
+
gz = StringIO.new("")
|
63
|
+
z = Zlib::GzipWriter.new(gz)
|
64
|
+
z.write tarfile.string
|
65
|
+
z.close # this is necessary!
|
66
|
+
|
67
|
+
# z was closed to write the gzip footer, so
|
68
|
+
# now we need a new StringIO
|
69
|
+
StringIO.new gz.string
|
70
|
+
end
|
71
|
+
|
72
|
+
# un-gzips the given IO, returning the
|
73
|
+
# decompressed version as a StringIO
|
74
|
+
def self.ungzip(tarfile)
|
75
|
+
z = Zlib::GzipReader.new(tarfile)
|
76
|
+
unzipped = StringIO.new(z.read)
|
77
|
+
z.close
|
78
|
+
unzipped
|
79
|
+
end
|
80
|
+
|
81
|
+
# untars the given IO into the specified
|
82
|
+
# directory
|
83
|
+
def self.untar(io, destination)
|
84
|
+
Gem::Package::TarReader.new io do |tar|
|
85
|
+
tar.each do |tarfile|
|
86
|
+
destination_file = File.join destination, tarfile.full_name
|
87
|
+
|
88
|
+
if tarfile.directory?
|
89
|
+
FileUtils.mkdir_p destination_file
|
90
|
+
else
|
91
|
+
destination_directory = File.dirname(destination_file)
|
92
|
+
FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
|
93
|
+
File.open destination_file, "wb" do |f|
|
94
|
+
f.print tarfile.read
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# require "vendor/zillabyte/okjson"
|
2
|
+
|
3
|
+
module Zillabyte
|
4
|
+
module Helpers
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def display(msg="", new_line=true)
|
8
|
+
if new_line
|
9
|
+
puts(msg)
|
10
|
+
else
|
11
|
+
print(msg)
|
12
|
+
$stdout.flush
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def error(message)
|
18
|
+
$stderr.puts(format_with_bang(message))
|
19
|
+
exit(1)
|
20
|
+
end
|
21
|
+
|
22
|
+
def format_with_bang(message)
|
23
|
+
return '' if message.to_s.strip == ""
|
24
|
+
" ! " + message.split("\n").join("\n ! ")
|
25
|
+
end
|
26
|
+
|
27
|
+
def longest(items)
|
28
|
+
items.map { |i| i.to_s.length }.sort.last
|
29
|
+
end
|
30
|
+
|
31
|
+
def read_multiline
|
32
|
+
$stdin.gets
|
33
|
+
end
|
34
|
+
|
35
|
+
def ask
|
36
|
+
$stdin.gets.to_s.strip
|
37
|
+
end
|
38
|
+
|
39
|
+
def with_tty(&block)
|
40
|
+
return unless $stdin.isatty
|
41
|
+
begin
|
42
|
+
yield
|
43
|
+
rescue
|
44
|
+
# fails on windows
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Zillabyte::Queries
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
def self.array_to_sxp_expression(exp)
|
6
|
+
s = []
|
7
|
+
s << "("
|
8
|
+
s << exp[0]
|
9
|
+
exp[1].each do |ss|
|
10
|
+
s << " "
|
11
|
+
s << ss
|
12
|
+
end
|
13
|
+
s << ")"
|
14
|
+
s = s.join("")
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def self.convert_clause_to_sxp(match)
|
19
|
+
return nil if match.nil? or match.size == 0
|
20
|
+
queue = match.clone
|
21
|
+
s = array_to_sxp_expression(queue.shift)
|
22
|
+
while queue.size > 0
|
23
|
+
next_exp = array_to_sxp_expression(queue.shift)
|
24
|
+
s = "(and #{s} #{next_exp})"
|
25
|
+
end
|
26
|
+
s
|
27
|
+
end
|
28
|
+
|
29
|
+
# def self.load
|
30
|
+
# Dir[File.join(File.dirname(__FILE__), "functions", "*.rb")].each do |file|
|
31
|
+
# require file
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# Load all helpers...
|
38
|
+
# Zillabyte::Functions.load()
|
39
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'zillabyte-cli/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "zillabyte-cli"
|
8
|
+
spec.version = Zillabyte::CLI::VERSION
|
9
|
+
spec.authors = ["zillabyte"]
|
10
|
+
spec.email = ["gem@zillabyte.com"]
|
11
|
+
spec.description = %q{The Official Zillabyte CLI Gem}
|
12
|
+
spec.summary = %q{The Official Zillabyte CLI Gem}
|
13
|
+
spec.homepage = "http://www.zillabyte.com"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
if File.directory?(".git")
|
17
|
+
spec.files = Dir.glob("{bin,lib}/**/*") + %w(LICENSE README.md zillabyte_emails.csv zillaconf.json Gemfile zillabyte-cli.gemspec)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
end
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
|
26
|
+
spec.add_dependency "netrc", "~> 0.7.7"
|
27
|
+
spec.add_dependency "rest-client", "~> 1.6.1"
|
28
|
+
|
29
|
+
spec.add_dependency "excon"
|
30
|
+
spec.add_dependency "terminal-table"
|
31
|
+
spec.add_dependency "activesupport", "~> 3.2.11"
|
32
|
+
|
33
|
+
spec.add_dependency "colorize"
|
34
|
+
spec.add_dependency "chronic"
|
35
|
+
spec.add_dependency "ascii_charts"
|
36
|
+
spec.add_dependency "indentation"
|
37
|
+
|
38
|
+
spec.add_dependency "bundler"
|
39
|
+
|
40
|
+
spec.add_dependency "mkfifo"
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
bob@zillabyte.com
|
data/zillaconf.json
ADDED