hotdog 0.5.4 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dad54741d7b612af34df19f0ae934c938411a941
4
- data.tar.gz: 951a0d2bafcf5edbc3262e9f1552b4aade13fc0c
3
+ metadata.gz: f3bcc93be20391d227013b6c05bb9113d68bc404
4
+ data.tar.gz: 3a8bc479c3122dc4b18ecf37d575e7b49dd8c1f8
5
5
  SHA512:
6
- metadata.gz: 9c4fdc6b65e2caa37150c2e47bf207cacfec32d775e7f23b9e7b79298935853b5c34dc094d75ee21b48187d9440b3d4d9ae787a212387a5ae3415e1e5caac7df
7
- data.tar.gz: 8e71095cbea2abee8f03173cfda463b289326a4a2a0fa187bd45040856e32e287f8ab84c270bacaa785f15ec6dddb052e126941438c6a353ed9d5e417b74140c
6
+ metadata.gz: 8c9646d739e72b331cdfdf145da4e93b0c44598b64618a20db48eff13185a9bc277550581f2288e20ee548c8001466c454d30d43df900d9cef8e773bcf5f4bef
7
+ data.tar.gz: d51c0697ca67251ded20b0c2807af26ead5d4f7ed87b3c189ee109ff464c2a5cfccc82efeff20ec8f6cdcd0a2a07ab4ee5c1f374d1df4c14cdf9d5b98994fe03
data/hotdog.gemspec CHANGED
@@ -23,7 +23,9 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "rspec", "~> 3.3.0"
24
24
 
25
25
  spec.add_dependency "dogapi", ">= 1.13.0"
26
+ spec.add_dependency "multi_json", "~> 1.11.2"
27
+ spec.add_dependency "oj", "~> 2.12.14"
28
+ spec.add_dependency "parallel", "~> 1.6.1"
26
29
  spec.add_dependency "parslet", "~> 1.6.2"
27
30
  spec.add_dependency "sqlite3", "~> 1.3.10"
28
- spec.add_dependency "parallel", "~> 1.4.1"
29
31
  end
@@ -13,6 +13,7 @@ module Hotdog
13
13
  @optparse = OptionParser.new
14
14
  @optparse.version = Hotdog::VERSION
