hotdog 0.30.0 → 0.31.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: 704ccd17864c284a1daa3550e9c955469e718ee4
4
- data.tar.gz: 0d5e59e8c274f25ebd179e92123380c5336d7cec
3
+ metadata.gz: 9919088eda80ed6ec42ab4448a1e9474a8f6b3cf
4
+ data.tar.gz: b4659b72b4ee22337f1d74d14dad1d0d686b8bf0
5
5
  SHA512:
6
- metadata.gz: 03d9ceb9147a75449c9b7542f3deecdb331cd0736d902603101508fbd1ef87881c82503b223dcd2c710f5f69c8408b173b95b1a17c57bbb08b5ca27857bfcc14
7
- data.tar.gz: 5d32974bbbb07110a678538b5275ca792a1d76eb5ae086ad1b9831ff434d1937d4eae8f0ae4048df393bec2f81664223da444ba9aeee3467224b78bf4e0d375d
6
+ metadata.gz: 6cdebee0eaf5a3c347aa9fb8fae6f589467cf040edcad75d1d220d2b29a7842a7619f1b1149fe58bb1b116e6fc59ae248b48af5291655e03da4866ade02d1005
7
+ data.tar.gz: 9af471697553ce75493da82aedfa9f79c59f65de5a74407b7fbf626bc04571dcfb5e29be495021eecea48fd3814cecabf6abd87cb9f8abe3a36550a934f01868
@@ -51,7 +51,8 @@ module Hotdog
51
51
  force: false,
52
52
  format: "text",
53
53
  headers: false,
54
- status: STATUS_RUNNING,
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(self.status, "unknown")
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 /\Apending\z/i
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 /\Arunning\z/i
249
+ when /\A(?:running)\z/i
223
250
  options[:status] = STATUS_RUNNING
224
- when /\Ashutting-down\z/i
251
+ when /\A(?:shutting-down)\z/i
225
252
  options[:status] = STATUS_SHUTTING_DOWN
226
- when /\Aterminated\z/i
253
+ when /\A(?:terminated)\z/i
227
254
  options[:status] = STATUS_TERMINATED
228
- when /\Astopping\z/i
255
+ when /\A(?:stopping)\z/i
229
256
  options[:status] = STATUS_STOPPING
230
- when /\Astopped\z/i
257
+ when /\A(?:stopped)\z/i
231
258
  options[:status] = STATUS_STOPPED
232
259
  else
233
- options[:status] = v.to_i
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|
@@ -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
- q = "UPDATE hosts SET status = ? WHERE name IN (%s);" % hosts.map { "?" }.join(", ")
64
- execute_db(@db, q, [STATUS_STOPPING] + hosts)
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
@@ -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
@@ -61,11 +61,7 @@ module Hotdog
61
61
 
62
62
  private
63
63
  def default_option(options, key, default_value)
64
- if options.key?(key)
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 / 2) do |hosts|
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
- q = "INSERT OR REPLACE INTO hosts_tags (host_id, tag_id) " \
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 ( SELECT * FROM tags WHERE name = 'host' ) AS tags " \
377
- "ON hosts.name = tags.value;"
378
- execute_db(db, q)
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
- q = "SELECT id FROM hosts " \
63
- "WHERE ? <= id AND id < ? AND id NOT IN (%s);"
64
- environment.execute(q % selected.map { "?" }.join(", "), [range.first, range.last] + selected).map { |row| row.first }
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
- q = "SELECT id FROM hosts " \
205
- "WHERE ? <= id AND id < ? AND ( id IN (%s) AND id IN (%s) );"
206
- environment.execute(q % [left_selected.map { "?" }.join(", "), right_selected.map { "?" }.join(", ")], [range.first, range.last] + left_selected + right_selected).map { |row| row.first }
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
- ( regexp.as(:tagname_regexp) >> separator.as(:separator) >> regexp.as(:tagvalue_regexp) \
110
- | regexp.as(:tagname_regexp) >> separator.as(:separator) \
111
- | regexp.as(:tagname_regexp) \
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) \
@@ -1,3 +1,3 @@
1
1
  module Hotdog
2
- VERSION = "0.30.0"
2
+ VERSION = "0.31.0"
3
3
  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.30.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-15 00:00:00.000000000 Z
11
+ date: 2017-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler