zillabyte-cli 0.0.9
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 +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