15
15
  @options = {
16
+ endpoint: ENV.fetch("DATADOG_HOST", "https://app.datadoghq.com"),
16
17
  api_key: ENV["DATADOG_API_KEY"],
17
18
  application_key: ENV["DATADOG_APPLICATION_KEY"],
18
19
  application: self,
@@ -53,7 +54,7 @@ module Hotdog
53
54
 
54
55
  begin
55
56
  command = ( args.shift || "help" )
56
- get_command(command).new(self).tap do |cmd|
57
+ get_command(command).tap do |cmd|
57
58
  @optparse.banner = "Usage: hotdog #{command} [options]"
58
59
  cmd.define_options(@optparse, @options)
59
60
  args = cmd.parse_options(@optparse, args)
@@ -69,7 +70,7 @@ module Hotdog
69
70
  options[:headers] = true
70
71
  end
71
72
 
72
- options[:formatter] = get_formatter(options[:format]).new
73
+ options[:formatter] = get_formatter(options[:format])
73
74
 
74
75
  if options[:debug] or options[:verbose]
75
76
  options[:logger].level = Logger::DEBUG
@@ -86,6 +87,9 @@ module Hotdog
86
87
 
87
88
  private
88
89
  def define_options
90
+ @optparse.on("--endpoint ENDPOINT", "Datadog API endpoint") do |endpoint|
91
+ options[:endpoint] = endpoint
92
+ end
89
93
  @optparse.on("--api-key API_KEY", "Datadog API key") do |api_key|
90
94
  options[:api_key] = api_key
91
95
  end
@@ -139,29 +143,31 @@ module Hotdog
139
143
 
140
144
  def get_formatter(name)
141
145
  begin
142
- Hotdog::Formatters.const_get(const_name(name))
146
+ klass = Hotdog::Formatters.const_get(const_name(name))
143
147
  rescue NameError
144
148
  if library = find_library("hotdog/formatters", name)
145
149
  load library
146
- Hotdog::Formatters.const_get(const_name(File.basename(library, ".rb")))
150
+ klass = Hotdog::Formatters.const_get(const_name(File.basename(library, ".rb")))
147
151
  else
148
152
  raise(NameError.new("unknown format: #{name}"))
149
153
  end
150
154
  end
155
+ klass.new
151
156
  end
152
157
 
153
158
  def get_command(name)
154
159
  begin
155
- Hotdog::Commands.const_get(const_name(name))
160
+ klass = Hotdog::Commands.const_get(const_name(name))
156
161
  rescue NameError
157
162
  if library = find_library("hotdog/commands", name)
158
163
  load library
159
- Hotdog::Commands.const_get(const_name(File.basename(library, ".rb")))
164
+ klass = Hotdog::Commands.const_get(const_name(File.basename(library, ".rb")))
160
165
  else
161
166
  require "hotdog/commands/help"
162
- Hotdog::Commands::Help
167
+ klass = Hotdog::Commands::Help
163
168
  end
164
169
  end
170
+ klass.new(self)
165
171
  end
166
172
 
167
173
  def find_library(dirname, name)
@@ -6,13 +6,13 @@ module Hotdog
6
6
  module Commands
7
7
  class Down < BaseCommand
8
8
  def define_options(optparse, options={})
9
- @downtime = 86400
10
- @start = Time.new
9
+ options[:downtime] = 86400
10
+ options[:start] = Time.new
11
11
  optparse.on("--downtime DURATION") do |v|
12
- @downtime = v.to_i
12
+ options[:downtime] = v.to_i
13
13
  end
14
14
  optparse.on("--start TIME") do |v|
15
- @start = Time.parse(v)
15
+ options[:start] = Time.parse(v)
16
16
  end
17
17
  end
18
18
 
@@ -23,8 +23,8 @@ module Hotdog
23
23
  else
24
24
  scope = arg
25
25
  end
26
- code, schedule = @dog.schedule_downtime(scope, :start => @start.to_i, :end => (@start+@downtime).to_i)
27
- logger.debug("dog.schedule_donwtime(%s, :start => %s, :end => %s) #==> [%s, %s]" % [scope.inspect, @start.to_i, (@start+@downtime).to_i, code.inspect, schedule.inspect])
26
+ code, schedule = dog.schedule_downtime(scope, :start => options[:start].to_i, :end => (options[:start]+options[:downtime]).to_i)
27
+ logger.debug("dog.schedule_donwtime(%s, :start => %s, :end => %s) #==> [%s, %s]" % [scope.inspect, options[:start].to_i, (options[:start]+options[:downtime]).to_i, code.inspect, schedule.inspect])
28
28
  if code.to_i / 100 != 2
29
29
  raise("dog.schedule_downtime(%s, ...) returns [%s, %s]" % [scope.inspect, code.inspect, schedule.inspect])
30
30
  end
@@ -14,7 +14,9 @@ module Hotdog
14
14
  options[:user] = nil
15
15
  options[:port] = nil
16
16
  options[:identity_file] = nil
17
+ options[:forward_agent] = false
17
18
  options[:max_parallelism] = nil
19
+ options[:color] = :auto
18
20
 
19
21
  optparse.on("-o SSH_OPTION", "Passes this string to ssh command through shell. This option may be given multiple times") do |option|
20
22
  options[:options] += [option]
@@ -22,6 +24,9 @@ module Hotdog
22
24
  optparse.on("-i SSH_IDENTITY_FILE", "SSH identity file path") do |path|
23
25
  options[:identity_file] = path
24
26
  end
27
+ optparse.on("-A", "Enable agent forwarding", TrueClass) do |b|
28
+ options[:forward_agent] = b
29
+ end
25
30
  optparse.on("-p PORT", "Port of the remote host", Integer) do |port|
26
31
  options[:port] = port
27
32
  end
@@ -31,13 +36,30 @@ module Hotdog
31
36
  optparse.on("-P PARALLELISM", "Max parallelism", Integer) do |n|
32
37
  options[:max_parallelism] = n
33
38
  end
39
+ optparse.on("-v", "--verbose", "Enable verbose ode") do |v|
40
+ options[:verbose] = v
41
+ end
42
+ optparse.on("--color=WHEN", "--colour=WHEN", "Enable colors") do |color|
43
+ options[:color] = color
44
+ end
34
45
  end
35
46
 
47
+ def parse_options(optparse, args=[])
48
+ if args.index("--")
49
+ @remote_command = args.slice(args.index("--") + 1, args.length).join(" ")
50
+ optparse.parse(args.slice(0, args.index("--")))
51
+ else
52
+ @remote_command = nil
53
+ optparse.parse(args)
54
+ end
55
+ end
56
+ attr_reader :remote_command
57
+
36
58
  def run(args=[], options={})
37
- use_color = STDOUT.tty?
38
59
  expression = args.join(" ").strip
39
- if expression.empty? || args.empty?
40
- exit(1)
60
+ if expression.empty?
61
+ # return everything if given expression is empty
62
+ expression = "*"
41
63
  end
42
64
 
43
65
  begin
@@ -47,61 +69,76 @@ module Hotdog
47
69
  exit(1)
48
70
  end
49
71
 
50
- result = evaluate(node, self)
51
- result, fields = get_hosts(result)
52
-
53
- if result.empty?
54
- STDERR.puts("no match found: #{search_args.join(" ")}")
72
+ result0 = evaluate(node, self)
73
+ if 0 < result0.length
74
+ exec_command(result0, options)
75
+ else
76
+ STDERR.puts("no match found: #{expression}")
55
77
  exit(1)
56
78
  end
79
+ end
57
80
 
58
- addresses = result.map {|host| [host.first, host.last] }
59
-
60
- # build ssh command
61
- cmdline = ["ssh"]
62
- options[:options].each do |option|
63
- cmdline << "-o" << option
64
- end
65
- if path = options[:identity_file]
66
- cmdline << "-i" << Shellwords.escape(path)
67
- end
68
- if port = options[:port]
69
- cmdline << "-p" << port.to_s
70
- end
71
- if options[:forward_agent]
72
- cmdline << "-A"
73
- end
74
-
75
- cmdline << "-o" << "BatchMode=yes"
76
-
77
- user = options[:user]
78
-
79
- threads = options[:max_parallelism] || addresses.size
80
- stats = Parallel.map(addresses, in_threads: threads) { |address,name|
81
- if use_color
81
+ def exec_command(result0, options={})
82
+ result, fields = get_hosts(result0)
83
+ hosts = result.flatten
84
+ threads = options[:max_parallelism] || hosts.size
85
+ stats = Parallel.map(hosts.zip(hosts), in_threads: threads) { |host, name|
86
+ if use_color?
82
87
  header = "\e[0;36m#{name}\e[00m"
83
88
  else
84
89
  header = name
85
90
  end
86
- c = cmdline.dup
87
- if user
88
- c << (user + "@" + address)
89
- else
90
- c << address
91
- end
92
- logger.debug("execute: #{Shellwords.join(c)}")
93
- IO.popen([*c, in: :close, err: [:child, :out]]) do |io|
91
+ cmdline = build_command_string(host, options)
92
+ logger.debug("execute: #{cmdline}")
93
+ IO.popen(cmdline, in: :close, err: [:child, :out]) do |io|
94
94
  io.each_line do |line|
95
- STDOUT.write "#{header}: #{line}"
95
+ STDOUT.write("#{header}: #{line}")
96
96
  end
97
97
  end
98
98
  $?.success? # $? is thread-local variable
99
99
  }
100
-
101
100
  unless stats.all?
102
101
  exit(1)
103
102
  end
104
103
  end
104
+
105
+ def build_command_string(host, options={})
106
+ # build ssh command
107
+ base_cmdline = ["ssh"]
108
+ if options[:forward_agent]
109
+ base_cmdline << "-A"
110
+ end
111
+ if options[:identity_file]
112
+ base_cmdline << "-i" << options[:identity_file]
113
+ end
114
+ if options[:user]
115
+ base_cmdline << "-l" << options[:user]
116
+ end
117
+ base_cmdline << "-o" << "BatchMode=yes"
118
+ if options[:options]
119
+ base_cmdline += options[:options].flat_map { |option| ["-o", option] }
120
+ end
121
+ if options[:port]
122
+ base_cmdline << "-p" << options[:port].to_s
123
+ end
124
+ cmdline = base_cmdline + [host]
125
+ if @remote_command
126
+ cmdline << "--" << @remote_command
127
+ end
128
+ Shellwords.join(cmdline)
129
+ end
130
+
131
+ private
132
+ def use_color?
133
+ case options[:color]
134
+ when :always
135
+ true
136
+ when :never
137
+ false
138
+ else
139
+ STDOUT.tty?
140
+ end
141
+ end
105
142
  end
106
143
  end
107
144
  end
@@ -26,18 +26,18 @@ module Hotdog
26
26
  exit(1)
27
27
  end
28
28
 
29
- result = evaluate(node, self)
30
- if 0 < result.length
31
- _result, fields = get_hosts_with_search_tags(result, node)
32
- result = _result.take(options.fetch(:limit, _result.size))
33
- STDOUT.print(format(result, fields: fields))
34
- if _result.length == result.length
35
- logger.info("found %d host(s)." % result.length)
29
+ result0 = evaluate(node, self)
30
+ if 0 < result0.length
31
+ result, fields = get_hosts_with_search_tags(result0, node)
32
+ if options[:limit]
33
+ STDOUT.print(format(result.take(options[:limit]), fields: fields))
34
+ logger.info("found %d host(s), limited to %d in result." % [result.length, options[:limit]])
36
35
  else
37
- logger.info("found %d host(s), limited to %d in result." % [_result.length, result.length])
36
+ STDOUT.print(format(result, fields: fields))
37
+ logger.info("found %d host(s)." % result.length)
38
38
  end
39
39
  else
40
- STDERR.puts("no match found: #{args.join(" ")}")
40
+ STDERR.puts("no match found: #{expression}")
41
41
  exit(1)
42
42
  end
43
43
  end
@@ -15,7 +15,6 @@ module Hotdog
15
15
  options[:port] = nil
16
16
  options[:identity_file] = nil
17
17
  options[:forward_agent] = false
18
- options[:verbose] = false
19
18
 
20
19
  optparse.on("-n", "--index INDEX", "Use this index of host if multiple servers are found", Integer) do |index|
21
20
  options[:index] = index
@@ -40,10 +39,22 @@ module Hotdog
40
39
  end
41
40
  end
42
41
 
42
+ def parse_options(optparse, args=[])
43
+ if args.index("--")
44
+ @remote_command = args.slice(args.index("--") + 1, args.length).join(" ")
45
+ optparse.parse(args.slice(0, args.index("--")))
46
+ else
47
+ @remote_command = nil
48
+ optparse.parse(args)
49
+ end
50
+ end
51
+ attr_reader :remote_command
52
+
43
53
  def run(args=[], options={})
44
54
  expression = args.join(" ").strip
45
55
  if expression.empty?
46
- exit(1)
56
+ # return everything if given expression is empty
57
+ expression = "*"
47
58
  end
48
59
 
49
60
  begin
@@ -53,57 +64,66 @@ module Hotdog
53
64
  exit(1)
54
65
  end
55
66
 
56
- result = evaluate(node, self)
57
-
58
- if result.length == 1
59
- host = result[0]
60
- elsif result.empty?
61
- STDERR.puts("no match found: #{search_args.join(" ")}")
62
- exit(1)
63
- else
64
- if options[:index] && result.length > options[:index]
65
- host = result[options[:index]]
67
+ result0 = evaluate(node, self)
68
+ if 0 < result0.length
69
+ if result0.length == 1
70
+ exec_command([result0.first], options)
66
71
  else
67
- result, fields = get_hosts_with_search_tags(result, node)
72
+ if options[:index] and options[:index] < result0.length
73
+ exec_command([result0[options[:index]]], options)
74
+ else
75
+ result, fields = get_hosts_with_search_tags(result0, node)
68
76
 
69
- # add "index" field
70
- result = result.each_with_index.map {|host,i| [i] + host }
71
- fields = ["index"] + fields
77
+ # add "index" field
78
+ result = result.each_with_index.map { |host, i| [i] + host }
79
+ fields = ["index"] + fields
72
80
 
73
- STDERR.print(format(result, fields: fields))
74
- logger.info("found %d host(s)." % result.length)
75
- exit(1)
81
+ STDERR.print(format(result, fields: fields))
82
+ logger.info("found %d host(s)." % result.length)
83
+ exit(1)
84
+ end
76
85
  end
86
+ else
87
+ STDERR.puts("no match found: #{expression}")
88
+ exit(1)
77
89
  end
90
+ exit(127)
91
+ end
78
92
 
79
- result, fields = get_hosts([host])
80
- address = result.flatten.first
93
+ def exec_command(result0, options={})
94
+ result, fields = get_hosts(result0)
95
+ hosts = result.flatten
96
+ cmdline = build_command_string(hosts.first, options)
97
+ logger.debug("execute: #{cmdline}")
98
+ exec(cmdline)
99
+ end
81
100
 
101
+ def build_command_string(host, options={})
82
102
  # build ssh command
83
- cmdline = ["ssh"]
84
- options[:options].each do |option|
85
- cmdline << "-o" << option
103
+ base_cmdline = ["ssh"]
104
+ if options[:forward_agent]
105
+ base_cmdline << "-A"
86
106
  end
87
- if path = options[:identity_file]
88
- cmdline << "-i" << Shellwords.escape(path)
107
+ if options[:identity_file]
108
+ base_cmdline << "-i" << options[:identity_file]
89
109
  end
90
- if port = options[:port]
91
- cmdline << "-p" << port.to_s
110
+ if options[:user]
111
+ base_cmdline << "-l" << options[:user]
92
112
  end
93
- if options[:forward_agent]
94
- cmdline << "-A"
113
+ if options[:options]
114
+ base_cmdline += options[:options].flat_map { |option| ["-o", option] }
115
+ end
116
+ if options[:port]
117
+ base_cmdline << "-p" << options[:port].to_s
95
118
  end
96
119
  if options[:verbose]
97
- cmdline << "-v"
120
+ base_cmdline << "-v"
98
121
  end
99
- if user = options[:user]
100
- cmdline << (user + "@" + address)
101
- else
102
- cmdline << address
122
+ cmdline = base_cmdline + [host]
123
+ if @remote_command
124
+ cmdline << "--" << @remote_command
103
125
  end
104
- logger.debug("execute: #{Shellwords.join(cmdline)}")
105
- exec(*cmdline)
106
- exit(127)
126
+ Shellwords.join(cmdline)
107
127
  end
108
128
  end
109
129
  end
@@ -13,7 +13,7 @@ module Hotdog
13
13
  arg
14
14
  end
15
15
  }
16
- code, all_downtimes = @dog.get_all_downtimes()
16
+ code, all_downtimes = dog.get_all_downtimes()
17
17
  if code.to_i / 100 != 2
18
18
  raise("dog.get_all_downtimes() returns [%s, %s]" % [code.inspect, all_downtimes.inspect])
19
19
  end
@@ -23,7 +23,7 @@ module Hotdog
23
23
  }
24
24
 
25
25
  cancel_downtimes.each do |downtime|
26
- code, cancel = @dog.cancel_downtime(downtime["id"])
26
+ code, cancel = dog.cancel_downtime(downtime["id"])
27
27
  if code.to_i / 100 != 2
28
28
  raise("dog.cancel_downtime(%s) returns [%s, %s]" % [downtime["id"].inspect, code.inspect, cancel.inspect])
29
29
  end
@@ -2,8 +2,12 @@
2
2
 
3
3
  require "fileutils"
4
4
  require "dogapi"
5
- require "json"
5
+ require "multi_json"
6
+ require "oj"
7
+ require "open-uri"
8
+ require "parallel"
6
9
  require "sqlite3"
10
+ require "uri"
7
11
 
8
12
  module Hotdog
9
13
  module Commands
@@ -18,7 +22,7 @@ module Hotdog
18
22
  @application = application
19
23
  @logger = application.options[:logger]
20
24
  @options = application.options
21
- @dog = Dogapi::Client.new(options[:api_key], options[:application_key])
25
+ @dog = nil # lazy initialization
22
26
  @prepared_statements = {}
23
27
  end
24
28
  attr_reader :application
@@ -31,13 +35,7 @@ module Hotdog
31
35
 
32
36
  def execute(q, args=[])
33
37
  update_db
34
- begin
35
- logger.debug("execute: #{q} -- #{args.inspect}")
36
- prepare(@db, q).execute(args)
37
- rescue
38
- logger.error("failed: #{q} -- #{args.inspect}")
39
- raise
40
- end
38
+ execute_db(@db, q, args)
41
39
  end
42
40
 
43
41
  def fixed_string?()
@@ -183,9 +181,12 @@ module Hotdog
183
181
  if (not options[:force] and File.exist?(persistent) and Time.new < File.mtime(persistent) + options[:expiry]) or options[:offline]
184
182
  begin
185
183
  persistent_db = SQLite3::Database.new(persistent)
186
- persistent_db.execute("SELECT id, name FROM hosts LIMIT 1")
187
- persistent_db.execute("SELECT id, name, value FROM tags LIMIT 1")
188
- persistent_db.execute("SELECT host_id, tag_id FROM hosts_tags LIMIT 1")
184
+ persistent_db.execute(<<-EOS)
185
+ SELECT hosts_tags.host_id FROM hosts_tags
186
+ INNER JOIN hosts ON hosts_tags.host_id = hosts.id
187
+ INNER JOIN tags ON hosts_tags.tag_id = tags.id
188
+ LIMIT 1;
189
+ EOS
189
190
  @db = persistent_db
190
191
  return
191
192
  rescue SQLite3::SQLException
@@ -198,12 +199,28 @@ module Hotdog
198
199
  end
199
200
 
200
201
  memory_db = SQLite3::Database.new(":memory:")
201
- create_table_hosts(memory_db)
202
- create_index_hosts(memory_db)
203
- create_table_tags(memory_db)
204
- create_index_tags(memory_db)
205
- create_table_hosts_tags(memory_db)
206
- create_index_hosts_tags(memory_db)
202
+ execute_db(memory_db, <<-EOS)
203
+ CREATE TABLE IF NOT EXISTS hosts (
204
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
205
+ name VARCHAR(255) NOT NULL COLLATE NOCASE
206
+ );
207
+ EOS
208
+ execute_db(memory_db, "CREATE UNIQUE INDEX IF NOT EXISTS hosts_name ON hosts ( name );")
209
+ execute_db(memory_db, <<-EOS)
210
+ CREATE TABLE IF NOT EXISTS tags (
211
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
212
+ name VARCHAR(200) NOT NULL COLLATE NOCASE,
213
+ value VARCHAR(200) NOT NULL COLLATE NOCASE
214
+ );
215
+ EOS
216
+ execute_db(memory_db, "CREATE UNIQUE INDEX IF NOT EXISTS tags_name_value ON tags ( name, value );")
217
+ execute_db(memory_db, <<-EOS)
218
+ CREATE TABLE IF NOT EXISTS hosts_tags (
219
+ host_id INTEGER NOT NULL,
220
+ tag_id INTEGER NOT NULL
221
+ );
222
+ EOS
223
+ execute_db(memory_db, "CREATE UNIQUE INDEX IF NOT EXISTS hosts_tags_host_id_tag_id ON hosts_tags ( host_id, tag_id );")
207
224
 
208
225
  all_tags = get_all_tags()
209
226
 
@@ -211,23 +228,13 @@ module Hotdog
211
228
  known_tags = all_tags.keys.map { |tag| split_tag(tag) }.uniq
212
229
  known_tags.each_slice(SQLITE_LIMIT_COMPOUND_SELECT / 2) do |known_tags|
213
230
  q = "INSERT OR IGNORE INTO tags (name, value) VALUES %s" % known_tags.map { "(?, ?)" }.join(", ")
214
- begin
215
- prepare(memory_db, q).execute(known_tags)
216
- rescue
217
- logger.error("failed: #{q} -- #{known_tags.inspect}")
218
- raise
219
- end
231
+ execute_db(memory_db, q, known_tags)
220
232
  end
221
233
 
222
234
  known_hosts = all_tags.values.reduce(:+).uniq
223
235
  known_hosts.each_slice(SQLITE_LIMIT_COMPOUND_SELECT) do |known_hosts|
224
236
  q = "INSERT OR IGNORE INTO hosts (name) VALUES %s" % known_hosts.map { "(?)" }.join(", ")
225
- begin
226
- prepare(memory_db, q).execute(known_hosts)
227
- rescue
228
- logger.error("failed: #{q} -- #{known_hosts.inspect}")
229
- raise
230
- end
237
+ execute_db(memory_db, q, known_hosts)
231
238
  end
232
239
 
233
240
  all_tags.each do |tag, hosts|
@@ -237,10 +244,18 @@ module Hotdog
237
244
  "( SELECT id FROM hosts WHERE name IN (%s) ) AS host, " \
238
245
  "( SELECT id FROM tags WHERE name = ? AND value = ? LIMIT 1 ) AS tag;" % hosts.map { "?" }.join(", ")
239
246
  begin
240
- prepare(memory_db, q).execute(hosts + split_tag(tag))
241
- rescue
242
- logger.error("failed: #{q} -- #{(hosts + split_tag(tag)).inspect}")
243
- raise
247
+ execute_db(memory_db, q, (hosts + split_tag(tag)))
248
+ rescue SQLite3::RangeException => error
249
+ # FIXME: bulk insert occationally fails even if there are no errors in bind parameters
250
+ # `bind_param': bind or column index out of range (SQLite3::RangeException)
251
+ logger.warn("bulk insert failed due to #{error.message}. fallback to normal insert.")
252
+ hosts.each do |host|
253
+ q = "INSERT OR REPLACE INTO hosts_tags (host_id, tag_id) " \
254
+ "SELECT host.id, tag.id FROM " \
255
+ "( SELECT id FROM hosts WHERE name = ? ) AS host, " \
256
+ "( SELECT id FROM tags WHERE name = ? AND value = ? LIMIT 1 ) AS tag;"
257
+ execute_db(memory_db, q, [host] + split_tag(tag))
258
+ end
244
259
  end
245
260
  end
246
261
  end
@@ -257,19 +272,37 @@ module Hotdog
257
272
  end
258
273
  end
259
274
 
260
- def get_all_tags() #==> Hash<Tag,Array<Host>>
261
- code, all_tags = @dog.all_tags()
262
- logger.debug("dog.all_tags() #==> [%s, ...]" % [code.inspect])
263
- if code.to_i / 100 != 2
264
- raise("dog.all_tags() returns [%s, ...]" % [code.inspect])
275
+ def execute_db(db, q, args=[])
276
+ begin
277
+ logger.debug("execute: #{q} -- #{args.inspect}")
278
+ prepare(db, q).execute(args)
279
+ rescue
280
+ logger.error("failed: #{q} -- #{args.inspect}")
281
+ raise
265
282
  end
266
- code, all_downtimes = @dog.get_all_downtimes()
267
- logger.debug("dog.get_all_downtimes() #==> [%s, ...]" % [code.inspect])
268
- if code.to_i / 100 != 2
269
- raise("dog.get_all_downtimes() returns [%s, ...]" % [code.inspect])
283
+ end
284
+
285
+ def get_all_tags() #==> Hash<Tag,Array<Host>>
286
+ endpoint = options[:endpoint]
287
+ requests = {all_downtime: "/api/v1/downtime", all_tags: "/api/v1/tags/hosts"}
288
+ query = URI.encode_www_form(api_key: options[:api_key], application_key: options[:application_key])
289
+ begin
290
+ responses = Hash[Parallel.map(requests) { |name, request_path|
291
+ uri = URI.join(endpoint, "#{request_path}?#{query}")
292
+ begin
293
+ response = uri.open("User-Agent" => "hotdog/#{Hotdog::VERSION}") { |fp| fp.read }
294
+ [name, MultiJson.load(response)]
295
+ rescue OpenURI::HTTPError => error
296
+ code, body = error.io.status
297
+ raise(RuntimeError.new("dog.get_#{name}() returns [#{code.inspect}, ...]"))
298
+ end
299
+ }]
300
+ rescue => error
301
+ STDERR.puts(error.message)
302
+ exit(1)
270
303
  end
271
304
  now = Time.new.to_i
272
- downtimes = all_downtimes.select { |downtime|
305
+ downtimes = responses.fetch(:all_downtime, []).select { |downtime|
273
306
  # active downtimes
274
307
  downtime["active"] and ( downtime["start"].nil? or downtime["start"] < now ) and ( downtime["end"].nil? or now <= downtime["end"] )
275
308
  }.flat_map { |downtime|
@@ -279,7 +312,11 @@ module Hotdog
279
312
  if not downtimes.empty?
280
313
  logger.info("ignore host(s) with scheduled downtimes: #{downtimes.inspect}")
281
314
  end
282
- Hash[all_tags["tags"].map { |tag, hosts| [tag, hosts.reject { |host| downtimes.include?(host) }] }]
315
+ Hash[responses.fetch(:all_tags, {}).fetch("tags", []).map { |tag, hosts| [tag, hosts.reject { |host| downtimes.include?(host) }] }]
316
+ end
317
+
318
+ def dog()
319
+ @dog ||= Dogapi::Client.new(options[:api_key], options[:application_key])
283
320
  end
284
321
 
285
322
  def split_tag(tag)
@@ -296,95 +333,9 @@ module Hotdog
296
333
  end
297
334
 
298
335
  def copy_db(src, dst)
299
- # create index later for better insert performance
300
- dst.transaction do
301
- create_table_hosts(dst)
302
- create_table_tags(dst)
303
- create_table_hosts_tags(dst)
304
-
305
- hosts = prepare(src, "SELECT id, name FROM hosts").execute().to_a
306
- hosts.each_slice(SQLITE_LIMIT_COMPOUND_SELECT / 2) do |hosts|
307
- q = "INSERT INTO hosts (id, name) VALUES %s" % hosts.map { "(?, ?)" }.join(", ")
308
- begin
309
- prepare(dst, q).execute(hosts)
310
- rescue
311
- logger.error("failed: #{q} -- #{hosts.inspect}")
312
- raise
313
- end
314
- end
315
-
316
- tags = prepare(src, "SELECT id, name, value FROM tags").execute().to_a
317
- tags.each_slice(SQLITE_LIMIT_COMPOUND_SELECT / 3) do |tags|
318
- q = "INSERT INTO tags (id, name, value) VALUES %s" % tags.map { "(?, ?, ?)" }.join(", ")
319
- begin
320
- prepare(dst, q).execute(tags)
321
- rescue
322
- logger.error("failed: #{q} -- #{tags.inspect}")
323
- raise
324
- end
325
- end
326
-
327
- hosts_tags = prepare(src, "SELECT host_id, tag_id FROM hosts_tags").to_a
328
- hosts_tags.each_slice(SQLITE_LIMIT_COMPOUND_SELECT / 2) do |hosts_tags|
329
- q = "INSERT INTO hosts_tags (host_id, tag_id) VALUES %s" % hosts_tags.map { "(?, ?)" }.join(", ")
330
- begin
331
- prepare(dst, q).execute(hosts_tags)
332
- rescue
333
- logger.error("failed: #{q} -- #{hosts_tags.inspect}")
334
- raise
335
- end
336
- end
337
-
338
- create_index_hosts(dst)
339
- create_index_tags(dst)
340
- create_index_hosts_tags(dst)
341
- end
342
- end
343
-
344
- def create_table_hosts(db)
345
- q = "CREATE TABLE IF NOT EXISTS hosts ( " \
346
- "id INTEGER PRIMARY KEY AUTOINCREMENT, " \
347
- "name VARCHAR(255) NOT NULL COLLATE NOCASE " \
348
- ");"
349
- logger.debug(q)
350
- db.execute(q)
351
- end
352
-
353
- def create_index_hosts(db)
354
- q = "CREATE UNIQUE INDEX IF NOT EXISTS hosts_name ON hosts ( name );"
355
- logger.debug(q)
356
- db.execute(q)
357
- end
358
-
359
- def create_table_tags(db)
360
- q = "CREATE TABLE IF NOT EXISTS tags ( " \
361
- "id INTEGER PRIMARY KEY AUTOINCREMENT, " \
362
- "name VARCHAR(200) NOT NULL COLLATE NOCASE, " \
363
- "value VARCHAR(200) NOT NULL COLLATE NOCASE " \
364
- ");"
365
- logger.debug(q)
366
- db.execute(q)
367
- end
368
-
369
- def create_index_tags(db)
370
- q = "CREATE UNIQUE INDEX IF NOT EXISTS tags_name_value ON tags ( name, value );"
371
- logger.debug(q)
372
- db.execute(q)
373
- end
374
-
375
- def create_table_hosts_tags(db)
376
- q = "CREATE TABLE IF NOT EXISTS hosts_tags ( " \
377
- "host_id INTEGER NOT NULL, " \
378
- "tag_id INTEGER NOT NULL " \
379
- ");"
380
- logger.debug(q)
381
- db.execute(q)
382
- end
383
-
384
- def create_index_hosts_tags(db)
385
- q = "CREATE UNIQUE INDEX IF NOT EXISTS hosts_tags_host_id_tag_id ON hosts_tags ( host_id, tag_id );"
386
- logger.debug(q)
387
- db.execute(q)
336
+ backup = SQLite3::Backup.new(dst, "main", src, "main")
337
+ backup.step(-1)
338
+ backup.finish
388
339
  end
389
340
  end
390
341
  end
@@ -1,3 +1,3 @@
1
1
  module Hotdog
2
- VERSION = "0.5.4"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -23,9 +23,9 @@ describe "application" do
23
23
  end
24
24
 
25
25
  it "returns proper class by name" do
26
- expect(app.__send__(:get_command, "hosts")).to be(Hotdog::Commands::Hosts)
27
- expect(app.__send__(:get_command, "search")).to be(Hotdog::Commands::Search)
28
- expect(app.__send__(:get_command, "tags")).to be(Hotdog::Commands::Tags)
26
+ expect(app.__send__(:get_command, "hosts")).to be_a(Hotdog::Commands::Hosts)
27
+ expect(app.__send__(:get_command, "search")).to be_a(Hotdog::Commands::Search)
28
+ expect(app.__send__(:get_command, "tags")).to be_a(Hotdog::Commands::Tags)
29
29
  end
30
30
 
31
31
  it "raises error if the action is base-command" do
@@ -0,0 +1,49 @@
1
+ require "spec_helper"
2
+ require "hotdog/application"
3
+ require "hotdog/commands/down"
4
+
5
+ describe "option parser for down" do
6
+ let(:app) {
7
+ Hotdog::Application.new
8
+ }
9
+
10
+ let(:cmd) {
11
+ Hotdog::Commands::Down.new(app)
12
+ }
13
+
14
+ before(:each) do
15
+ allow(app).to receive(:get_command).with("down") {
16
+ cmd
17
+ }
18
+ end
19
+
20
+ it "cannot handle subcommand options before subcommand" do
21
+ expect {
22
+ app.main(["--downtime", "86400", "down", "foo", "bar", "baz"])
23
+ }.to raise_error(OptionParser::InvalidOption)
24
+ end
25
+
26
+ it "can handle subcommand options after subcommand" do
27
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
28
+ downtime: 12345,
29
+ verbose: false,
30
+ ))
31
+ app.main(["down", "--downtime", "12345", "foo", "bar", "baz"])
32
+ end
33
+
34
+ it "can handle common options before subcommand" do
35
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
36
+ downtime: 12345,
37
+ verbose: true,
38
+ ))
39
+ app.main(["--verbose", "down", "--downtime", "12345", "foo", "bar", "baz"])
40
+ end
41
+
42
+ it "can handle common options after subcommand" do
43
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
44
+ downtime: 12345,
45
+ verbose: true,
46
+ ))
47
+ app.main(["down", "--downtime", "12345", "--verbose", "foo", "bar", "baz"])
48
+ end
49
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+ require "hotdog/application"
3
+ require "hotdog/commands/hosts"
4
+
5
+ describe "option parser for hosts" do
6
+ let(:app) {
7
+ Hotdog::Application.new
8
+ }
9
+
10
+ let(:cmd) {
11
+ Hotdog::Commands::Hosts.new(app)
12
+ }
13
+
14
+ before(:each) do
15
+ allow(app).to receive(:get_command).with("hosts") {
16
+ cmd
17
+ }
18
+ end
19
+
20
+ it "can handle common options before subcommand" do
21
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
22
+ verbose: true,
23
+ ))
24
+ app.main(["--verbose", "hosts", "foo", "bar", "baz"])
25
+ end
26
+
27
+ it "can handle common options after subcommand" do
28
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
29
+ verbose: true,
30
+ ))
31
+ app.main(["hosts", "--verbose", "foo", "bar", "baz"])
32
+ end
33
+ end
@@ -0,0 +1,76 @@
1
+ require "spec_helper"
2
+ require "hotdog/application"
3
+ require "hotdog/commands/pssh"
4
+
5
+ describe "option parser for pssh" do
6
+ let(:app) {
7
+ Hotdog::Application.new
8
+ }
9
+
10
+ let(:cmd) {
11
+ Hotdog::Commands::Pssh.new(app)
12
+ }
13
+
14
+ before(:each) do
15
+ allow(app).to receive(:get_command).with("pssh") {
16
+ cmd
17
+ }
18
+ end
19
+
20
+ it "cannot handle subcommand options before subcommand" do
21
+ expect {
22
+ app.main(["-P", "42", "pssh", "foo", "bar", "baz"])
23
+ }.to raise_error(OptionParser::InvalidOption)
24
+ end
25
+
26
+ it "can handle subcommand options after subcommand" do
27
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
28
+ max_parallelism: 42,
29
+ verbose: false,
30
+ ))
31
+ app.main(["pssh", "-P", "42", "foo", "bar", "baz"])
32
+ end
33
+
34
+ it "can handle common options before subcommand" do
35
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
36
+ max_parallelism: 42,
37
+ verbose: true,
38
+ ))
39
+ app.main(["--verbose", "pssh", "-P", "42", "foo", "bar", "baz"])
40
+ end
41
+
42
+ it "can handle common options after subcommand" do
43
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
44
+ max_parallelism: 42,
45
+ verbose: true,
46
+ ))
47
+ app.main(["pssh", "-P", "42", "--verbose", "foo", "bar", "baz"])
48
+ end
49
+
50
+ it "can handle subcommand options with remote command, 1" do
51
+ allow(cmd).to receive(:run).with([], a_hash_including(
52
+ max_parallelism: 42,
53
+ verbose: true,
54
+ ))
55
+ app.main(["pssh", "-P", "42", "--verbose", "--", "foo", "bar", "baz"])
56
+ expect(cmd.remote_command).to eq("foo bar baz")
57
+ end
58
+
59
+ it "can handle subcommand options with remote command, 2" do
60
+ allow(cmd).to receive(:run).with(["foo"], a_hash_including(
61
+ max_parallelism: 42,
62
+ verbose: true,
63
+ ))
64
+ app.main(["pssh", "-P", "42", "--verbose", "foo", "--", "bar", "baz"])
65
+ expect(cmd.remote_command).to eq("bar baz")
66
+ end
67
+
68
+ it "can handle subcommand options with remote command, 3" do
69
+ allow(cmd).to receive(:run).with(["foo"], a_hash_including(
70
+ max_parallelism: 42,
71
+ verbose: true,
72
+ ))
73
+ app.main(["pssh", "-P", "42", "--verbose", "foo", "--", "bar", "--", "baz"])
74
+ expect(cmd.remote_command).to eq("bar -- baz")
75
+ end
76
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+ require "hotdog/application"
3
+ require "hotdog/commands/search"
4
+
5
+ describe "option parser for search" do
6
+ let(:app) {
7
+ Hotdog::Application.new
8
+ }
9
+
10
+ let(:cmd) {
11
+ Hotdog::Commands::Search.new(app)
12
+ }
13
+
14
+ before(:each) do
15
+ allow(app).to receive(:get_command).with("search") {
16
+ cmd
17
+ }
18
+ end
19
+
20
+ it "can handle common options before subcommand" do
21
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
22
+ verbose: true,
23
+ ))
24
+ app.main(["--verbose", "search", "foo", "bar", "baz"])
25
+ end
26
+
27
+ it "can handle common options after subcommand" do
28
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
29
+ verbose: true,
30
+ ))
31
+ app.main(["search", "--verbose", "foo", "bar", "baz"])
32
+ end
33
+ end
@@ -0,0 +1,76 @@
1
+ require "spec_helper"
2
+ require "hotdog/application"
3
+ require "hotdog/commands/ssh"
4
+
5
+ describe "option parser for ssh" do
6
+ let(:app) {
7
+ Hotdog::Application.new
8
+ }
9
+
10
+ let(:cmd) {
11
+ Hotdog::Commands::Ssh.new(app)
12
+ }
13
+
14
+ before(:each) do
15
+ allow(app).to receive(:get_command).with("ssh") {
16
+ cmd
17
+ }
18
+ end
19
+
20
+ it "cannot handle subcommand options before subcommand" do
21
+ expect {
22
+ app.main(["--index", "42", "ssh", "foo", "bar", "baz"])
23
+ }.to raise_error(OptionParser::InvalidOption)
24
+ end
25
+
26
+ it "can handle subcommand options after subcommand" do
27
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
28
+ index: 42,
29
+ verbose: false,
30
+ ))
31
+ app.main(["ssh", "--index", "42", "foo", "bar", "baz"])
32
+ end
33
+
34
+ it "can handle common options before subcommand" do
35
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
36
+ index: 42,
37
+ verbose: true,
38
+ ))
39
+ app.main(["--verbose", "ssh", "--index", "42", "foo", "bar", "baz"])
40
+ end
41
+
42
+ it "can handle common options after subcommand" do
43
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
44
+ index: 42,
45
+ verbose: true,
46
+ ))
47
+ app.main(["ssh", "--index", "42", "--verbose", "foo", "bar", "baz"])
48
+ end
49
+
50
+ it "can handle subcommand options with remote command, 1" do
51
+ allow(cmd).to receive(:run).with([], a_hash_including(
52
+ index: 42,
53
+ verbose: true,
54
+ ))
55
+ app.main(["ssh", "--index", "42", "--verbose", "--", "foo", "bar", "baz"])
56
+ expect(cmd.remote_command).to eq("foo bar baz")
57
+ end
58
+
59
+ it "can handle subcommand options with remote command, 2" do
60
+ allow(cmd).to receive(:run).with(["foo"], a_hash_including(
61
+ index: 42,
62
+ verbose: true,
63
+ ))
64
+ app.main(["ssh", "--index", "42", "--verbose", "foo", "--", "bar", "baz"])
65
+ expect(cmd.remote_command).to eq("bar baz")
66
+ end
67
+
68
+ it "can handle subcommand options with remote command, 3" do
69
+ allow(cmd).to receive(:run).with(["foo"], a_hash_including(
70
+ index: 42,
71
+ verbose: true,
72
+ ))
73
+ app.main(["ssh", "--index", "42", "--verbose", "foo", "--", "bar", "--", "baz"])
74
+ expect(cmd.remote_command).to eq("bar -- baz")
75
+ end
76
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+ require "hotdog/application"
3
+ require "hotdog/commands/tags"
4
+
5
+ describe "option parser for tags" do
6
+ let(:app) {
7
+ Hotdog::Application.new
8
+ }
9
+
10
+ let(:cmd) {
11
+ Hotdog::Commands::Tags.new(app)
12
+ }
13
+
14
+ before(:each) do
15
+ allow(app).to receive(:get_command).with("tags") {
16
+ cmd
17
+ }
18
+ end
19
+
20
+ it "can handle common options before subcommand" do
21
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
22
+ verbose: true,
23
+ ))
24
+ app.main(["--verbose", "tags", "foo", "bar", "baz"])
25
+ end
26
+
27
+ it "can handle common options after subcommand" do
28
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
29
+ verbose: true,
30
+ ))
31
+ app.main(["tags", "--verbose", "foo", "bar", "baz"])
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+ require "hotdog/application"
3
+ require "hotdog/commands/up"
4
+
5
+ describe "option parser for up" do
6
+ let(:app) {
7
+ Hotdog::Application.new
8
+ }
9
+
10
+ let(:cmd) {
11
+ Hotdog::Commands::Up.new(app)
12
+ }
13
+
14
+ before(:each) do
15
+ allow(app).to receive(:get_command).with("up") {
16
+ cmd
17
+ }
18
+ end
19
+
20
+ it "can handle common options before subcommand" do
21
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
22
+ verbose: true,
23
+ ))
24
+ app.main(["--verbose", "up", "foo", "bar", "baz"])
25
+ end
26
+
27
+ it "can handle common options after subcommand" do
28
+ allow(cmd).to receive(:run).with(["foo", "bar", "baz"], a_hash_including(
29
+ verbose: true,
30
+ ))
31
+ app.main(["up", "--verbose", "foo", "bar", "baz"])
32
+ end
33
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotdog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yamashita Yuu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-02 00:00:00.000000000 Z
11
+ date: 2015-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,47 +67,75 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.13.0
69
69
  - !ruby/object:Gem::Dependency
