hotdog 0.0.2 → 0.0.3

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: c0f33496f07a7069e8a6fab90cf456a98f80e986
4
- data.tar.gz: d7bfd8130aa345ff212cabb30f06ddb83b286a46
3
+ metadata.gz: 9ec9c646216c6e398de74ef323b24368fb50ebb9
4
+ data.tar.gz: afbfbb8ae6fde51f3eb651385263c9294c22c864
5
5
  SHA512:
6
- metadata.gz: 5c3aa62c94710e8bd3e1c738489782cfce401a3942d46be03128c4fc427719bba81f74d4cdf108c3cb9c3382ad83bdc2ba4085ca4f554ec2496fcdcb2b6a3b39
7
- data.tar.gz: 19fce13c8757dd1fb0437abd99027d0d10ecbea68ca2db57808da119745fafbb0c704b588480f75682de5b7a12509829e2fe27c572ae1f09da5192ca5d2ace41
6
+ metadata.gz: c2ac8c3bb3d161d8f3ce102ce4a61c022d55b7dc165df776d5b8be31c85d3b103d88516bf60206efac7dbeabe7e26a4a2054d65a0728fff56fc5d2116a26dafc
7
+ data.tar.gz: 55df8e863c2b6234bd593073ea958fdb25d6232de94fd9f499ec6a6530abc5b1b26ac5f6b6f6e7237be16136743016b981a0854b2c6f77ac128aaa9039465627
@@ -15,12 +15,13 @@ module Hotdog
15
15
  @options = {
16
16
  environment: "default",
17
17
  minimum_expiry: 28800, # 8 hours
18
- random_expiry: 57600, # 16 hours
18
+ random_expiry: 604800, # 7 days
19
19
  force: false,
20
20
  formatter: get_formatter("plain").new,
21
21
  headers: false,
22
22
  listing: false,
23
23
  logger: Logger.new(STDERR),
24
+ max_time: 30,
24
25
  api_key: ENV["DATADOG_API_KEY"],
25
26
  application_key: ENV["DATADOG_APPLICATION_KEY"],
26
27
  print0: false,
@@ -54,14 +55,19 @@ module Hotdog
54
55
 
55
56
  begin
56
57
  command = ( args.shift || "help" )
57
- run_command(command, args)
58
+ c = run_command(command, args)
59
+ if c.suspended?
60
+ exit(2)
61
+ end
58
62
  rescue Errno::EPIPE
59
63
  # nop
60
64
  end
61
65
  end
62
66
 
63
67
  def run_command(command, args=[])
64
- get_command(command).new(@db, options.merge(application: self)).run(args)
68
+ get_command(command).new(@db, options.merge(application: self)).tap do |c|
69
+ c.run(args)
70
+ end
65
71
  end
66
72
 
67
73
  private
@@ -72,35 +78,38 @@ module Hotdog
72
78
  @optparse.on("--application-key APP_KEY", "Datadog application key") do |app_key|
73
79
  options[:application_key] = app_key
74
80
  end
75
- @optparse.on("-0", "--null", "Use null character as separator") do
76
- options[:print0] = true
81
+ @optparse.on("-0", "--null", "Use null character as separator") do |v|
82
+ options[:print0] = v
77
83
  end
78
- @optparse.on("-1", "Use newline as separator") do
79
- options[:print1] = true
84
+ @optparse.on("-1", "Use newline as separator") do |v|
85
+ options[:print1] = v
80
86
  end
81
- @optparse.on("-d", "--debug", "Enable debug mode") do
82
- options[:logger].level = Logger::DEBUG
87
+ @optparse.on("-d", "--[no-]debug", "Enable debug mode") do |v|
88
+ options[:logger].level = v ? Logger::DEBUG : Logger::INFO
83
89
  end
84
90
  @optparse.on("-E ENVIRONMENT", "--environment ENVIRONMENT", "Specify environment") do |environment|
85
91
  options[:environment] = environment
86
92
  end
87
- @optparse.on("-f", "--force", "Enable force mode") do
88
- options[:force] = true
93
+ @optparse.on("-f", "--[no-]force", "Enable force mode") do |v|
94
+ options[:force] = v
89
95
  end
90
96
  @optparse.on("-F FORMAT", "--format FORMAT", "Specify output format") do |format|
91
97
  options[:formatter] = get_formatter(format).new
92
98
  end
93
- @optparse.on("-h", "--headers", "Display headeres for each columns") do |headers|
94
- options[:headers] = headers
99
+ @optparse.on("-h", "--[no-]headers", "Display headeres for each columns") do |v|
100
+ options[:headers] = v
95
101
  end
96
- @optparse.on("-l", "Use listing format") do
97
- options[:listing] = true
102
+ @optparse.on("-l", "--[no-]listing", "Use listing format") do |v|
103
+ options[:listing] = v
98
104
  end
99
105
  @optparse.on("-a TAG", "-t TAG", "--tag TAG", "Use specified tag name/value") do |tag|
100
106
  options[:tags] += [tag]
101
107
  end
102
- @optparse.on("-V", "--verbose", "Enable verbose mode") do |tag|
103
- options[:logger].level = Logger::DEBUG
108
+ @optparse.on("-m SECONDS", "--max-time SECONDS", Integer, "Maximum time in seconds") do |seconds|
109
+ options[:max_time] = seconds
110
+ end
111
+ @optparse.on("-V", "--[no-]verbose", "Enable verbose mode") do |v|
112
+ options[:logger].level = v ? Logger::DEBUG : Logger::INFO
104
113
  end
105
114
  end
106
115
 
@@ -36,6 +36,9 @@ module Hotdog
36
36
  execute(<<-EOS)
37
37
  CREATE INDEX IF NOT EXISTS hosts_tags_expires_at ON hosts_tags ( expires_at );
38
38
  EOS
39
+ execute(<<-EOS)
40
+ CREATE INDEX IF NOT EXISTS hosts_tags_host_id_expires_at ON hosts_tags ( host_id, expires_at );
41
+ EOS
39
42
  application.run_command("update")
40
43
  end
41
44
  end
@@ -14,6 +14,8 @@ module Hotdog
14
14
  @application = options[:application]
15
15
  @options = options
16
16
  @dog = Dogapi::Client.new(options[:api_key], options[:application_key])
17
+ @started_at = Time.new
18
+ @suspended = false
17
19
  end
18
20
  attr_reader :application
19
21
  attr_reader :formatter
@@ -34,6 +36,10 @@ module Hotdog
34
36
  @db.execute(query, args)
35
37
  end
36
38
 
39
+ def suspended?()
40
+ @suspended
41
+ end
42
+
37
43
  private
38
44
  def format(result, options={})
39
45
  @formatter.format(result, @options.merge(options))
@@ -106,10 +112,12 @@ module Hotdog
106
112
  def update_hosts(options={})
107
113
  @db.transaction do
108
114
  if not options[:force]
115
+ # Update host list on every expirations to update frequently.
109
116
  @update_hosts_q1 ||= @db.prepare("SELECT MIN(expires_at) FROM hosts_tags;")
110
117
  logger.debug("update_hosts_q1()")
111
118
  if expires_at = @update_hosts_q1.execute().map { |row| row.first }.first
112
119
  if Time.new.to_i < expires_at
120
+ logger.debug("next update will run after %s." % [Time.at(expires_at)])
113
121
  return
114
122
  else
115
123
  logger.debug("minimum expires_at was %s. start updateing." % [Time.at(expires_at)])
@@ -120,26 +128,36 @@ module Hotdog
120
128
  end
121
129
 
122
130
  code, result = @dog.search("hosts:")
131
+ logger.debug("dog.serarch(%s) #==> [%s, %s]" % ["hosts:".inspect, code.inspect, result.inspect])
123
132
  if code.to_i / 100 != 2
124
133
  raise("HTTP #{code}: #{result.inspect}")
125
134
  end
126
135
 
136
+ execute(<<-EOS % result["results"]["hosts"].map { "LOWER(?)" }.join(", "), result["results"]["hosts"])
137
+ DELETE FROM hosts_tags WHERE host_id NOT IN
138
+ ( SELECT id FROM hosts WHERE LOWER(name) IN ( %s ) );
139
+ EOS
140
+
127
141
  result["results"]["hosts"].each do |host_name|
128
142
  @update_hosts_q2 ||= @db.prepare("INSERT OR IGNORE INTO hosts (name) VALUES (?);")
129
143
  logger.debug("update_hosts_q2(%s)" % [host_name.inspect])
130
144
  @update_hosts_q2.execute(host_name)
131
145
  update_host_tags(host_name, options)
132
- end
133
146
 
134
- execute(<<-EOS % result["results"]["hosts"].map { "LOWER(?)" }.join(", "), result["results"]["hosts"])
135
- DELETE FROM hosts_tags WHERE host_id NOT IN
136
- ( SELECT id FROM hosts WHERE LOWER(name) IN ( %s ) );
137
- EOS
147
+ elapsed_time = Time.new - @started_at
148
+ if 0 < options[:max_time] and options[:max_time] < elapsed_time
149
+ logger.info("update host tags exceeded the maximum time (#{options[:max_time]} < #{elapsed_time}). will resume on next run.")
150
+ suspend_host_tags
151
+ break
152
+ end
153
+ end
138
154
  end
139
155
  end
140
156
 
141
157
  def update_tags(options={})
142
158
  @db.transaction do
159
+ resume_host_tags
160
+
143
161
  if options[:force]
144
162
  @update_tags_q1 ||= @db.prepare(<<-EOS)
145
163
  SELECT DISTINCT hosts_tags.host_id FROM hosts_tags;
@@ -154,12 +172,52 @@ module Hotdog
154
172
  EOS
155
173
  hosts = @update_tags_q2.execute(Time.new.to_i)
156
174
  end
157
- hosts.each do |host_name|
158
- update_host_tags(host_name, options)
175
+ hosts.each do |host_id|
176
+ @update_tags_q3 ||= @db.prepare("DELETE FROM hosts_tags WHERE host_id = ? AND hosts_tags.expires_at < ?;")
177
+ logger.debug("update_tags_q3(%s, %s)" % [host_id.inspect, Time.new.to_i])
178
+ @update_tags_q3.execute(host_id, Time.new.to_i)
179
+
180
+ update_host_tags(host_id, options)
181
+
182
+ elapsed_time = Time.new - @started_at
183
+ if 0 < options[:max_time] and options[:max_time] < elapsed_time
184
+ logger.info("update host tags exceeded the maximum time (#{options[:max_time]} < #{elapsed_time}). will resume on next run.")
185
+ suspend_host_tags
186
+ break
187
+ end
159
188
  end
160
189
  end
161
190
  end
162
191
 
192
+ # it'd be better to filter out this host/tag entry on displaying...
193
+ EMPTY_HOST_NAME = ""
194
+ EMPTY_TAG_NAME = ""
195
+ EMPTY_TAG_VALUE = ""
196
+ EMPTY_EXPIRES_AT = Time.at(0).to_i
197
+
198
+ def suspend_host_tags()
199
+ @suspended = true
200
+ @suspend_host_tags_q1 ||= @db.prepare("INSERT OR IGNORE INTO hosts (name) VALUES (?);")
201
+ @suspend_host_tags_q1.execute(EMPTY_HOST_NAME)
202
+ @suspend_host_tags_q2 ||= @db.prepare("INSERT OR IGNORE INTO tags (name, value) VALUES (?, ?);")
203
+ @suspend_host_tags_q2.execute(EMPTY_TAG_NAME, EMPTY_TAG_VALUE)
204
+ @suspend_host_tags_q3 ||= @db.prepare(<<-EOS)
205
+ INSERT OR REPLACE INTO hosts_tags (host_id, tag_id, expires_at)
206
+ SELECT host.id, tag.id, ? FROM
207
+ ( SELECT id FROM hosts WHERE name = ?) AS host,
208
+ ( SELECT id FROM tags WHERE name = ? AND value = ? ) AS tag;
209
+ EOS
210
+ @suspend_host_tags_q3.execute(EMPTY_EXPIRES_AT, EMPTY_HOST_NAME, EMPTY_TAG_NAME, EMPTY_TAG_VALUE)
211
+ end
212
+
213
+ def resume_host_tags()
214
+ @resume_host_tags_q1 ||= @db.prepare(<<-EOS)
215
+ DELETE FROM hosts_tags
216
+ WHERE host_id IN ( SELECT id FROM hosts WHERE name = ? ) AND tag_id IN ( SELECT id FROM tags WHERE name = ? AND value = ? );
217
+ EOS
218
+ @resume_host_tags_q1.execute(EMPTY_HOST_NAME, EMPTY_TAG_NAME, EMPTY_TAG_VALUE)
219
+ end
220
+
163
221
  def update_host_tags(host_name, options={})
164
222
  if Integer === host_name
165
223
  host_id = host_name
@@ -173,13 +231,16 @@ module Hotdog
173
231
  end
174
232
 
175
233
  if not options[:force]
176
- @update_host_tags_q3 ||= @db.prepare("SELECT MIN(expires_at) FROM hosts_tags WHERE host_id = ?;")
234
+ # Update host tags less frequently.
235
+ # Don't need to run updates on every expiration.
236
+ @update_host_tags_q3 ||= @db.prepare("SELECT AVG(expires_at) FROM hosts_tags WHERE host_id = ?;")
177
237
  logger.debug("update_host_tags_q3(%s)" % [host_id.inspect])
178
238
  if expires_at = @update_host_tags_q3.execute(host_id).map { |row| row.first }.first
179
239
  if Time.new.to_i < expires_at
240
+ logger.debug("%s: next update will run after %s." % [host_name, Time.at(expires_at)])
180
241
  return
181
242
  else
182
- logger.debug("%s: minimum expires_at was %s. start updating." % [host_name, Time.at(expires_at)])
243
+ logger.debug("%s: average expires_at was %s. start updating." % [host_name, Time.at(expires_at)])
183
244
  end
184
245
  else
185
246
  logger.debug("%s: expires_at not found. start updateing." % [host_name])
@@ -187,10 +248,12 @@ module Hotdog
187
248
  end
188
249
 
189
250
  code, result = @dog.host_tags(host_name)
251
+ logger.debug("dog.hosts_tags(%s) #==> [%s, %s]" % [host_name.inspect, code.inspect, result.inspect])
190
252
  if code.to_i / 100 != 2
191
253
  case code.to_i
192
254
  when 404 # host not found on datadog
193
255
  @update_host_tags_q7 ||= @db.prepare("DELETE FROM hosts_tags WHERE host_id IN ( SELECT id FROM hosts WHERE LOWER(name) = LOWER(?) );")
256
+ logger.debug("update_host_tags_q7(%s)" % [host_name.inspect])
194
257
  @update_host_tags_q7.execute(host_name)
195
258
  end
196
259
  raise("HTTP #{code}: #{result.inspect}")
@@ -1,3 +1,3 @@
1
1
  module Hotdog
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
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.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yamashita Yuu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-30 00:00:00.000000000 Z
11
+ date: 2014-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler