hotdog 0.1.18 → 0.2.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.
@@ -27,7 +27,7 @@ module Hotdog
27
27
  raise(NotImplementedError)
28
28
  end
29
29
 
30
- def execute(query, *args)
30
+ def execute(query, args=[])
31
31
  update_db
32
32
  q = query.strip
33
33
  if 0 < args.length
@@ -67,73 +67,94 @@ module Hotdog
67
67
  s.index('*') or s.index('?') or s.index('[') or s.index(']')
68
68
  end
69
69
 
70
- def host?(host_id)
71
- host_id = execute("SELECT id FROM hosts WHERE name = %s LIMIT 1", s)
72
- not host_id.nil?
73
- end
74
-
75
- def get_hosts(hosts, tags=nil)
70
+ def get_hosts(host_ids, tags=nil)
76
71
  tags ||= @options[:tags]
77
72
  update_db
78
- if 0 < tags.length
79
- result = hosts.map { |host_id|
80
- tags.map { |tag|
81
- tag_name, tag_value = tag.split(":", 2)
82
- case tag_name
83
- when "host"
84
- select_name_from_hosts_by_id(@db, host_id)
85
- else
86
- if glob?(tag_name)
87
- select_tag_values_from_hosts_tags_by_host_id_and_tag_name_glob(@db, host_id, tag_name)
88
- else
89
- select_tag_values_from_hosts_tags_by_host_id_and_tag_name(@db, host_id, tag_name)
90
- end
91
- end
92
- }
93
- }
94
- fields = tags
73
+ if host_ids.empty?
74
+ [[], []]
95
75
  else