70
- name: parslet
70
+ name: multi_json
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.6.2
75
+ version: 1.11.2
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.6.2
82
+ version: 1.11.2
83
83
  - !ruby/object:Gem::Dependency
84
- name: sqlite3
84
+ name: oj
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 1.3.10
89
+ version: 2.12.14
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 1.3.10
96
+ version: 2.12.14
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: parallel
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.4.1
103
+ version: 1.6.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.6.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: parslet
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.6.2
104
118
  type: :runtime
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: 1.4.1
124
+ version: 1.6.2
125
+ - !ruby/object:Gem::Dependency
126
+ name: sqlite3
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 1.3.10
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 1.3.10
111
139
  description: Yet another command-line tool for Datadog
112
140
  email:
113
141
  - peek824545201@gmail.com
@@ -153,6 +181,13 @@ files:
153
181
  - spec/formatter/text_spec.rb
154
182
  - spec/formatter/tsv_spec.rb
155
183
  - spec/formatter/yaml_spec.rb
184
+ - spec/optparse/down_spec.rb
185
+ - spec/optparse/hosts_spec.rb
186
+ - spec/optparse/pssh_spec.rb
187
+ - spec/optparse/search_spec.rb
188
+ - spec/optparse/ssh_spec.rb
189
+ - spec/optparse/tags_spec.rb
190
+ - spec/optparse/up_spec.rb
156
191
  - spec/parser/glob_expression_spec.rb
157
192
  - spec/parser/parser_spec.rb
158
193
  - spec/parser/regexp_expression_spec.rb
@@ -192,6 +227,13 @@ test_files:
192
227
  - spec/formatter/text_spec.rb
193
228
  - spec/formatter/tsv_spec.rb
194
229
  - spec/formatter/yaml_spec.rb
230
+ - spec/optparse/down_spec.rb
231
+ - spec/optparse/hosts_spec.rb
232
+ - spec/optparse/pssh_spec.rb
233
+ - spec/optparse/search_spec.rb
234
+ - spec/optparse/ssh_spec.rb
235
+ - spec/optparse/tags_spec.rb
236
+ - spec/optparse/up_spec.rb
195
237
  - spec/parser/glob_expression_spec.rb
196
238
  - spec/parser/parser_spec.rb
197
239
  - spec/parser/regexp_expression_spec.rb