wavefront-cli 4.0.2 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83528e35b66e2a098928edb63b4f62cf4f730153caf886e8d2132dd8ef870340
4
- data.tar.gz: 9a6affc13f2b2fc1c41052abbd25dae47c2412a7bd70b39ec84ab8516ee748fa
3
+ metadata.gz: 48f9a11ef858f502c05d4c4d89080a31267f70d96430e88e44deba5b2f929015
4
+ data.tar.gz: a1bbc741a8379fb2a5783688a858b8c12b5d020a1501d58478042fc303ca43c3
5
5
  SHA512:
6
- metadata.gz: 46710487da70d0ea78ec7ba703b608b634a80d8b837b0ac91d0f4b9efad7a36ede6365060eb3f25455f56fbbdfd55b015a92f87c5c684af86e32f77ed00b038e
7
- data.tar.gz: d7527a3814e9b2cc8fe1ba1f49fa294122406442e2c5c50ecdafd0f2b6a4a975a2c0c22b74fb01cb5a9379e07977b421d3a526b070714120d2ccfb64f0e59110
6
+ metadata.gz: 759172c664ff1b81f2e199afceb052a61f31f4c91b7f72ea69ad5e511dc19d7397d9731d7e03269d75b88bd3baa52bfedc3bc289c166a84b590fb71ea9bc7a11
7
+ data.tar.gz: 5c7a9545f5ea086dce5bc02588ddf678ebad99321e55c68026a9e12ad0645b5a4a0bffcffac155ca238ad79370cd00cf146bd8033780f83dfabe2d7322b6c378
data/HISTORY.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.1.0 (27/06/2019)
4
+ * Add `dump` subcommand for all importable object types. Produces
5
+ JSON or YAML output.
6
+ * Allow batch importing of objects. Works with files produced by
7
+ `dump` subcommand, or by manually creating a JSON or YAML array of
8
+ objects. Batch imports are automatically detected by the `import`
9
+ subcommand.
10
+
3
11
  ## 4.0.2 (20/06/2019)
4
12
  * Allow importing of dashboards which have a URL but not an ID.