96
- if @options[:listing]
97
- # TODO: should respect `:primary_tag`
98
- fields = []
99
- hosts = execute("SELECT id, name FROM hosts WHERE id IN (%s)" % hosts.map { "?" }.join(", "), hosts)
100
- result = hosts.map { |host_id, host_name|
101
- tag_names = select_tag_names_from_hosts_tags_by_host_id(@db, host_id)
102
- tag_names.each do |tag_name|
103
- fields << tag_name unless fields.index(tag_name)
104
- end
105
- [host_name] + fields.map { |tag_name|
106
- if glob?(tag_name)
107
- select_tag_values_from_hosts_tags_by_host_id_and_tag_name_glob(@db, host_id, tag_name)
76
+ if 0 < tags.length
77
+ fields = tags.map { |tag|
78
+ tag_name, tag_value = split_tag(tag)
79
+ tag_name
80
+ }
81
+ fields_without_host = fields.reject { |tag_name| tag_name == "host" }
82
+ if fields == fields_without_host
83
+ host_names = {}
84
+ else
85
+ host_names = Hash[execute("SELECT id, name FROM hosts WHERE id IN (%s)" % host_ids.map { "?" }.join(", "), host_ids).map { |row| row.to_a }]
86
+ end
87
+ q1 = []
88
+ q1 << "SELECT tags.name, GROUP_CONCAT(tags.value, ',') FROM hosts_tags"
89
+ q1 << "INNER JOIN hosts ON hosts_tags.host_id = hosts.id"
90
+ q1 << "INNER JOIN tags ON hosts_tags.tag_id = tags.id"
91
+ q1 << "WHERE hosts_tags.host_id = ? AND tags.name IN (%s)"
92
+ q1 << "GROUP BY tags.name;"
93
+ result = host_ids.map { |host_id|
94
+ tag_values = Hash[execute(q1.join(" ") % fields_without_host.map { "?" }.join(", "), [host_id] + fields_without_host).map { |row| row.to_a }]
95
+ fields.map { |tag_name|
96
+ if tag_name == "host"
97
+ host_names.fetch(host_id, "")
108
98
  else
109
- select_tag_values_from_hosts_tags_by_host_id_and_tag_name(@db, host_id, tag_name)
99
+ tag_values.fetch(tag_name, "")
110
100
  end
111
101
  }
112
102
  }
113
- fields = ["host"] + fields
103
+ [result, fields]
114
104
  else
115
- if @options[:primary_tag]
116
- fields = [@options[:primary_tag]]
117
- tag_name, tag_value = @options[:primary_tag].split(":", 2)
118
- case tag_name
119
- when "host"
120
- result = execute("SELECT name FROM hosts WHERE id IN (%s)" % hosts.map { "?" }.join(", "), hosts)
105
+ if @options[:listing]
106
+ q1 = []
107
+ q1 << "SELECT DISTINCT tags.name FROM hosts_tags"
108
+ q1 << "INNER JOIN tags ON hosts_tags.tag_id = tags.id"
109
+ q1 << "WHERE hosts_tags.host_id IN (%s);"
110
+ if @options[:primary_tag]
111
+ fields = [
112
+ @options[:primary_tag],
113
+ "host",
114
+ ] + execute(q1.join(" ") % host_ids.map { "?" }.join(", "), host_ids).map { |row| row.first }.reject { |tag_name|
115
+ tag_name == @options[:primary_tag]
116
+ }
121
117
  else
122
- result = hosts.map { |host_id|
123
- if glob?(tag_name)
124
- [select_tag_values_from_hosts_tags_by_host_id_and_tag_name_glob(@db, host_id, tag_name)]
118
+ fields = [
119
+ "host",
120
+ ] + execute(q1.join(" ") % host_ids.map { "?" }.join(", "), host_ids).map { |row| row.first }
121
+ end
122
+ host_names = Hash[execute("SELECT id, name FROM hosts WHERE id IN (%s)" % host_ids.map { "?" }.join(", "), host_ids).map { |row| row.to_a }]
123
+ q2 = []
124
+ q2 << "SELECT tags.name, GROUP_CONCAT(tags.value, ',') FROM hosts_tags"
125
+ q2 << "INNER JOIN tags ON hosts_tags.tag_id = tags.id"
126
+ q2 << "WHERE hosts_tags.host_id = ? AND tags.name IN (%s)"
127
+ q2 << "GROUP BY tags.name;"
128
+ fields_without_host = fields.reject { |tag_name| tag_name == "host" }
129
+ result = host_ids.map { |host_id|
130
+ tag_values = Hash[execute(q2.join(" ") % fields_without_host.map { "?" }.join(", "), [host_id] + fields_without_host).map { |row| row.to_a }]
131
+ fields.map { |tag_name|
132
+ if tag_name == "host"
133
+ host_names.fetch(host_id, "")
125
134
  else
126
- [select_tag_values_from_hosts_tags_by_host_id_and_tag_name(@db, host_id, tag_name)]
135
+ tag_values.fetch(tag_name, "")
127
136
  end
128
137
  }
129
- end
138
+ }
139
+ [result, fields]
130
140
  else
131
- fields = ["host"]
132
- result = execute("SELECT name FROM hosts WHERE id IN (%s)" % hosts.map { "?" }.join(", "), hosts)
141
+ if @options[:primary_tag]
142
+ fields = [@options[:primary_tag]]
143
+ q1 = []
144
+ q1 << "SELECT tags.value FROM hosts_tags"
145
+ q1 << "INNER JOIN hosts ON hosts_tags.host_id = hosts.id"
146
+ q1 << "INNER JOIN tags ON hosts_tags.tag_id = tags.id"
147
+ q1 << "WHERE hosts_tags.host_id IN (%s) AND tags.name = ?;"
148
+ result = execute(q1.join(" ") % host_ids.map { "?" }.join(", "), host_ids + [@options[:primary_tag]]).map { |row| row.to_a }
149
+ [result, fields]
150
+ else
151
+ fields = ["host"]
152
+ result = execute("SELECT name FROM hosts WHERE id IN (%s)" % host_ids.map { "?" }.join(", "), host_ids).map { |row| row.to_a }
153
+ [result, fields]
154
+ end
133
155
  end
134
156
  end
135
157
  end
136
- [result, fields]
137
158
  end
138
159
 
139
160
  def close_db(db, options={})
@@ -172,44 +193,26 @@ module Hotdog
172
193
  create_table_hosts_tags(memory_db)
173
194
  create_index_hosts_tags(memory_db)
174
195
 
175
- code, all_tags = @dog.all_tags()
176
- logger.debug("dog.all_tags() #==> [%s, ...]" % [code.inspect])
177
- if code.to_i / 100 != 2
178
- raise("dog.all_tags() returns [%s, ...]" % [code.inspect])
179
- end
196
+ all_tags = get_all_tags()
180
197
 
181
- code, all_downtimes = @dog.get_all_downtimes()
182
- logger.debug("dog.get_all_downtimes() #==> [%s, ...]" % [code.inspect])
183
- if code.to_i / 100 != 2
184
- raise("dog.get_all_downtimes() returns [%s, ...]" % [code.inspect])
198
+ known_tags = all_tags.keys.map { |tag| split_tag(tag) }.uniq
199
+ unless known_tags.empty?
200
+ prepare(memory_db, "INSERT OR IGNORE INTO tags (name, value) VALUES %s" % known_tags.map { "(?, ?)" }.join(", ")).execute(known_tags)
185
201
  end
186
202
 
187
- now = Time.new.to_i
188
- downs = all_downtimes.select { |downtime|
189
- # active downtimes
190
- downtime["active"] and ( downtime["start"].nil? or downtime["start"] < now ) and ( downtime["end"].nil? or now <= downtime["end"] )
191
- }.map { |downtime|
192
- # find host scopes
193
- downtime["scope"].select { |scope| scope.start_with?("host:") }.map { |scope| scope.sub(/\Ahost:/, "") }
194
- }.reduce(:+)
195
- downs ||= []
196
-
197
- # for case-insensitive match of hostname
198
- downs = downs.map { |down| down.downcase }
199
-
200
- if not downs.empty?
201
- logger.info("ignore host(s) with scheduled downtimes: #{downs.inspect}")
203
+ known_hosts = all_tags.values.reduce(:+).uniq
204
+ unless known_hosts.empty?
205
+ prepare(memory_db, "INSERT OR IGNORE INTO hosts (name) VALUES %s" % known_hosts.map { "(?)" }.join(", ")).execute(known_hosts)
202
206
  end
203
207
 
204
- all_tags["tags"].each do |tag, hosts|
205
- tag_name, tag_value = tag.split(":", 2)
206
- tag_value ||= ""
207
- insert_or_ignore_into_tags(memory_db, tag_name, tag_value)
208
- hosts.each do |host_name|
209
- if not downs.include?(host_name.downcase)
210
- insert_or_ignore_into_hosts(memory_db, host_name)
211
- insert_or_replace_into_hosts_tags(memory_db, host_name, tag_name, tag_value)
212
- end
208
+ all_tags.each do |tag, hosts|
209
+ q = []
210
+ q << "INSERT OR REPLACE INTO hosts_tags (host_id, tag_id)"
211
+ q << "SELECT host.id, tag.id FROM"
212
+ q << "( SELECT id FROM hosts WHERE name IN (%s) ) AS host,"
213
+ q << "( SELECT id FROM tags WHERE name = ? AND value = ? LIMIT 1 ) AS tag;"
214
+ unless hosts.empty?
215
+ prepare(memory_db, q.join(" ") % hosts.map { "?" }.join(", ")).execute(hosts + split_tag(tag))
213
216
  end
214
217
  end
215
218
 
@@ -224,6 +227,36 @@ module Hotdog
224
227
  end
225
228
  end
226
229
 
230
+ def get_all_tags() #==> Hash<Tag,Array<Host>>
231
+ code, all_tags = @dog.all_tags()
232
+ logger.debug("dog.all_tags() #==> [%s, ...]" % [code.inspect])
233
+ if code.to_i / 100 != 2
234
+ raise("dog.all_tags() returns [%s, ...]" % [code.inspect])
235
+ end
236
+ code, all_downtimes = @dog.get_all_downtimes()
237
+ logger.debug("dog.get_all_downtimes() #==> [%s, ...]" % [code.inspect])
238
+ if code.to_i / 100 != 2
239
+ raise("dog.get_all_downtimes() returns [%s, ...]" % [code.inspect])
240
+ end
241
+ now = Time.new.to_i
242
+ downtimes = all_downtimes.select { |downtime|
243
+ # active downtimes
244
+ downtime["active"] and ( downtime["start"].nil? or downtime["start"] < now ) and ( downtime["end"].nil? or now <= downtime["end"] )
245
+ }.map { |downtime|
246
+ # find host scopes
247
+ downtime["scope"].select { |scope| scope.start_with?("host:") }.map { |scope| scope.sub(/\Ahost:/, "") }
248
+ }.reduce(:+) || []
249
+ if not downtimes.empty?
250
+ logger.info("ignore host(s) with scheduled downtimes: #{downtimes.inspect}")
251
+ end
252
+ Hash[all_tags["tags"].map { |tag, hosts| [tag, hosts.reject { |host| downtimes.include?(host) }] }]
253
+ end
254
+
255
+ def split_tag(tag)
256
+ tag_name, tag_value = tag.split(":", 2)
257
+ [tag_name, tag_value || ""]
258
+ end
259
+
227
260
  def copy_db(src, dst)
228
261
  # create index later for better insert performance
229
262
  dst.transaction do
@@ -231,15 +264,14 @@ module Hotdog
231
264
  create_table_tags(dst)
232
265
  create_table_hosts_tags(dst)
233
266
 
234
- select_from_hosts(src).each do |host_id, host_name|
235
- insert_into_hosts(dst, host_id, host_name)
236
- end
237
- select_from_tags(src).each do |tag_id, tag_name, tag_value|
238
- insert_into_tags(dst, tag_id, tag_name, tag_value)
239
- end
240
- select_from_hosts_tags(src).each do |host_id, tag_id|
241
- insert_into_hosts_tags(dst, host_id, tag_id)
242
- end
267
+ hosts = prepare(src, "SELECT id, name FROM hosts").execute().to_a
268
+ prepare(dst, "INSERT INTO hosts (id, name) VALUES %s" % hosts.map { "(?, ?)" }.join(", ")).execute(hosts) unless hosts.empty?
269
+
270
+ tags = prepare(src, "SELECT id, name, value FROM tags").execute().to_a
271
+ prepare(dst, "INSERT INTO tags (id, name, value) VALUES %s" % tags.map { "(?, ?, ?)" }.join(", ")).execute(tags) unless tags.empty?
272
+
273
+ hosts_tags = prepare(src, "SELECT host_id, tag_id FROM hosts_tags").to_a
274
+ prepare(dst, "INSERT INTO hosts_tags (host_id, tag_id) VALUES %s" % hosts_tags.map { "(?, ?)" }.join(", ")).execute(hosts_tags) unless hosts_tags.empty?
243
275
 
244
276
  create_index_hosts(dst)
245
277
  create_index_tags(dst)
@@ -247,29 +279,14 @@ module Hotdog
247
279
  end
248
280
  end
249
281
 
250
- def select_from_hosts(db)
251
- logger.debug("select_from_hosts()")
252
- prepare(db, "SELECT id, name FROM hosts").execute()
253
- end
254
-
255
- def select_from_tags(db)
256
- logger.debug("select_from_tags()")
257
- prepare(db, "SELECT id, name, value FROM tags").execute()
258
- end
259
-
260
- def select_from_hosts_tags(db)
261
- logger.debug("select_from_hosts_tags()")
262
- prepare(db, "SELECT host_id, tag_id FROM hosts_tags").execute()
263
- end
264
-
265
282
  def create_table_hosts(db)
266
283
  logger.debug("create_table_hosts()")
267
- db.execute(<<-EOS)
268
- CREATE TABLE IF NOT EXISTS hosts (
269
- id INTEGER PRIMARY KEY AUTOINCREMENT,
270
- name VARCHAR(255) NOT NULL
271
- );
272
- EOS
284
+ q = []
285
+ q << "CREATE TABLE IF NOT EXISTS hosts ("
286
+ q << "id INTEGER PRIMARY KEY AUTOINCREMENT,"
287
+ q << "name VARCHAR(255) NOT NULL COLLATE NOCASE"
288
+ q << ");"
289
+ db.execute(q.join(" "))
273
290
  end
274
291
 
275
292
  def create_index_hosts(db)
@@ -279,13 +296,13 @@ module Hotdog
279
296
 
280
297
  def create_table_tags(db)
281
298
  logger.debug("create_table_tags()")
282
- db.execute(<<-EOS)
283
- CREATE TABLE IF NOT EXISTS tags (
284
- id INTEGER PRIMARY KEY AUTOINCREMENT,
285
- name VARCHAR(200) NOT NULL,
286
- value VARCHAR(200) NOT NULL DEFAULT ""
287
- );
288
- EOS
299
+ q = []
300
+ q << "CREATE TABLE IF NOT EXISTS tags ("
301
+ q << "id INTEGER PRIMARY KEY AUTOINCREMENT,"
302
+ q << "name VARCHAR(200) NOT NULL COLLATE NOCASE,"
303
+ q << "value VARCHAR(200) NOT NULL COLLATE NOCASE"
304
+ q << ");"
305
+ db.execute(q.join(" "))
289
306
  end
290
307
 
291
308
  def create_index_tags(db)
@@ -295,85 +312,18 @@ module Hotdog
295
312
 
296
313
  def create_table_hosts_tags(db)
297
314
  logger.debug("create_table_hosts_tags()")
298
- db.execute(<<-EOS)
299
- CREATE TABLE IF NOT EXISTS hosts_tags (
300
- host_id INTEGER NOT NULL,
301
- tag_id INTEGER NOT NULL
302
- );
303
- EOS
315
+ q = []
316
+ q << "CREATE TABLE IF NOT EXISTS hosts_tags ("
317
+ q << "host_id INTEGER NOT NULL,"
318
+ q << "tag_id INTEGER NOT NULL"
319
+ q << ");"
320
+ db.execute(q.join(" "))
304
321
  end
305
322
 
306
323
  def create_index_hosts_tags(db)
307
324
  logger.debug("create_index_hosts_tags()")
308
325
  db.execute("CREATE UNIQUE INDEX IF NOT EXISTS hosts_tags_host_id_tag_id ON hosts_tags ( host_id, tag_id )")
309
326
  end
310
-
311
- def insert_into_tags(db, tag_id, tag_name, tag_value)
312
- logger.debug("insert_into_tags(%s, %s, %s)" % [tag_id.inspect, tag_name.inspect, tag_value.inspect])
313
- prepare(db, "INSERT INTO tags (id, name, value) VALUES (?, ?, ?)").execute(tag_id, tag_name, tag_value)
314
- end
315
-
316
- def insert_or_ignore_into_tags(db, tag_name, tag_value)
317
- logger.debug("insert_or_ignore_into_tags(%s, %s)" % [tag_name.inspect, tag_value.inspect])
318
- prepare(db, "INSERT OR IGNORE INTO tags (name, value) VALUES (?, ?)").execute(tag_name, tag_value)
319
- end
320
-
321
- def insert_into_hosts(db, host_id, host_name)
322
- logger.debug("insert_into_hosts(%s, %s)" % [host_id.inspect, host_name.inspect])
323
- prepare(db, "INSERT INTO hosts (id, name) VALUES (?, ?)").execute(host_id, host_name)
324
- end
325
-
326
- def insert_or_ignore_into_hosts(db, host_name)
327
- logger.debug("insert_or_ignore_into_hosts(%s)" % [host_name.inspect])
328
- prepare(db, "INSERT OR IGNORE INTO hosts (name) VALUES (?)").execute(host_name)
329
- end
330
-
331
- def insert_into_hosts_tags(db, host_id, tag_id)
332
- logger.debug("insert_into_hosts_tags(%s, %s)" % [host_id.inspect, tag_id.inspect])
333
- prepare(db, "INSERT INTO hosts_tags (host_id, tag_id) VALUES (?, ?)").execute(host_id, tag_id)
334
- end
335
-
336
- def insert_or_replace_into_hosts_tags(db, host_name, tag_name, tag_value)
337
- logger.debug("insert_or_replace_into_hosts_tags(%s, %s, %s)" % [host_name.inspect, tag_name.inspect, tag_value.inspect])
338
- prepare(db, <<-EOS).execute(host_name, tag_name, tag_value)
339
- INSERT OR REPLACE INTO hosts_tags (host_id, tag_id)
340
- SELECT host.id, tag.id FROM
341
- ( SELECT id FROM hosts WHERE LOWER(name) = LOWER(?) ) AS host,
342
- ( SELECT id FROM tags WHERE LOWER(name) = LOWER(?) AND LOWER(value) = LOWER(?) ) AS tag;
343
- EOS
344
- end
345
-
346
- def select_name_from_hosts_by_id(db, host_id)
347
- logger.debug("select_name_from_hosts_by_id(%s)" % [host_id.inspect])
348
- prepare(db, "SELECT name FROM hosts WHERE id = ? LIMIT 1").execute(host_id).map { |row| row.first }.first
349
- end
350
-
351
- def select_tag_values_from_hosts_tags_by_host_id_and_tag_name_glob(db, host_id, tag_name)
352
- logger.debug("select_tag_values_from_hosts_tags_by_host_id_and_tag_name_glob(%s, %s)" % [host_id.inspect, tag_name.inspect])
353
- prepare(db, <<-EOS).execute(host_id, tag_name).map { |row| row.first }.join(",")
354
- SELECT tags.value FROM hosts_tags
355
- INNER JOIN tags ON hosts_tags.tag_id = tags.id
356
- WHERE hosts_tags.host_id = ? AND LOWER(tags.name) GLOB LOWER(?);
357
- EOS
358
- end
359
-
360
- def select_tag_values_from_hosts_tags_by_host_id_and_tag_name(db, host_id, tag_name)
361
- logger.debug("select_tag_values_from_hosts_tags_by_host_id_and_tag_name(%s, %s)" % [host_id.inspect, tag_name.inspect])
362
- prepare(db, <<-EOS).execute(host_id, tag_name).map { |row| row.first }.join(",")
363
- SELECT tags.value FROM hosts_tags
364
- INNER JOIN tags ON hosts_tags.tag_id = tags.id
365
- WHERE hosts_tags.host_id = ? AND LOWER(tags.name) = LOWER(?);
366
- EOS
367
- end
368
-
369
- def select_tag_names_from_hosts_tags_by_host_id(db, host_id)
370
- logger.debug("select_tag_names_from_hosts_tags_by_host_id(%s)" % [host_id.inspect])
371
- prepare(db, <<-EOS).execute(host_id).map { |row| row.first }
372
- SELECT DISTINCT tags.name FROM hosts_tags
373
- INNER JOIN tags ON hosts_tags.tag_id = tags.id
374
- WHERE hosts_tags.host_id = ?;
375
- EOS
376
- end
377
327
  end
378
328
  end
379
329
  end
@@ -4,10 +4,15 @@ module Hotdog
4
4
  module Formatters
5
5
  class Ltsv < BaseFormatter
6
6
  def format(result, options={})
7
- fields = options.fetch(:fields, [])
8
- result.map { |row|
9
- fields.zip(row).map { |column| column.join(":") }.join("\t")
10
- }.join("\n") + "\n"
7
+ if options[:fields]
8
+ result.map { |row|
9
+ options[:fields].zip(row).map { |column| column.join(":") }.join("\t")
10
+ }.join("\n") + "\n"
11
+ else
12
+ result.map { |row|
13
+ row.join("\t")
14
+ }.join("\n") + "\n"
15
+ end
11
16
  end
12
17
  end
13
18
  end
@@ -27,7 +27,7 @@ module Hotdog
27
27
  },
28
28
  ] + result.map { |row|
29
29
  row.zip(field_length).map { |field, length|
30
- padding = length - ((field.nil?) ? 0 : field.length)
30
+ padding = length - ((field.nil?) ? 0 : field.to_s.length)
31
31
  field.to_s + (" " * padding)
32
32
  }
33
33
  }
@@ -1,3 +1,3 @@
1
1
  module Hotdog
2
- VERSION = "0.1.18"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,36 @@
1
+ require "spec_helper"
2
+ require "hotdog/application"
3
+ require "hotdog/commands"
4
+ require "hotdog/commands/hosts"
5
+ require "hotdog/commands/search"
6
+ require "hotdog/commands/tags"
7
+
8
+ describe "application" do
9
+ let(:app) {
10
+ Hotdog::Application.new
11
+ }
12
+
13
+ before(:each) do
14
+ ENV["DATADOG_API_KEY"] = "DATADOG_API_KEY"
15
+ ENV["DATADOG_APPLICATION_KEY"] = "DATADOG_APPLICATION_KEY"
16
+ end
17
+
18
+ it "generates proper class name from file name" do
19
+ expect(app.__send__(:const_name, "csv")).to eq("Csv")
20
+ expect(app.__send__(:const_name, "json")).to eq("Json")
21
+ expect(app.__send__(:const_name, "pssh")).to eq("Pssh")
22
+ expect(app.__send__(:const_name, "parallel-ssh")).to eq("ParallelSsh")
23
+ end
24
+
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)
29
+ end
30
+
31
+ it "raises error if the action is base-command" do
32
+ expect {
33
+ app.main(["base-command"])
34
+ }.to raise_error(NotImplementedError)
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+ require "hotdog/formatters"
3
+ require "hotdog/formatters/csv"
4
+
5
+ describe "csv" do
6
+ let(:fmt) {
7
+ Hotdog::Formatters::Csv.new
8
+ }
9
+
10
+ it "generates csv without headers" do
11
+ options = {
12
+ headers: false,
13
+ }
14
+ expect(fmt.format([["foo", "aaa", 1], ["bar", "bbb", 2], ["baz", "ccc", 3]], options)).to eq(<<-EOS)
15
+ foo,aaa,1
16
+ bar,bbb,2
17
+ baz,ccc,3
18
+ EOS
19
+ end
20
+
21
+ it "generates csv with headers" do
22
+ options = {
23
+ headers: true,
24
+ fields: ["key1", "key2", "val1"],
25
+ }
26
+ expect(fmt.format([["foo", "aaa", 1], ["bar", "bbb", 2], ["baz", "ccc", 3]], options)).to eq(<<-EOS)
27
+ key1,key2,val1
28
+ foo,aaa,1
29
+ bar,bbb,2
30
+ baz,ccc,3
31
+ EOS
32
+ end
33
+ end
@@ -0,0 +1,66 @@
1
+ require "spec_helper"
2
+ require "hotdog/formatters"
3
+ require "hotdog/formatters/json"
4
+
5
+ describe "json" do
6
+ let(:fmt) {
7
+ Hotdog::Formatters::Json.new
8
+ }
9
+
10
+ it "generates json without headers" do
11
+ options = {
12
+ headers: false,
13
+ }
14
+ expect(fmt.format([["foo", "aaa", 1], ["bar", "bbb", 2], ["baz", "ccc", 3]], options)).to eq(<<-EOS)
15
+ [
16
+ [
17
+ "foo",
18
+ "aaa",
19
+ 1
20
+ ],
21
+ [
22
+ "bar",
23
+ "bbb",
24
+ 2
25
+ ],
26
+ [
27
+ "baz",
28
+ "ccc",
29
+ 3
30
+ ]
31
+ ]
32
+ EOS
33
+ end
34
+
35
+ it "generates json with headers" do
36
+ options = {
37
+ headers: true,
38
+ fields: ["key1", "key2", "val1"],
39
+ prettyprint: false,
40
+ }
41
+ expect(fmt.format([["foo", "aaa", 1], ["bar", "bbb", 2], ["baz", "ccc", 3]], options)).to eq(<<-EOS)
42
+ [
43
+ [
44
+ "key1",
45
+ "key2",
46
+ "val1"
47
+ ],
48
+ [
49
+ "foo",
50
+ "aaa",
51
+ 1
52
+ ],
53
+ [
54
+ "bar",
55
+ "bbb",
56
+ 2
57
+ ],
58
+ [
59
+ "baz",
60
+ "ccc",
61
+ 3
62
+ ]
63
+ ]
64
+ EOS
65
+ end
66
+ end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+ require "hotdog/formatters"
3
+ require "hotdog/formatters/ltsv"
4
+
5
+ describe "ltsv" do
6
+ let(:fmt) {
7
+ Hotdog::Formatters::Ltsv.new
8
+ }
9
+
10
+ it "generates ltsv without headers" do
11
+ options = {
12
+ headers: false,
13
+ }
14
+ expect(fmt.format([["foo", "aaa", 1], ["bar", "bbb", 2], ["baz", "ccc", 3]], options)).to eq(<<-EOS)
15
+ foo\taaa\t1
16
+ bar\tbbb\t2
17
+ baz\tccc\t3
18
+ EOS
19
+ end
20
+
21
+ it "generates ltsv with headers" do
22
+ options = {
23
+ headers: true,
24
+ fields: ["key1", "key2", "val1"],
25
+ }
26
+ expect(fmt.format([["foo", "aaa", 1], ["bar", "bbb", 2], ["baz", "ccc", 3]], options)).to eq(<<-EOS)
27
+ key1:foo\tkey2:aaa\tval1:1
28
+ key1:bar\tkey2:bbb\tval1:2
29
+ key1:baz\tkey2:ccc\tval1:3
30
+ EOS
31
+ end
32
+ end