hotdog 0.30.0 → 0.31.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hotdog/application.rb +37 -10
- data/lib/hotdog/commands/down.rb +3 -2
- data/lib/hotdog/commands/search.rb +8 -0
- data/lib/hotdog/commands/ssh.rb +2 -0
- data/lib/hotdog/commands.rb +56 -21
- data/lib/hotdog/expression/semantics.rb +14 -6
- data/lib/hotdog/expression/syntax.rb +7 -3
- data/lib/hotdog/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9919088eda80ed6ec42ab4448a1e9474a8f6b3cf
|
4
|
+
data.tar.gz: b4659b72b4ee22337f1d74d14dad1d0d686b8bf0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cdebee0eaf5a3c347aa9fb8fae6f589467cf040edcad75d1d220d2b29a7842a7619f1b1149fe58bb1b116e6fc59ae248b48af5291655e03da4866ade02d1005
|
7
|
+
data.tar.gz: 9af471697553ce75493da82aedfa9f79c59f65de5a74407b7fbf626bc04571dcfb5e29be495021eecea48fd3814cecabf6abd87cb9f8abe3a36550a934f01868
|
data/lib/hotdog/application.rb
CHANGED
@@ -51,7 +51,8 @@ module Hotdog
|
|
51
51
|
force: false,
|
52
52
|
format: "text",
|
53
53
|
headers: false,
|
54
|
-
|
54
|
+
source: nil,
|
55
|
+
status: nil,
|
55
56
|
listing: false,
|
56
57
|
logger: @logger,
|
57
58
|
max_time: 5,
|
@@ -159,11 +160,21 @@ module Hotdog
|
|
159
160
|
end
|
160
161
|
end
|
161
162
|
|
163
|
+
def source()
|
164
|
+
options.fetch(:source, SOURCE_DATADOG)
|
165
|
+
end
|
166
|
+
|
167
|
+
def source_name(source=self.source)
|
168
|
+
{
|
169
|
+
SOURCE_DATADOG => "datadog",
|
170
|
+
}.fetch(source, "unknown")
|
171
|
+
end
|
172
|
+
|
162
173
|
def status()
|
163
174
|
options.fetch(:status, STATUS_RUNNING)
|
164
175
|
end
|
165
176
|
|
166
|
-
def status_name()
|
177
|
+
def status_name(status=self.status)
|
167
178
|
{
|
168
179
|
STATUS_PENDING => "pending",
|
169
180
|
STATUS_RUNNING => "running",
|
@@ -171,7 +182,7 @@ module Hotdog
|
|
171
182
|
STATUS_TERMINATED => "terminated",
|
172
183
|
STATUS_STOPPING => "stopping",
|
173
184
|
STATUS_STOPPED => "stopped",
|
174
|
-
}.fetch(
|
185
|
+
}.fetch(status, "unknown")
|
175
186
|
end
|
176
187
|
|
177
188
|
private
|
@@ -215,22 +226,38 @@ module Hotdog
|
|
215
226
|
@optparse.on("-h", "--[no-]headers", "Display headeres for each columns") do |v|
|
216
227
|
options[:headers] = v
|
217
228
|
end
|
229
|
+
@optparse.on("--source=SOURCE", "Specify custom host source") do |v|
|
230
|
+
case v
|
231
|
+
when /\A\d\z/i
|
232
|
+
options[:source] = v.to_i
|
233
|
+
when /\A(?:all|any)\z/i
|
234
|
+
options[:source] = nil
|
235
|
+
when /\A(?:datadog)\z/i
|
236
|
+
options[:source] = SOURCE_DATADOG
|
237
|
+
else
|
238
|
+
raise(OptionParser::InvalidArgument.new("unknown source: #{v}"))
|
239
|
+
end
|
240
|
+
end
|
218
241
|
@optparse.on("--status=STATUS", "Specify custom host status") do |v|
|
219
242
|
case v
|
220
|
-
when /\
|
243
|
+
when /\A\d\z/i
|
244
|
+
options[:status] = v.to_i
|
245
|
+
when /\A(?:all|any)\z/i
|
246
|
+
options[:status] = nil
|
247
|
+
when /\A(?:pending)\z/i
|
221
248
|
options[:status] = STATUS_PENDING
|
222
|
-
when /\
|
249
|
+
when /\A(?:running)\z/i
|
223
250
|
options[:status] = STATUS_RUNNING
|
224
|
-
when /\
|
251
|
+
when /\A(?:shutting-down)\z/i
|
225
252
|
options[:status] = STATUS_SHUTTING_DOWN
|
226
|
-
when /\
|
253
|
+
when /\A(?:terminated)\z/i
|
227
254
|
options[:status] = STATUS_TERMINATED
|
228
|
-
when /\
|
255
|
+
when /\A(?:stopping)\z/i
|
229
256
|
options[:status] = STATUS_STOPPING
|
230
|
-
when /\
|
257
|
+
when /\A(?:stopped)\z/i
|
231
258
|
options[:status] = STATUS_STOPPED
|
232
259
|
else
|
233
|
-
|
260
|
+
raise(OptionParser::InvalidArgument.new("unknown status: #{v}"))
|
234
261
|
end
|
235
262
|
end
|
236
263
|
@optparse.on("-l", "--[no-]listing", "Use listing format") do |v|
|
data/lib/hotdog/commands/down.rb
CHANGED
@@ -60,9 +60,10 @@ module Hotdog
|
|
60
60
|
@db.transaction do
|
61
61
|
sqlite_limit_compound_select = options[:sqlite_limit_compound_select] || SQLITE_LIMIT_COMPOUND_SELECT
|
62
62
|
hosts.each_slice(sqlite_limit_compound_select - 1) do |hosts|
|
63
|
-
|
64
|
-
execute_db(@db,
|
63
|
+
execute_db(@db, "DELETE FROM hosts_tags WHERE tag_id IN ( SELECT id FROM tags WHERE name = '@status' ) AND host_id IN ( SELECT id FROM hosts WHERE name IN (%s) );" % hosts.map { "?" }.join(", "), hosts)
|
64
|
+
execute_db(@db, "UPDATE hosts SET status = ? WHERE name IN (%s);" % hosts.map { "?" }.join(", "), [STATUS_STOPPING] + hosts)
|
65
65
|
end
|
66
|
+
associate_tag_hosts(@db, "@status:#{application.status_name(STATUS_STOPPING)}", hosts)
|
66
67
|
end
|
67
68
|
end
|
68
69
|
end
|
@@ -120,6 +120,14 @@ module Hotdog
|
|
120
120
|
# return everything if given expression is empty
|
121
121
|
expression = "*"
|
122
122
|
end
|
123
|
+
if options[:source]
|
124
|
+
source_name = application.source_name(options[:source])
|
125
|
+
expression = "@source:#{source_name} AND (#{expression})"
|
126
|
+
end
|
127
|
+
if options[:status]
|
128
|
+
status_name = application.status_name(options[:status])
|
129
|
+
expression = "@status:#{status_name} AND (#{expression})"
|
130
|
+
end
|
123
131
|
if options[:limit]
|
124
132
|
expression = "LIMIT((#{expression}), #{options[:limit]})"
|
125
133
|
end
|
data/lib/hotdog/commands/ssh.rb
CHANGED
@@ -15,6 +15,8 @@ module Hotdog
|
|
15
15
|
default_option(options, :max_parallelism, Parallel.processor_count * 2)
|
16
16
|
default_option(options, :shuffle, false)
|
17
17
|
default_option(options, :ssh_config, nil)
|
18
|
+
# we must not need to run ssh against terminated hosts
|
19
|
+
default_option(options, :status, STATUS_RUNNING)
|
18
20
|
optparse.on("-C", "Enable compression.") do |v|
|
19
21
|
options[:ssh_options]["Compression"] = "yes"
|
20
22
|
end
|
data/lib/hotdog/commands.rb
CHANGED
@@ -61,11 +61,7 @@ module Hotdog
|
|
61
61
|
|
62
62
|
private
|
63
63
|
def default_option(options, key, default_value)
|
64
|
-
|
65
|
-
options[key]
|
66
|
-
else
|
67
|
-
options[key] = default_value
|
68
|
-
end
|
64
|
+
options[key] = default_value
|
69
65
|
end
|
70
66
|
|
71
67
|
def prepare(db, query)
|
@@ -81,15 +77,6 @@ module Hotdog
|
|
81
77
|
end
|
82
78
|
|
83
79
|
def get_hosts(host_ids, tags=nil)
|
84
|
-
status = application.status
|
85
|
-
n = Array(host_ids).length
|
86
|
-
host_ids = Array(host_ids).each_slice(SQLITE_LIMIT_COMPOUND_SELECT).flat_map { |host_ids|
|
87
|
-
execute("SELECT id FROM hosts WHERE status = ? AND id IN (%s);" % host_ids.map { "?" }.join(", "), [status] + host_ids).map { |row| row[0] }
|
88
|
-
}
|
89
|
-
m = host_ids.length
|
90
|
-
if n != m
|
91
|
-
logger.warn("filtered out #{n - m} host(s) out of #{n} due to status != #{application.status_name}.")
|
92
|
-
end
|
93
80
|
tags ||= @options[:tags]
|
94
81
|
update_db
|
95
82
|
if host_ids.empty?
|
@@ -263,6 +250,7 @@ module Hotdog
|
|
263
250
|
db = SQLite3::Database.new(persistent_db_path)
|
264
251
|
copy_db(memory_db, db)
|
265
252
|
close_db(memory_db)
|
253
|
+
$did_reload = true
|
266
254
|
@db = db
|
267
255
|
end
|
268
256
|
end
|
@@ -295,6 +283,25 @@ module Hotdog
|
|
295
283
|
execute_db(db, "CREATE TABLE IF NOT EXISTS hosts_tags (host_id INTEGER NOT NULL, tag_id INTEGER NOT NULL);")
|
296
284
|
execute_db(db, "CREATE UNIQUE INDEX IF NOT EXISTS hosts_tags_host_id_tag_id ON hosts_tags (host_id, tag_id);")
|
297
285
|
|
286
|
+
execute_db(db, "CREATE TABLE IF NOT EXISTS source_names (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(200) NOT NULL COLLATE NOCASE);")
|
287
|
+
{
|
288
|
+
SOURCE_DATADOG => application.source_name(SOURCE_DATADOG),
|
289
|
+
}.each do |source_id, source_name|
|
290
|
+
execute_db(db, "INSERT OR IGNORE INTO source_names (id, name) VALUES (?, ?);", [source_id, source_name])
|
291
|
+
end
|
292
|
+
|
293
|
+
execute_db(db, "CREATE TABLE IF NOT EXISTS status_names (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(200) NOT NULL COLLATE NOCASE);")
|
294
|
+
{
|
295
|
+
STATUS_PENDING => application.status_name(STATUS_PENDING),
|
296
|
+
STATUS_RUNNING => application.status_name(STATUS_RUNNING),
|
297
|
+
STATUS_SHUTTING_DOWN => application.status_name(STATUS_SHUTTING_DOWN),
|
298
|
+
STATUS_TERMINATED => application.status_name(STATUS_TERMINATED),
|
299
|
+
STATUS_STOPPING => application.status_name(STATUS_STOPPING),
|
300
|
+
STATUS_STOPPED => application.status_name(STATUS_STOPPED),
|
301
|
+
}.each do |status_id, status_name|
|
302
|
+
execute_db(db, "INSERT OR IGNORE INTO status_names (id, name) VALUES (?, ?);", [status_id, status_name])
|
303
|
+
end
|
304
|
+
|
298
305
|
known_tags = all_tags.keys.map { |tag| split_tag(tag) }.uniq
|
299
306
|
create_tags(db, known_tags)
|
300
307
|
|
@@ -362,20 +369,48 @@ module Hotdog
|
|
362
369
|
end
|
363
370
|
|
364
371
|
def create_hosts(db, hosts, downtimes)
|
365
|
-
hosts.each_slice(SQLITE_LIMIT_COMPOUND_SELECT /
|
366
|
-
q = "INSERT OR IGNORE INTO hosts (name, status) VALUES %s;" % hosts.map { "(?, ?)" }.join(", ")
|
372
|
+
hosts.each_slice(SQLITE_LIMIT_COMPOUND_SELECT / 3) do |hosts|
|
373
|
+
q = "INSERT OR IGNORE INTO hosts (name, source, status) VALUES %s;" % hosts.map { "(?, ?, ?)" }.join(", ")
|
367
374
|
execute_db(db, q, hosts.map { |host|
|
375
|
+
source = SOURCE_DATADOG
|
368
376
|
status = downtimes.include?(host) ? STATUS_STOPPED : STATUS_RUNNING
|
369
|
-
[host, status]
|
377
|
+
[host, source, status]
|
370
378
|
})
|
371
379
|
end
|
380
|
+
|
372
381
|
# create virtual `host` tag
|
373
382
|
execute_db(db, "INSERT OR IGNORE INTO tags (name, value) SELECT 'host', hosts.name FROM hosts;")
|
374
|
-
|
383
|
+
execute_db(db,
|
384
|
+
"INSERT OR REPLACE INTO hosts_tags (host_id, tag_id) " \
|
385
|
+
"SELECT hosts.id, tags.id FROM hosts " \
|
386
|
+
"INNER JOIN tags ON tags.name = 'host' AND hosts.name = tags.value;"
|
387
|
+
)
|
388
|
+
|
389
|
+
# create virtual `@host` tag
|
390
|
+
execute_db(db, "INSERT OR IGNORE INTO tags (name, value) SELECT '@host', hosts.name FROM hosts;")
|
391
|
+
execute_db(db,
|
392
|
+
"INSERT OR REPLACE INTO hosts_tags (host_id, tag_id) " \
|
393
|
+
"SELECT hosts.id, tags.id FROM hosts " \
|
394
|
+
"INNER JOIN tags ON tags.name = '@host' AND hosts.name = tags.value;"
|
395
|
+
)
|
396
|
+
|
397
|
+
# create virtual `@source` tag
|
398
|
+
execute_db(db, "INSERT OR IGNORE INTO tags (name, value) SELECT '@source', name FROM source_names;")
|
399
|
+
execute_db(db,
|
400
|
+
"INSERT OR REPLACE INTO hosts_tags (host_id, tag_id) " \
|
401
|
+
"SELECT hosts.id, tags.id FROM hosts " \
|
402
|
+
"INNER JOIN source_names ON hosts.source = source_names.id " \
|
403
|
+
"INNER JOIN tags ON tags.name = '@source' AND source_names.name = tags.value;"
|
404
|
+
)
|
405
|
+
|
406
|
+
# create virtual `@status` tag
|
407
|
+
execute_db(db, "INSERT OR IGNORE INTO tags (name, value) SELECT '@status', name FROM status_names;")
|
408
|
+
execute_db(db,
|
409
|
+
"INSERT OR REPLACE INTO hosts_tags (host_id, tag_id) " \
|
375
410
|
"SELECT hosts.id, tags.id FROM hosts " \
|
376
|
-
"INNER JOIN
|
377
|
-
|
378
|
-
|
411
|
+
"INNER JOIN status_names ON hosts.status = status_names.id " \
|
412
|
+
"INNER JOIN tags ON tags.name = '@status' AND status_names.name = tags.value;"
|
413
|
+
)
|
379
414
|
end
|
380
415
|
|
381
416
|
def create_tags(db, tags)
|
@@ -59,9 +59,13 @@ module Hotdog
|
|
59
59
|
(min / (sqlite_limit_compound_select - 2)).upto(max / (sqlite_limit_compound_select - 2)).flat_map { |i|
|
60
60
|
range = ((sqlite_limit_compound_select - 2) * i)...((sqlite_limit_compound_select - 2) * (i + 1))
|
61
61
|
selected = values.select { |n| range === n }
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
if 0 < selected.length
|
63
|
+
q = "SELECT id FROM hosts " \
|
64
|
+
"WHERE ? <= id AND id < ? AND id NOT IN (%s);"
|
65
|
+
environment.execute(q % selected.map { "?" }.join(", "), [range.first, range.last] + selected).map { |row| row.first }
|
66
|
+
else
|
67
|
+
[]
|
68
|
+
end
|
65
69
|
}.tap do |values|
|
66
70
|
environment.logger.debug("NOT expr: #{values.length} value(s)")
|
67
71
|
end
|
@@ -201,9 +205,13 @@ module Hotdog
|
|
201
205
|
range = (((sqlite_limit_compound_select - 2) / 2) * i)...(((sqlite_limit_compound_select - 2) / 2) * (i + 1))
|
202
206
|
left_selected = left_values.select { |n| range === n }
|
203
207
|
right_selected = right_values.select { |n| range === n }
|
204
|
-
|
205
|
-
|
206
|
-
|
208
|
+
if 0 < left_selected.length and 0 < right_selected.length
|
209
|
+
q = "SELECT id FROM hosts " \
|
210
|
+
"WHERE ? <= id AND id < ? AND ( id IN (%s) AND id IN (%s) );"
|
211
|
+
environment.execute(q % [left_selected.map { "?" }.join(", "), right_selected.map { "?" }.join(", ")], [range.first, range.last] + left_selected + right_selected).map { |row| row.first }
|
212
|
+
else
|
213
|
+
[]
|
214
|
+
end
|
207
215
|
}.tap do |values|
|
208
216
|
environment.logger.debug("lhs(#{left_values.length}) AND rhs(#{right_values.length}) => #{values.length}")
|
209
217
|
end
|
@@ -106,9 +106,9 @@ module Hotdog
|
|
106
106
|
)
|
107
107
|
}
|
108
108
|
rule(:tag) {
|
109
|
-
(
|
110
|
-
|
|
111
|
-
|
|
109
|
+
( tagname_regexp.as(:tagname_regexp) >> separator.as(:separator) >> tagvalue_regexp.as(:tagvalue_regexp) \
|
110
|
+
| tagname_regexp.as(:tagname_regexp) >> separator.as(:separator) \
|
111
|
+
| tagname_regexp.as(:tagname_regexp) \
|
112
112
|
| tagname_glob.as(:tagname_glob) >> separator.as(:separator) >> tagvalue_glob.as(:tagvalue_glob) \
|
113
113
|
| tagname_glob.as(:tagname_glob) >> separator.as(:separator) >> tagvalue.as(:tagvalue) \
|
114
114
|
| tagname_glob.as(:tagname_glob) >> separator.as(:separator) \
|
@@ -117,6 +117,10 @@ module Hotdog
|
|
117
117
|
| tagname.as(:tagname) >> separator.as(:separator) >> tagvalue.as(:tagvalue) \
|
118
118
|
| tagname.as(:tagname) >> separator.as(:separator) \
|
119
119
|
| tagname.as(:tagname) \
|
120
|
+
| (str('@') >> tagname).as(:tagname) >> separator.as(:separator) >> tagvalue_glob.as(:tagvalue_glob) \
|
121
|
+
| (str('@') >> tagname).as(:tagname) >> separator.as(:separator) >> tagvalue.as(:tagvalue) \
|
122
|
+
| (str('@') >> tagname).as(:tagname) >> separator.as(:separator) \
|
123
|
+
| (str('@') >> tagname).as(:tagname) \
|
120
124
|
| separator.as(:separator) >> regexp.as(:tagvalue_regexp) \
|
121
125
|
| separator.as(:separator) >> tagvalue_glob.as(:tagvalue_glob) \
|
122
126
|
| separator.as(:separator) >> tagvalue.as(:tagvalue) \
|
data/lib/hotdog/version.rb
CHANGED
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.
|
4
|
+
version: 0.31.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: 2017-11-
|
11
|
+
date: 2017-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|