5
13
 
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017-2018, Sysdef Ltd
1
+ Copyright (c) 2017-2019, Sysdef Ltd
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
data/README.md CHANGED
@@ -18,7 +18,7 @@ SDK](https://github.com/snltd/wavefront-sdk) and requires Ruby >=
18
18
  2.3. It has no "native extension" dependencies.
19
19
 
20
20
  For a far more comprehensive overview/tutorial, please read [this
21
- article](http://sysdef.xyz/post/2017-07-26-wavefront-cli).
21
+ article](https://sysdef.xyz/article/wavefront-cli).
22
22
 
23
23
  ```
24
24
  $ wf --help
@@ -11,7 +11,7 @@ module WavefrontCli
11
11
  include WavefrontCli::Mixin::Acl
12
12
 
13
13
  def import_fields
14
- %w[name condition minutes target severity displayExpression
14
+ %i[name condition minutes target severity displayExpression
15
15
  tags additionalInformation resolveAfterMinutes]
16
16
  end
17
17
 
@@ -128,8 +128,8 @@ module WavefrontCli
128
128
  import_fields.each_with_object({}) { |k, a| a[k.to_sym] = raw[k] }
129
129
  .tap do |ret|
130
130
 
131
- if raw.key?('resolveAfterMinutes')
132
- ret[:resolveMinutes] = raw['resolveAfterMinutes']
131
+ if raw.key?(:resolveAfterMinutes)
132
+ ret[:resolveMinutes] = raw[:resolveAfterMinutes]
133
133
  end
134
134
 
135
135
  if raw.key?('customerTagsWithCounts')
@@ -143,9 +143,10 @@ module WavefrontCli
143
143
  end
144
144
 
145
145
  # To allow a user to default to different output formats for
146
- # different object, we are able to define a format for each class.
147
- # instance, `alertformat` or `agentformat`. This method returns
148
- # such a string appropriate for the inheriting class.
146
+ # different object types, we are able to define a format for
147
+ # each class. instance, `alertformat` or `proxyformat`. This
148
+ # method returns such a symbol appropriate for the inheriting
149
+ # class.
149
150
  #
150
151
  # @return [Symbol] name of the option or config-file key which
151
152
  # sets the default output format for this class
@@ -164,25 +165,15 @@ module WavefrontCli
164
165
  # @raise WavefrontCli::Exception::UnhandledCommand if the
165
166
  # command does not match a `do_` method.
166
167
  #
167
- # rubocop:disable Metrics/AbcSize
168
168
  def dispatch
169
+ # Look through each deconstructed method name and see if the
170
+ # user supplied an option for each component. Call the first
171
+ # one that matches. The order will ensure we match
172
+ # "do_delete_tags" before we match "do_delete".
169
173
  #
170
- # Take a list of do_ methods, remove the 'do_' from their name,
171
- # and break them into arrays of '_' separated words.
172
- #
173
- m_list = methods.select { |m| m.to_s.start_with?('do_') }.map do |m|
174
- m.to_s.split('_')[1..-1]
175
- end
176
-
177
- # Sort that array of arrays by length, longest first. Then look
178
- # through each deconstructed method name and see if the user
179
- # supplied an option for each component. Call the first one that
180
- # matches. The order will ensure we match "do_delete_tags" before
181
- # we match "do_delete".
182
- #
183
- m_list.sort_by(&:length).reverse_each do |m|
184
- if m.reject { |w| options[w.to_sym] }.empty?
185
- method = (%w[do] + m).join('_')
174
+ method_word_list.reverse_each do |w_list|
175
+ if w_list.reject { |w| options[w.to_sym] }.empty?
176
+ method = name_of_do_method(w_list)
186
177
  return display(public_send(method), method)
187
178
  end
188
179
  end
@@ -193,7 +184,19 @@ module WavefrontCli
193
184
 
194
185
  raise WavefrontCli::Exception::UnhandledCommand
195
186
  end
196
- # rubocop:enable Metrics/AbcSize
187
+
188
+ def name_of_do_method(word_list)
189
+ (%w[do] + word_list).join('_')
190
+ end
191
+
192
+ # Take a list of do_ methods, remove the 'do_' from their name,
193
+ # and break them into arrays of '_' separated words. The array
194
+ # is sorted by length, longest first.
195
+ #
196
+ def method_word_list
197
+ do_methods = methods.select { |m| m.to_s.start_with?('do_') }
198
+ do_methods.map { |m| m.to_s.split('_')[1..-1] }.sort_by(&:length)
199
+ end
197
200
 
198
201
  # Display a Ruby object as JSON, YAML, or human-readable. We
199
202
  # provide a default method to format human-readable output, but
@@ -208,7 +211,6 @@ module WavefrontCli
208
211
  # @param method [String] the name of the method which produced
209
212
  # this output. Used to find a suitable humanize method.
210
213
  #
211
- # rubocop:disable Metrics/AbcSize
212
214
  def display(data, method)
213
215
  if no_api_response.include?(method)
214
216
  return display_no_api_response(data, method)
@@ -216,18 +218,22 @@ module WavefrontCli
216
218
 
217
219
  exit if options[:noop]
218
220
 
221
+ check_response_blocks(data)
222
+ status_error_handler(data, method)
223
+ handle_response(data.response, format_var, method)
224
+ end
225
+
226
+ def status_error_handler(data, method)
227
+ return if check_status(data.status)
228
+ handle_error(method, data.status.code) if format_var == :human
229
+ display_api_error(data.status)
230
+ end
231
+
232
+ def check_response_blocks(data)
219
233
  %i[status response].each do |b|
220
234
  abort "no #{b} block in API response" unless data.respond_to?(b)
221
235
  end
222
-
223
- unless check_status(data.status)
224
- handle_error(method, data.status.code) if format_var == :human
225
- display_api_error(data.status)
226
- end
227
-
228
- handle_response(data.response, format_var, method)
229
236
  end
230
- # rubocop:enable Metrics/AbcSize
231
237
 
232
238
  # Classes can provide methods which give the user information on
233
239
  # a given error code. They are named #handle_errcode_xxx, and
@@ -384,24 +390,51 @@ module WavefrontCli
384
390
  end
385
391
 
386
392
  # rubocop:disable Metrics/AbcSize
393
+ def do_dump
394
+ items = wf.list(ALL_PAGE_SIZE, :all).response.items
395
+
396
+ if options[:format] == 'yaml'
397
+ ok_exit items.to_yaml
398
+ elsif options[:format] == 'json'
399
+ ok_exit items.to_json
400
+ else
401
+ abort format("Dump format must be 'json' or 'yaml'. (Tried '%s')",
402
+ options[:format])
403
+ end
404
+ end
405
+ # rubocop:enable Metrics/AbcSize
406
+
387
407
  def do_import
388
408
  raw = load_file(options[:'<file>'])
389
- raw = preprocess_rawfile(raw) if respond_to?(:preprocess_rawfile)
409
+ errs = 0
390
410
 
391
- begin
392
- prepped = import_to_create(raw)
393
- rescue StandardError => e
394
- puts e if options[:debug]
395
- raise WavefrontCli::Exception::UnparseableInput
411
+ [raw].flatten.each do |obj|
412
+ resp = import_object(obj)
413
+ next if options[:noop]
414
+ errs += 1 unless resp.ok?
415
+ puts import_message(obj, resp)
396
416
  end
397
417
 
418
+ exit errs
419
+ end
420
+
421
+ def import_message(obj, resp)
422
+ format('%-15s %-10s %s',
423
+ obj[:id] || obj[:url],
424
+ resp.ok? ? 'IMPORTED' : 'FAILED',
425
+ resp.status.message)
426
+ end
427
+
428
+ def import_object(raw)
429
+ raw = preprocess_rawfile(raw) if respond_to?(:preprocess_rawfile)
430
+ prepped = import_to_create(raw)
431
+
398
432
  if options[:update]
399
433
  import_update(raw)
400
434
  else
401
435
  wf.create(prepped)
402
436
  end
403
437
  end
404
- # rubocop:enable Metrics/AbcSize
405
438
 
406
439
  def import_update(raw)
407
440
  wf.update(raw[:id], raw, false)
@@ -508,8 +541,11 @@ module WavefrontCli
508
541
  #
509
542
  def import_to_create(raw)
510
543
  raw.each_with_object({}) do |(k, v), a|
511
- a[k.to_sym] = v unless k == 'id'
544
+ a[k.to_sym] = v unless k == :id
512
545
  end
546
+ rescue StandardError => e
547
+ puts e if options[:debug]
548
+ raise WavefrontCli::Exception::UnparseableInput
513
549
  end
514
550
 
515
551
  # Return a detailed description of one item, if an ID has been
@@ -14,6 +14,7 @@ class WavefrontCommandAlert < WavefrontCommandBase
14
14
  "history #{CMN} [-o offset] [-L limit] <id>",
15
15
  "clone #{CMN} [-v version] <id>",
16
16
  "latest #{CMN} <id>",
17
+ "dump #{CMN}",
17
18
  "import #{CMN} [-u] <file>",
18
19
  "snooze #{CMN} [-T time] <id>",
19
20
  "set #{CMN} <key=value> <id>",
@@ -22,6 +22,7 @@ class WavefrontCommandCloudintegration < WavefrontCommandBase
22
22
  "undelete #{CMN} <id>",
23
23
  "enable #{CMN} <id>",
24
24
  "disable #{CMN} <id>",
25
+ "dump #{CMN}",
25
26
  "import #{CMN} [-u] <file>",
26
27
  "search #{CMN} [-al] [-o offset] [-L limit] <condition>..."]
27
28
  end
@@ -6,6 +6,7 @@ class WavefrontCommandDashboard < WavefrontCommandBase
6
6
  def _commands
7
7
  ["list #{CMN} [-alN] [-O fields] [-o offset] [-L limit]",
8
8
  "describe #{CMN} [-v version] <id>",
9
+ "dump #{CMN}",
9
10
  "import #{CMN} [-u] <file>",
10
11
  "set #{CMN} <key=value> <id>",
11
12
  "delete #{CMN} <id>",
@@ -20,6 +20,7 @@ class WavefrontCommandDerivedmetric < WavefrontCommandBase
20
20
  "describe #{CMN} [-v version] <id>",
21
21
  "create #{CMN} [-d description] [-T tag...] [-b] [-i interval] " \
22
22
  '[-r range] <name> <query>',
23
+ "dump #{CMN}",
23
24
  "import #{CMN} [-u] <file>",
24
25
  "set #{CMN} <key=value> <id>",
25
26
  "delete #{CMN} <id>",
@@ -21,6 +21,7 @@ class WavefrontCommandLink < WavefrontCommandBase
21
21
  "create #{CMN} [-m regex] [-s regex] [-p str=regex...] <name> " \
22
22
  '<description> <template>',
23
23
  "delete #{CMN} <id>",
24
+ "dump #{CMN}",
24
25
  "import #{CMN} [-u] <file>",
25
26
  "set #{CMN} <key=value> <id>",
26
27
  "search #{CMN} [-al] [-o offset] [-L limit] <condition>..."]
@@ -14,6 +14,7 @@ class WavefrontCommandNotificant < WavefrontCommandBase
14
14
  def _commands
15
15
  ["list #{CMN} [-al] [-O fields] [-o offset] [-L limit]",
16
16
  "describe #{CMN} <id>",
17
+ "dump #{CMN}",
17
18
  "import #{CMN} [-u] <file>",
18
19
  "delete #{CMN} <id>",
19
20
  "test #{CMN} <id>",
@@ -23,6 +23,7 @@ class WavefrontCommandSavedsearch < WavefrontCommandBase
23
23
  ["list #{CMN} [-al] [-O fields] [-o offset] [-L limit]",
24
24
  "describe #{CMN} <id>",
25
25
  "delete #{CMN} <id>",
26
+ "dump #{CMN}",
26
27
  "import #{CMN} [-u] <file>",
27
28
  "search #{CMN} [-al] [-o offset] [-L limit] <condition>..."]
28
29
  end
@@ -18,6 +18,7 @@ class WavefrontCommandUser < WavefrontCommandBase
18
18
  "invite #{CMN} [-m permission...] [-g group...] <id>",
19
19
  "set #{CMN} <key=value> <id>",
20
20
  "delete #{CMN} <user>...",
21
+ "dump #{CMN}",
21
22
  "import #{CMN} [-u] <file>",
22
23
  "groups #{CMN} <id>",
23
24
  "join #{CMN} <id> <group>...",
@@ -24,6 +24,7 @@ class WavefrontCommandUsergroup < WavefrontCommandBase
24
24
  "describe #{CMN} <id>",
25
25
  "create #{CMN} [-p permission...] <name>",
26
26
  "delete #{CMN} <id>",
27
+ "dump #{CMN}",
27
28
  "import #{CMN} [-u] <file>",
28
29
  "set #{CMN} <key=value> <id>",
29
30
  "users #{CMN} <id>",
@@ -7,6 +7,7 @@ class WavefrontCommandWebhook < WavefrontCommandBase
7
7
  ["list #{CMN} [-al] [-O fields] [-o offset] [-L limit]",
8
8
  "describe #{CMN} <id>",
9
9
  "delete #{CMN} <id>",
10
+ "dump #{CMN}",
10
11
  "import #{CMN} [-u] <file>",
11
12
  "set #{CMN} <key=value> <id>",
12
13
  "search #{CMN} [-al] [-o offset] [-L limit] <condition>..."]
@@ -23,6 +23,7 @@ class WavefrontCommandWindow < WavefrontCommandBase
23
23
  "close #{CMN} <id>",
24
24
  "extend #{CMN} (by|to) <time> <id>",
25
25
  "delete #{CMN} <id>",
26
+ "dump #{CMN}",
26
27
  "import #{CMN} [-u] <file>",
27
28
  "set #{CMN} <key=value> <id>",
28
29
  "search #{CMN} [-al] [-o offset] [-L limit] <condition>...",
@@ -1 +1 @@
1
- WF_CLI_VERSION = '4.0.2'.freeze
1
+ WF_CLI_VERSION = '4.1.0'.freeze
@@ -430,7 +430,7 @@ class CliMethodTest < MiniTest::Test
430
430
  end
431
431
 
432
432
  def import_tester(word, have_fields, do_not_have_fields = [])
433
- input = JSON.parse(IO.read(RES_DIR + 'imports' + "#{word}.json"))
433
+ input = wf.load_file(RES_DIR + 'imports' + "#{word}.json")
434
434
  x = wf.import_to_create(input)
435
435
  assert_instance_of(Hash, x)
436
436
  have_fields.each { |f| assert_includes(x.keys, f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wavefront-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.2
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Fisher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-20 00:00:00.000000000 Z
11
+ date: 2019-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docopt