Class: WavefrontDisplay::Base
- Inherits:
-
Object
- Object
- WavefrontDisplay::Base
- Includes:
- WavefrontCli::Constants
- Defined in:
- lib/wavefront-cli/display/base.rb
Overview
Print human-friendly output. If a command requires a dedicated handler to format its output, define a method with the same name as that which fetches the data, in a WavefrontDisplay class, extending this one.
We provide #long_output() and #multicolumn() methods to solve standard formatting problems. To use them, define a do_() method but rather than printing the output, have it call the method.
Direct Known Subclasses
Account, Alert, ApiToken, CloudIntegration, Dashboard, DerivedMetric, Event, ExternalLink, IngestionPolicy, Integration, MaintenanceWindow, Message, Metric, Notificant, Proxy, Query, Role, SavedSearch, ServiceAccount, Settings, Source, Spy, Usage, UserGroup, Webhook, Write
Constant Summary
Constants included from WavefrontCli::Constants
WavefrontCli::Constants::ALL_PAGE_SIZE, WavefrontCli::Constants::DEFAULT_CONFIG, WavefrontCli::Constants::DEFAULT_OPTS, WavefrontCli::Constants::EVENT_STATE_DIR, WavefrontCli::Constants::HUMAN_TIME_FORMAT, WavefrontCli::Constants::HUMAN_TIME_FORMAT_MS, WavefrontCli::Constants::SEARCH_SPLIT
Instance Attribute Summary collapse
-
#data ⇒ Object
readonly
Returns the value of attribute data.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#raw ⇒ Object
readonly
Returns the value of attribute raw.
Instance Method Summary collapse
-
#_prioritize_keys(data, keys) ⇒ Hash, Map
Move the given fields to the start of a Hash or Map.
-
#display_brief_freetext_results ⇒ Object
For freetext searches, we just display the matching fields in “brief” mode.
- #do_delete ⇒ Object
- #do_import ⇒ Object
-
#do_list ⇒ Object
The following do_ methods are default handlers called following their namesake operation in the corresponding WavefrontCli class.
- #do_list_brief ⇒ Object
- #do_list_fields ⇒ Object
- #do_queries ⇒ Object
- #do_search ⇒ Object
- #do_search_brief ⇒ Object
- #do_search_fields ⇒ Object
- #do_tag_add ⇒ Object
- #do_tag_clear ⇒ Object
- #do_tag_delete ⇒ Object
- #do_tag_pathsearch ⇒ Object
- #do_tag_set ⇒ Object
- #do_tags ⇒ Object
- #do_undelete ⇒ Object
-
#drop_fields(*keys) ⇒ Nil
Modify, in-place, the data structure to remove fields which we deem not of interest to the user.
-
#filter_data(data, fields) ⇒ Array[Hash]
Modified version of data.
-
#filter_fields_as_arr ⇒ Array
Filter fields from -O option.
- #freetext_keys ⇒ Object
-
#friendly_name ⇒ Object
return [String] the name of the thing we’re operating on, like ‘alert’ or ‘dashboard’.
-
#human_time(time, force_utc = false) ⇒ Object
Make a time human-readable.
-
#index_of_final_item ⇒ Object
Return the offset of the final item in view.
-
#initialize(raw_response, options = {}) ⇒ Base
constructor
A new instance of Base.
-
#key_width(hash = {}, pad = 2) ⇒ Integer
Give it a key-value hash, and it will return the size of the first column to use when formatting that data.
-
#long_output(fields = nil, modified_data = nil) ⇒ Object
Default display method for ‘describe’ and long-list methods.
- #multicolumn(*columns) ⇒ Object
-
#pagination_line ⇒ Object
if this is a section of a larger dataset, say so.
- #prioritize_keys(data, keys) ⇒ Object
-
#priority_keys ⇒ Object
Keys which we wish to float to the top of descriptions and long listing objects.
-
#quoted(things) ⇒ String
All “things”, strong-quoted and comma-separated.
-
#readable_time(*keys) ⇒ Object
Modify, in-place, the @data structure to make times human-readable.
-
#readable_time_arr(*keys) ⇒ Object
As for #readable_time, but when @data is an array.
-
#run(method) ⇒ Object
find the correct method to deal with the output of the user’s command.
-
#run_error(method) ⇒ Object
Display classes can provide a do_method_code() method, which handles <code> errors when running do_method().
-
#run_list ⇒ Object
Choose the correct list handler.
-
#run_search ⇒ Object
Choose the correct search handler.
- #search_display_keys ⇒ Object
-
#search_identifier_key ⇒ Object
Most objects refer to themselves by ‘id’.
-
#time_formats(str) ⇒ String
How do we format a timestamp?.
Constructor Details
#initialize(raw_response, options = {}) ⇒ Base
Returns a new instance of Base.
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/wavefront-cli/display/base.rb', line 25 def initialize(raw_response, = {}) @raw = raw_response data = if raw_response.respond_to?(:items) raw_response.items else raw_response end @data = prioritize_keys(data, priority_keys) @options = end |
Instance Attribute Details
#data ⇒ Object (readonly)
Returns the value of attribute data.
19 20 21 |
# File 'lib/wavefront-cli/display/base.rb', line 19 def data @data end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
19 20 21 |
# File 'lib/wavefront-cli/display/base.rb', line 19 def @options end |
#raw ⇒ Object (readonly)
Returns the value of attribute raw.
19 20 21 |
# File 'lib/wavefront-cli/display/base.rb', line 19 def raw @raw end |
Instance Method Details
#_prioritize_keys(data, keys) ⇒ Hash, Map
Move the given fields to the start of a Hash or Map
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/wavefront-cli/display/base.rb', line 129 def _prioritize_keys(data, keys) keys.each.with_object(data.is_a?(Map) ? Map.new : {}) do |k, a| next unless data.key?(k) a[k] = data[k] data.delete(k) end.merge(data) rescue NoMethodError data end |
#display_brief_freetext_results ⇒ Object
For freetext searches, we just display the matching fields in “brief” mode.
261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/wavefront-cli/display/base.rb', line 261 def display_brief_freetext_results search_keys = freetext_keys data.map! do |d| mf = d.select do |_k, v| search_keys.any? { |s| v.to_s.include?(s) } end { id: d[:id], matching_fields: mf.to_h.keys } end multicolumn(:id, :matching_fields) end |
#do_delete ⇒ Object
234 235 236 |
# File 'lib/wavefront-cli/display/base.rb', line 234 def do_delete puts "Deleted #{friendly_name} '#{[:'<id>']}'." end |
#do_import ⇒ Object
229 230 231 232 |
# File 'lib/wavefront-cli/display/base.rb', line 229 def do_import puts "Imported #{friendly_name}." long_output end |
#do_list ⇒ Object
The following do_ methods are default handlers called following their namesake operation in the corresponding WavefrontCli class. They can be overriden in the inheriting class.
217 218 219 |
# File 'lib/wavefront-cli/display/base.rb', line 217 def do_list long_output end |
#do_list_brief ⇒ Object
225 226 227 |
# File 'lib/wavefront-cli/display/base.rb', line 225 def do_list_brief multicolumn(:id, :name) end |
#do_list_fields ⇒ Object
221 222 223 |
# File 'lib/wavefront-cli/display/base.rb', line 221 def do_list_fields multicolumn(*filter_fields_as_arr.map(&:to_sym)) end |
#do_queries ⇒ Object
330 331 332 333 334 335 336 |
# File 'lib/wavefront-cli/display/base.rb', line 330 def do_queries if [:brief] multicolumn(:condition) else multicolumn(:id, :condition) end end |
#do_search ⇒ Object
292 293 294 |
# File 'lib/wavefront-cli/display/base.rb', line 292 def do_search long_output end |
#do_search_brief ⇒ Object
242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/wavefront-cli/display/base.rb', line 242 def do_search_brief search_keys = search_display_keys if search_keys.include?(:freetext) display_brief_freetext_results else multicolumn(*search_keys) end rescue KeyError raise WavefrontCli::Exception::ImpossibleSearch end |
#do_search_fields ⇒ Object
254 255 256 |
# File 'lib/wavefront-cli/display/base.rb', line 254 def do_search_fields do_list_fields end |
#do_tag_add ⇒ Object
296 297 298 |
# File 'lib/wavefront-cli/display/base.rb', line 296 def do_tag_add puts "Tagged #{friendly_name} '#{[:'<id>']}'." end |
#do_tag_clear ⇒ Object
304 305 306 |
# File 'lib/wavefront-cli/display/base.rb', line 304 def do_tag_clear puts "Cleared tags on #{friendly_name} '#{[:'<id>']}'." end |
#do_tag_delete ⇒ Object
300 301 302 |
# File 'lib/wavefront-cli/display/base.rb', line 300 def do_tag_delete puts "Deleted tag from #{friendly_name} '#{[:'<id>']}'." end |
#do_tag_pathsearch ⇒ Object
320 321 322 323 324 325 326 327 328 |
# File 'lib/wavefront-cli/display/base.rb', line 320 def do_tag_pathsearch if data.empty? puts 'No matches.' elsif [:long] long_output else multicolumn(:id, :name) end end |
#do_tag_set ⇒ Object
308 309 310 |
# File 'lib/wavefront-cli/display/base.rb', line 308 def do_tag_set puts "Set tags on #{friendly_name} '#{[:'<id>']}'." end |
#do_tags ⇒ Object
312 313 314 315 316 317 318 |
# File 'lib/wavefront-cli/display/base.rb', line 312 def if data.empty? puts "No tags set on #{friendly_name} '#{[:'<id>']}'." else data.sort.each { |t| puts t } end end |
#do_undelete ⇒ Object
238 239 240 |
# File 'lib/wavefront-cli/display/base.rb', line 238 def do_undelete puts "Undeleted #{friendly_name} '#{[:'<id>']}'." end |
#drop_fields(*keys) ⇒ Nil
Modify, in-place, the data structure to remove fields which we deem not of interest to the user.
344 345 346 347 348 349 350 |
# File 'lib/wavefront-cli/display/base.rb', line 344 def drop_fields(*keys) if data.is_a?(Array) data.each { |i| i.delete_if { |k, _v| keys.include?(k.to_sym) } } else data.delete_if { |k, _v| keys.include?(k.to_sym) } end end |
#filter_data(data, fields) ⇒ Array[Hash]
Returns modified version of data. Each hash will contain only the fields given in ‘fields`, in the given order.
77 78 79 80 81 |
# File 'lib/wavefront-cli/display/base.rb', line 77 def filter_data(data, fields) data.map! do |d| fields.each_with_object({}) { |f, a| a[f] = d[f] if d.key?(f) } end end |
#filter_fields_as_arr ⇒ Array
Returns filter fields from -O option.
208 209 210 |
# File 'lib/wavefront-cli/display/base.rb', line 208 def filter_fields_as_arr [:fields].split(',') end |
#freetext_keys ⇒ Object
275 276 277 |
# File 'lib/wavefront-cli/display/base.rb', line 275 def freetext_keys [:'<condition>'].map { |c| c.split(SEARCH_SPLIT, 2).last } end |
#friendly_name ⇒ Object
return [String] the name of the thing we’re operating on, like
'alert' or 'dashboard'.
201 202 203 204 |
# File 'lib/wavefront-cli/display/base.rb', line 201 def friendly_name self.class.name.split('::').last.gsub(/([a-z])([A-Z])/, '\\1 \\2') .downcase end |
#human_time(time, force_utc = false) ⇒ Object
Make a time human-readable. Automatically deals with epoch seconds and epoch milliseconds
param t [Integer, String] a timestamp. If it’s a string, it is
converted to an int.
param force_utc [Boolean] force output in UTC. Currently only
used for unit tests.
return [String] a human-readable timestamp
382 383 384 385 386 387 388 389 390 391 392 393 |
# File 'lib/wavefront-cli/display/base.rb', line 382 def human_time(time, force_utc = false) raise ArgumentError unless time.is_a?(Numeric) || time.is_a?(String) return 'FOREVER' if time == -1 str = time.to_s fmt, out_fmt = time_formats(str) ret = DateTime.strptime(str, fmt).to_time ret = force_utc ? ret.utc : ret.localtime ret.strftime(out_fmt) end |
#index_of_final_item ⇒ Object
Return the offset of the final item in view.
181 182 183 |
# File 'lib/wavefront-cli/display/base.rb', line 181 def index_of_final_item raw.limit.positive? ? raw.offset + raw.limit - 1 : 0 end |
#key_width(hash = {}, pad = 2) ⇒ Integer
Give it a key-value hash, and it will return the size of the first column to use when formatting that data.
192 193 194 195 196 |
# File 'lib/wavefront-cli/display/base.rb', line 192 def key_width(hash = {}, pad = 2) return 0 if hash.keys.empty? hash.keys.map(&:size).max + pad end |
#long_output(fields = nil, modified_data = nil) ⇒ Object
Default display method for ‘describe’ and long-list methods. Wraps around #_two_columns() giving you the chance to modify
150 151 152 153 154 155 156 157 158 |
# File 'lib/wavefront-cli/display/base.rb', line 150 def long_output(fields = nil, modified_data = nil) if data.empty? || modified_data&.empty? puts 'No data.' else require_relative 'printer/long' puts WavefrontDisplayPrinter::Long.new(data, fields, modified_data) pagination_line end end |
#multicolumn(*columns) ⇒ Object
160 161 162 163 164 |
# File 'lib/wavefront-cli/display/base.rb', line 160 def multicolumn(*columns) require_relative 'printer/terse' puts WavefrontDisplayPrinter::Terse.new(data, columns) pagination_line end |
#pagination_line ⇒ Object
if this is a section of a larger dataset, say so
168 169 170 171 172 173 174 175 176 177 |
# File 'lib/wavefront-cli/display/base.rb', line 168 def pagination_line return unless raw.respond_to?(:moreItems) && raw.moreItems == true puts format('List shows items %<first>d to %<last>d. ' \ 'Use -o and -L for more.', first: raw.offset, last: index_of_final_item) rescue StandardError puts 'List shows paginated output. Use -o and -L for more.' end |
#prioritize_keys(data, keys) ⇒ Object
118 119 120 121 122 |
# File 'lib/wavefront-cli/display/base.rb', line 118 def prioritize_keys(data, keys) return _prioritize_keys(data, keys) unless data.is_a?(Array) data.map { |e| _prioritize_keys(e, keys) } end |
#priority_keys ⇒ Object
Keys which we wish to float to the top of descriptions and long listing objects. Subclasses may define their own.
114 115 116 |
# File 'lib/wavefront-cli/display/base.rb', line 114 def priority_keys %i[id name identifier] end |
#quoted(things) ⇒ String
Returns all “things”, strong-quoted and comma-separated.
412 413 414 |
# File 'lib/wavefront-cli/display/base.rb', line 412 def quoted(things) things.map { |item| "'#{item}'" }.join(', ') end |
#readable_time(*keys) ⇒ Object
Modify, in-place, the @data structure to make times human-readable. Automatically handles second and millisecond epoch times. Currently only operates on top-level keys.
param keys [Symbol, Array] the keys you wish to be
turned into readable times.
return [Nil]
360 361 362 |
# File 'lib/wavefront-cli/display/base.rb', line 360 def readable_time(*keys) keys.each { |k| data[k] = human_time(data[k]) if data.key?(k) } end |
#readable_time_arr(*keys) ⇒ Object
As for #readable_time, but when @data is an array. For instance in “firing” alerts
367 368 369 370 371 |
# File 'lib/wavefront-cli/display/base.rb', line 367 def readable_time_arr(*keys) data.map do |row| keys.each { |k| row[k] = human_time(row[k]) if row.key?(k) } end end |
#run(method) ⇒ Object
find the correct method to deal with the output of the user’s command.
rubocop:disable Metrics/MethodLength
42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/wavefront-cli/display/base.rb', line 42 def run(method) if method == 'do_list' run_list elsif method == 'do_search' run_search elsif respond_to?("#{method}_brief") && ![:long] send("#{method}_brief") elsif respond_to?(method) send(method) else long_output end end |
#run_error(method) ⇒ Object
Display classes can provide a do_method_code() method, which handles <code> errors when running do_method(). (Code is 404 etc.)
104 105 106 107 108 109 |
# File 'lib/wavefront-cli/display/base.rb', line 104 def run_error(method) return unless respond_to?(method) send(method) exit 1 end |
#run_list ⇒ Object
Choose the correct list handler. The user can specifiy a long listing with the –long options.
60 61 62 63 64 65 66 67 68 69 |
# File 'lib/wavefront-cli/display/base.rb', line 60 def run_list if [:long] @data = filter_data(data, filter_fields_as_arr) if [:fields] do_list elsif [:fields] do_list_fields else do_list_brief end end |
#run_search ⇒ Object
Choose the correct search handler. The user can specifiy a long listing with the –long options.
86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/wavefront-cli/display/base.rb', line 86 def run_search if data.empty? puts 'No matches.' elsif [:long] do_search elsif [:fields] do_search_fields else do_search_brief end end |
#search_display_keys ⇒ Object
279 280 281 282 283 |
# File 'lib/wavefront-cli/display/base.rb', line 279 def search_display_keys ([search_identifier_key] + [:'<condition>'].map do |c| c.split(SEARCH_SPLIT, 2).first.to_sym end).uniq end |
#search_identifier_key ⇒ Object
Most objects refer to themselves by ‘id’. Some, like accounts, don’t. Override here.
288 289 290 |
# File 'lib/wavefront-cli/display/base.rb', line 288 def search_identifier_key :id end |
#time_formats(str) ⇒ String
How do we format a timestamp?
399 400 401 402 403 404 405 406 407 |
# File 'lib/wavefront-cli/display/base.rb', line 399 def time_formats(str) if str =~ /^\d{13}$/ ['%Q', HUMAN_TIME_FORMAT_MS] elsif str =~ /^\d{10}$/ ['%s', HUMAN_TIME_FORMAT] else raise ArgumentError end end |