wavefront-cli 8.5.0 → 9.0.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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +37 -0
  3. data/.github/workflows/test.yml +23 -0
  4. data/.rubocop.yml +10 -9
  5. data/HISTORY.md +15 -0
  6. data/README.md +4 -2
  7. data/lib/wavefront-cli/base.rb +2 -2
  8. data/lib/wavefront-cli/commands/.rubocop.yml +2 -13
  9. data/lib/wavefront-cli/commands/base.rb +10 -9
  10. data/lib/wavefront-cli/commands/derivedmetric.rb +1 -1
  11. data/lib/wavefront-cli/commands/metric.rb +3 -3
  12. data/lib/wavefront-cli/commands/metricspolicy.rb +33 -0
  13. data/lib/wavefront-cli/commands/query.rb +5 -5
  14. data/lib/wavefront-cli/commands/write.rb +12 -12
  15. data/lib/wavefront-cli/config.rb +4 -4
  16. data/lib/wavefront-cli/constants.rb +2 -1
  17. data/lib/wavefront-cli/controller.rb +19 -15
  18. data/lib/wavefront-cli/display/base.rb +3 -2
  19. data/lib/wavefront-cli/display/metricspolicy.rb +15 -0
  20. data/lib/wavefront-cli/display/printer/long.rb +11 -13
  21. data/lib/wavefront-cli/display/printer/sparkline.rb +3 -3
  22. data/lib/wavefront-cli/display/query.rb +1 -1
  23. data/lib/wavefront-cli/display/write.rb +2 -1
  24. data/lib/wavefront-cli/event.rb +2 -2
  25. data/lib/wavefront-cli/event_store.rb +2 -2
  26. data/lib/wavefront-cli/exception.rb +21 -0
  27. data/lib/wavefront-cli/exception_handler.rb +8 -1
  28. data/lib/wavefront-cli/helpers/load_file.rb +2 -2
  29. data/lib/wavefront-cli/maintenancewindow.rb +1 -1
  30. data/lib/wavefront-cli/metricspolicy.rb +42 -0
  31. data/lib/wavefront-cli/opt_handler.rb +3 -4
  32. data/lib/wavefront-cli/output/csv/query.rb +2 -2
  33. data/lib/wavefront-cli/output/hcl/dashboard.rb +6 -6
  34. data/lib/wavefront-cli/output/hcl/stdlib/array.rb +1 -1
  35. data/lib/wavefront-cli/output/wavefront/query.rb +7 -7
  36. data/lib/wavefront-cli/query.rb +1 -1
  37. data/lib/wavefront-cli/settings.rb +3 -4
  38. data/lib/wavefront-cli/stdlib/string.rb +5 -5
  39. data/lib/wavefront-cli/usage.rb +1 -1
  40. data/lib/wavefront-cli/version.rb +1 -1
  41. data/lib/wavefront-cli/write.rb +14 -18
  42. data/spec/.rubocop.yml +2 -17
  43. data/spec/constants.rb +4 -5
  44. data/spec/support/command_base.rb +12 -0
  45. data/spec/support/minitest_assertions.rb +15 -11
  46. data/spec/support/output_tester.rb +2 -2
  47. data/spec/support/supported_commands.rb +3 -1
  48. data/spec/test_mixins/import.rb +2 -2
  49. data/spec/test_mixins/search.rb +9 -7
  50. data/spec/test_mixins/set.rb +1 -1
  51. data/spec/wavefront-cli/account_spec.rb +6 -4
  52. data/spec/wavefront-cli/alert_spec.rb +29 -6
  53. data/spec/wavefront-cli/commands/base_spec.rb +4 -4
  54. data/spec/wavefront-cli/commands/config_spec.rb +3 -3
  55. data/spec/wavefront-cli/config_spec.rb +3 -3
  56. data/spec/wavefront-cli/controller_spec.rb +4 -0
  57. data/spec/wavefront-cli/dashboard_spec.rb +1 -1
  58. data/spec/wavefront-cli/derivedmetric_spec.rb +9 -7
  59. data/spec/wavefront-cli/display/printer/long_spec.rb +5 -3
  60. data/spec/wavefront-cli/display/printer/terse_spec.rb +1 -1
  61. data/spec/wavefront-cli/event_spec.rb +14 -11
  62. data/spec/wavefront-cli/event_store_spec.rb +16 -12
  63. data/spec/wavefront-cli/externallink_spec.rb +5 -3
  64. data/spec/wavefront-cli/maintenancewindow_spec.rb +25 -19
  65. data/spec/wavefront-cli/message_spec.rb +3 -3
  66. data/spec/wavefront-cli/metricspolicy_spec.rb +30 -0
  67. data/spec/wavefront-cli/opt_handler_spec.rb +4 -4
  68. data/spec/wavefront-cli/output/helpers.rb +1 -1
  69. data/spec/wavefront-cli/proxy_spec.rb +1 -1
  70. data/spec/wavefront-cli/query_spec.rb +1 -1
  71. data/spec/wavefront-cli/role_spec.rb +4 -3
  72. data/spec/wavefront-cli/serviceaccount_spec.rb +7 -7
  73. data/spec/wavefront-cli/stdlib/string_spec.rb +3 -1
  74. data/spec/wavefront-cli/usage_spec.rb +1 -1
  75. data/spec/wavefront-cli/{write_spec.rb → write_class_spec.rb} +1 -14
  76. data/wavefront-cli.gemspec +13 -12
  77. metadata +72 -146
  78. data/.travis.yml +0 -20
  79. data/spec/spec_helper.rb +0 -113
@@ -13,7 +13,8 @@ module WavefrontDisplay
13
13
  def do_point
14
14
  @not_sent = data['rejected'] + data['unsent']
15
15
  report unless nothing_to_say?
16
- exit not_sent.zero? ? 0 : 1
16
+
17
+ raise unless not_sent.zero?
17
18
  end
18
19
 
19
20
  def nothing_to_say?
@@ -38,7 +38,7 @@ module WavefrontCli
38
38
  def do_show
39
39
  events = state.list
40
40
 
41
- if events.size.zero?
41
+ if events.empty?
42
42
  puts 'No open events.'
43
43
  else
44
44
  events.sort.reverse_each { |e| puts e.basename }
@@ -94,7 +94,7 @@ module WavefrontCli
94
94
  end
95
95
 
96
96
  def window_start
97
- parse_time((options[:start] || Time.now - 600), true)
97
+ parse_time((options[:start] || (Time.now - 600)), true)
98
98
  end
99
99
 
100
100
  def window_end
@@ -41,7 +41,7 @@ module WavefrontCli
41
41
  end
42
42
 
43
43
  def event_file(id)
44
- id =~ /^\d{13}:.+/ ? dir + id : nil
44
+ /^\d{13}:.+/.match?(id) ? dir + id : nil
45
45
  end
46
46
 
47
47
  # We can override the temp directory with the WF_EVENT_STATE_DIR env var.
@@ -70,7 +70,7 @@ module WavefrontCli
70
70
  def event(id)
71
71
  if !id
72
72
  pop_event!
73
- elsif id =~ /^\d{13}:.+:\d+/
73
+ elsif /^\d{13}:.+:\d+/.match?(id)
74
74
  id
75
75
  else
76
76
  pop_event!(id)
@@ -7,26 +7,47 @@ module WavefrontCli
7
7
  #
8
8
  class Exception
9
9
  class CredentialError < RuntimeError; end
10
+
10
11
  class MandatoryValue < RuntimeError; end
12
+
11
13
  class ConfigFileNotFound < IOError; end
14
+
12
15
  class FileNotFound < IOError; end
16
+
13
17
  class ImpossibleSearch < RuntimeError; end
18
+
14
19
  class InsufficientData < RuntimeError; end
20
+
15
21
  class InvalidInput < RuntimeError; end
22
+
16
23
  class InvalidQuery < RuntimeError; end
24
+
17
25
  class InvalidValue < RuntimeError; end
26
+
18
27
  class ProfileExists < RuntimeError; end
28
+
19
29
  class ProfileNotFound < RuntimeError; end
30
+
20
31
  class SystemError < RuntimeError; end
32
+
21
33
  class UnhandledCommand < RuntimeError; end
34
+
22
35
  class UnparseableInput < RuntimeError; end
36
+
23
37
  class UnparseableResponse < RuntimeError; end
38
+
24
39
  class UnparseableSearchPattern < RuntimeError; end
40
+
25
41
  class UnsupportedFileFormat < RuntimeError; end
42
+
26
43
  class UnsupportedNoop < RuntimeError; end
44
+
27
45
  class UnsupportedOperation < RuntimeError; end
46
+
28
47
  class UnsupportedOutput < RuntimeError; end
48
+
29
49
  class UserGroupNotFound < RuntimeError; end
50
+
30
51
  class UserError < RuntimeError; end
31
52
  end
32
53
  end
@@ -8,6 +8,7 @@ module WavefrontCli
8
8
  # rubocop:disable Metrics/MethodLength
9
9
  # rubocop:disable Metrics/AbcSize
10
10
  # rubocop:disable Metrics/CyclomaticComplexity
11
+ # rubocop:disable Metrics/PerceivedComplexity
11
12
  def exception_handler(exception)
12
13
  case exception
13
14
  when WavefrontCli::Exception::UnhandledCommand
@@ -18,7 +19,8 @@ module WavefrontCli
18
19
  abort "\nOperation aborted at user request."
19
20
  when WavefrontCli::Exception::ConfigFileNotFound
20
21
  abort "Configuration file #{exception}' not found."
21
- when WavefrontCli::Exception::CredentialError
22
+ when WavefrontCli::Exception::CredentialError,
23
+ Wavefront::Exception::CredentialError
22
24
  handle_missing_credentials(exception)
23
25
  when WavefrontCli::Exception::MandatoryValue
24
26
  abort 'A value must be supplied.'
@@ -26,6 +28,8 @@ module WavefrontCli
26
28
  abort 'Connection timed out.'
27
29
  when Wavefront::Exception::InvalidPermission
28
30
  abort "'#{exception}' is not a valid Wavefront permission."
31
+ when Wavefront::Exception::InvalidTimestamp
32
+ abort "'#{exception}' is not a parseable time."
29
33
  when Wavefront::Exception::InvalidUserGroupId
30
34
  abort "'#{exception}' is not a valid user group ID."
31
35
  when Wavefront::Exception::InvalidAccountId
@@ -38,6 +42,8 @@ module WavefrontCli
38
42
  abort "'#{exception}' is not a valid API token ID."
39
43
  when Wavefront::Exception::InvalidIngestionPolicyId
40
44
  abort "'#{exception}' is not a valid ingestion policy ID."
45
+ when Wavefront::Exception::InvalidVersion
46
+ abort "'#{exception}' is not a valid version."
41
47
  when WavefrontCli::Exception::InvalidValue
42
48
  abort "Invalid value for #{exception}."
43
49
  when WavefrontCli::Exception::ProfileExists
@@ -80,6 +86,7 @@ module WavefrontCli
80
86
  abort
81
87
  end
82
88
  end
89
+ # rubocop:enable Metrics/PerceivedComplexity
83
90
  # rubocop:enable Metrics/MethodLength
84
91
  # rubocop:enable Metrics/AbcSize
85
92
  # rubocop:enable Metrics/CyclomaticComplexity
@@ -40,11 +40,11 @@ module WavefrontCli
40
40
  private
41
41
 
42
42
  def load_json(file)
43
- read_json(IO.read(file))
43
+ read_json(File.read(file))
44
44
  end
45
45
 
46
46
  def load_yaml(file)
47
- read_yaml(IO.read(file))
47
+ read_yaml(File.read(file))
48
48
  end
49
49
 
50
50
  # Read STDIN and return a Ruby object, assuming that STDIN is
@@ -27,7 +27,7 @@ module WavefrontCli
27
27
 
28
28
  [%i[CustomerTags atag], %i[HostTags htag],
29
29
  %i[HostNames host]].each do |key, opt|
30
- k = ('relevant' + key.to_s).to_sym
30
+ k = "relevant#{key}".to_sym
31
31
  body[k] = options[opt] unless options[opt].empty?
32
32
  end
33
33
 
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wavefront-sdk/support/mixins'
4
+ require_relative 'base'
5
+ require_relative 'helpers/load_file'
6
+
7
+ module WavefrontCli
8
+ #
9
+ # CLI coverage for the metricspolicy part of the v2 'usage' API.
10
+ #
11
+ class MetricsPolicy < WavefrontCli::Base
12
+ def do_describe
13
+ wf.describe(options[:version])
14
+ end
15
+
16
+ def do_history
17
+ wf.history(options[:offset] || 0, options[:limit] || 100)
18
+ end
19
+
20
+ def do_revert
21
+ wf.revert(options[:'<version>'])
22
+ end
23
+
24
+ def do_update
25
+ raw = WavefrontCli::Helper::LoadFile.new(options[:'<file>']).load
26
+ rules = process_update(raw)
27
+ wf.update(policyRules: rules)
28
+ end
29
+
30
+ # It looks like the API expects arrays of ID strings for accounts, groups,
31
+ # and roles, but when you export one, those fields are objects with name
32
+ # and ID.
33
+ #
34
+ def process_update(raw)
35
+ raw[:policyRules].tap do |rule|
36
+ rule[:accounts] = rule[:accounts].map { |r| r[:id] }
37
+ rule[:userGroups] = rule[:userGroups].map { |r| r[:id] }
38
+ rule[:roles] = rule[:roles].map { |r| r[:id] }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -29,7 +29,7 @@ module WavefrontCli
29
29
 
30
30
  def initialize(cli_opts = {})
31
31
  cred_opts = setup_cred_opts(cli_opts)
32
- cli_opts.reject! { |_k, v| v.nil? }
32
+ cli_opts.compact!
33
33
  @opts = DEFAULT_OPTS.merge(load_profile(cred_opts)).merge(cli_opts)
34
34
  rescue WavefrontCli::Exception::ConfigFileNotFound => e
35
35
  abort "Configuration file '#{e}' not found."
@@ -43,11 +43,10 @@ module WavefrontCli
43
43
  # constructor.
44
44
  # @param cli_opts [Hash] options from docopt, which may include
45
45
  # the location of the config file and the stanza within it
46
- # @return [Hash] keys are none, one, or both of :file and
47
- # :profile
46
+ # @return [Hash] keys are none, one, or both of :file and :profile
48
47
  #
49
48
  def setup_cred_opts(cli_opts)
50
- cred_opts = { raise_on_no_profile: true }
49
+ cred_opts = cli_opts[:config] ? { raise_on_no_profile: true } : {}
51
50
 
52
51
  if cli_opts[:config]
53
52
  cred_opts[:file] = Pathname.new(cli_opts[:config])
@@ -32,7 +32,7 @@ module WavefrontCsvOutput
32
32
  def raw_output
33
33
  resp.each_with_object([]) do |point, a|
34
34
  point[:points].each do |p|
35
- a.<< csv_format(options[:'<metric>'],
35
+ a << csv_format(options[:'<metric>'],
36
36
  p[:value],
37
37
  p[:timestamp],
38
38
  options[:host],
@@ -48,7 +48,7 @@ module WavefrontCsvOutput
48
48
 
49
49
  resp[:timeseries].each_with_object([]) do |ts, a|
50
50
  ts[:data].each do |point|
51
- a.<< csv_format(ts[:label],
51
+ a << csv_format(ts[:label],
52
52
  point[1],
53
53
  point[0],
54
54
  ts[:host],
@@ -32,19 +32,19 @@ module WavefrontHclOutput
32
32
  # @return [String] HCL list of vals
33
33
  #
34
34
  def listmaker(vals, method)
35
- vals.each_with_object([]) { |v, a| a.<< send(method, v) }.to_hcl_list
35
+ vals.each_with_object([]) { |v, a| a << send(method, v) }.to_hcl_list
36
36
  end
37
37
 
38
38
  def vhandle_sections(vals)
39
39
  vals.each_with_object([]) do |section, a|
40
- a.<< ("name = \"#{section[:name]}\"\n row = " +
40
+ a << ("name = \"#{section[:name]}\"\n row = " +
41
41
  handle_rows(section[:rows])).braced(4)
42
42
  end.to_hcl_list
43
43
  end
44
44
 
45
45
  def handle_rows(rows)
46
46
  rows.each_with_object([]) do |row, a|
47
- a.<< ('chart = ' + handle_charts(row[:charts]).to_s).braced(8)
47
+ a << "chart = #{handle_charts(row[:charts])}".braced(8)
48
48
  end.to_hcl_list
49
49
  end
50
50
 
@@ -58,10 +58,10 @@ module WavefrontHclOutput
58
58
  lines = chart.each_with_object([]) do |(k, v), a|
59
59
  next unless fields.include?(k)
60
60
 
61
- a.<< format('%<key>s = %<value>s', key: k, value: quote_value(v))
61
+ a << format('%<key>s = %<value>s', key: k, value: quote_value(v))
62
62
  end
63
63
 
64
- lines.<< "source = #{handle_sources(chart[:sources])}"
64
+ lines << "source = #{handle_sources(chart[:sources])}"
65
65
  lines.to_hcl_obj(10)
66
66
  end
67
67
 
@@ -75,7 +75,7 @@ module WavefrontHclOutput
75
75
 
76
76
  k = 'queryBuilderEnabled' if k == 'querybuilderEnabled'
77
77
 
78
- a.<< format('%<key>s = %<value>s',
78
+ a << format('%<key>s = %<value>s',
79
79
  key: k.to_snake,
80
80
  value: quote_value(v))
81
81
  end.to_hcl_obj(14)
@@ -9,7 +9,7 @@ class Array
9
9
  # @return [String]
10
10
  #
11
11
  def to_hcl_list
12
- '[' + join(',') + ']'
12
+ "[#{join(',')}]"
13
13
  end
14
14
 
15
15
  # Turn an array into a string which represents an HCL object
@@ -20,11 +20,11 @@ module WavefrontWavefrontOutput
20
20
  def raw_output
21
21
  resp.each_with_object('') do |point, a|
22
22
  point[:points].each do |p|
23
- a.<< wavefront_format(options[:'<metric>'],
24
- p[:value],
25
- p[:timestamp],
26
- options[:host],
27
- point[:tags]) + "\n"
23
+ a << "#{wavefront_format(options[:'<metric>'],
24
+ p[:value],
25
+ p[:timestamp],
26
+ options[:host],
27
+ point[:tags])}\n"
28
28
  end
29
29
  end
30
30
  end
@@ -34,7 +34,7 @@ module WavefrontWavefrontOutput
34
34
 
35
35
  resp[:timeseries].each_with_object([]) do |ts, a|
36
36
  ts[:data].each do |point|
37
- a.<< wavefront_format(ts[:label],
37
+ a << wavefront_format(ts[:label],
38
38
  point[1],
39
39
  point[0],
40
40
  ts[:host],
@@ -46,7 +46,7 @@ module WavefrontWavefrontOutput
46
46
  def wavefront_format(path, value, timestamp, source, tags = nil)
47
47
  arr = [path, value, timestamp, format('source=%<source>s',
48
48
  source: source)]
49
- arr.<< tags.to_wf_tag if tags && !tags.empty?
49
+ arr << tags.to_wf_tag if tags && !tags.empty?
50
50
  arr.join(' ')
51
51
  end
52
52
  end
@@ -126,7 +126,7 @@ module WavefrontCli
126
126
  end
127
127
  end
128
128
 
129
- def handle_errcode_404(_status)
129
+ def handle_errcode404(_status)
130
130
  'Perhaps metric does not exist for given host.'
131
131
  end
132
132
  end
@@ -7,6 +7,8 @@ module WavefrontCli
7
7
  # CLI coverage for the v2 'settings' API.
8
8
  #
9
9
  class Settings < WavefrontCli::Base
10
+ JOBS = %w[invitePermissions defaultUserGroups].freeze
11
+
10
12
  def do_list_permissions
11
13
  wf.permissions
12
14
  end
@@ -24,10 +26,7 @@ module WavefrontCli
24
26
  k, v = o.split('=', 2)
25
27
  next unless v && !v.empty?
26
28
 
27
- if %w[invitePermissions defaultUserGroups].include?(k)
28
- v = v.include?(',') ? v.split(',') : [v]
29
- end
30
-
29
+ v = v.include?(',') ? v.split(',') : [v] if JOBS.include?(k)
31
30
  a[k] = v
32
31
  end
33
32
 
@@ -10,7 +10,7 @@ class String
10
10
  # @param indent [Integer] size of hanging indent, in chars
11
11
  #
12
12
  def cmd_fold(twidth = TW, indent = 10)
13
- gsub(/(-\w) /, '\\1^').scan_line(twidth - 12).join("\n" + ' ' * indent)
13
+ gsub(/(-\w) /, '\\1^').scan_line(twidth - 12).join("\n#{' ' * indent}")
14
14
  .restored
15
15
  end
16
16
 
@@ -50,7 +50,7 @@ class String
50
50
  # undesirable line breaking. This puts it back
51
51
  #
52
52
  def restored
53
- tr('^', ' ').chomp("\n")
53
+ tr('^', ' ').chomp
54
54
  end
55
55
 
56
56
  # Fold long value lines in two-column output. The returned string
@@ -58,7 +58,7 @@ class String
58
58
  #
59
59
  def value_fold(indent = 0, twidth = TW)
60
60
  max_line_length = twidth - indent - 4
61
- scan_line(max_line_length).join("\n" + ' ' * indent)
61
+ scan_line(max_line_length).join("\n#{' ' * indent}")
62
62
  end
63
63
 
64
64
  # @param width [Integer] length of longest string (width of
@@ -94,7 +94,7 @@ class String
94
94
  #
95
95
  def to_snake
96
96
  gsub(/(.)([A-Z])/) do
97
- Regexp.last_match[1] + '_' + Regexp.last_match[2].downcase
97
+ "#{Regexp.last_match[1]}_#{Regexp.last_match[2].downcase}"
98
98
  end
99
99
  end
100
100
 
@@ -102,7 +102,7 @@ class String
102
102
 
103
103
  def indent_folded_lines(chunks, twidth, indent, prefix)
104
104
  chunks.join(' ').scan_line(twidth - indent - 5).map do |line|
105
- prefix + ' ' * indent + line
105
+ "#{prefix}#{' ' * indent}#{line}"
106
106
  end
107
107
  end
108
108
  end
@@ -18,7 +18,7 @@ module WavefrontCli
18
18
  end
19
19
 
20
20
  def default_start
21
- parse_time(Time.now - 60 * 60 * 24)
21
+ parse_time(Time.now - 86_400)
22
22
  end
23
23
  end
24
24
  end
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- WF_CLI_VERSION = '8.5.0'
3
+ WF_CLI_VERSION = '9.0.0'
@@ -74,8 +74,8 @@ module WavefrontCli
74
74
  end
75
75
  # rubocop:enable Metrics/AbcSize
76
76
 
77
- # Turn our user's representation of a distribution into one
78
- # which suits Wavefront. The SDK can do this for us.
77
+ # Turn our user's representation of a distribution into one which suits
78
+ # Wavefront. The SDK can do this for us.
79
79
  #
80
80
  def mk_dist
81
81
  xpanded = expand_dist(options[:'<val>'])
@@ -83,7 +83,11 @@ module WavefrontCli
83
83
  end
84
84
 
85
85
  def extra_options
86
- options[:using] ? { writer: options[:using] } : {}
86
+ if options[:using]
87
+ { writer: options[:using] }
88
+ else
89
+ { writer: :http }
90
+ end
87
91
  end
88
92
 
89
93
  # I chose to prioritise UI consistency over internal elegance
@@ -108,6 +112,7 @@ module WavefrontCli
108
112
  port: options[:port] || default_port,
109
113
  socket: options[:socket],
110
114
  endpoint: options[:endpoint],
115
+ agent: "wavefront-cli-#{WF_CLI_VERSION}",
111
116
  token: options[:token] }
112
117
  end
113
118
 
@@ -115,18 +120,9 @@ module WavefrontCli
115
120
  distribution? ? 40_000 : 2878
116
121
  end
117
122
 
123
+ # The SDK writer plugins validate the credentials they need
118
124
  def validate_opts
119
125
  validate_opts_file if options[:file]
120
-
121
- if options[:using] == 'unix'
122
- return true if options[:socket]
123
-
124
- raise(WavefrontCli::Exception::CredentialError, 'No socket path.')
125
- end
126
-
127
- return true if options[:proxy]
128
-
129
- raise(WavefrontCli::Exception::CredentialError, 'No proxy address.')
130
126
  end
131
127
 
132
128
  def validate_opts_file
@@ -167,7 +163,7 @@ module WavefrontCli
167
163
  #
168
164
  def process_input_file(data)
169
165
  data.each_with_object([]) do |l, a|
170
- a.<< process_line(l)
166
+ a << process_line(l)
171
167
  rescue WavefrontCli::Exception::UnparseableInput => e
172
168
  puts "Bad input. #{e.message}."
173
169
  next
@@ -375,7 +371,7 @@ module WavefrontCli
375
371
  end
376
372
 
377
373
  def format_string_is_all_valid_chars?(fmt)
378
- return true if fmt =~ /^[dmstTv]+$/
374
+ return true if /^[dmstTv]+$/.match?(fmt)
379
375
 
380
376
  raise(WavefrontCli::Exception::UnparseableInput,
381
377
  'unsupported field in format string')
@@ -426,17 +422,17 @@ module WavefrontCli
426
422
  #
427
423
  def valid_timestamp?(timestamp)
428
424
  (timestamp.is_a?(Integer) ||
429
- timestamp.is_a?(String) && timestamp.match(/^\d+$/)) &&
425
+ (timestamp.is_a?(String) && timestamp.match(/^\d+$/))) &&
430
426
  timestamp.to_i > 946_684_800 &&
431
427
  timestamp.to_i < (Time.now.to_i + 31_557_600)
432
428
  end
433
429
 
434
430
  def setup_fmt(fmt)
435
- @fmt = fmt.split('')
431
+ @fmt = fmt.chars
436
432
  end
437
433
 
438
434
  def load_data(file)
439
- IO.read(file)
435
+ File.read(file)
440
436
  rescue StandardError
441
437
  raise WavefrontCli::Exception::FileNotFound
442
438
  end
data/spec/.rubocop.yml CHANGED
@@ -1,23 +1,8 @@
1
1
  ---
2
- AllCops:
3
- NewCops: enable
2
+ inherit_from:
3
+ - ../.rubocop.yml
4
4
 
5
5
  Metrics/MethodLength:
6
6
  Max: 30
7
-
8
7
  Metrics/AbcSize:
9
8
  Max: 45
10
-
11
- Metrics/ClassLength:
12
- Max: 300
13
-
14
- # Is nothing sacred?
15
- Layout/LineLength:
16
- Max: 80
17
-
18
- Style/IfUnlessModifier:
19
- Enabled: false # because it wants to make lines >80 chars
20
- Style/StringConcatenation:
21
- Enabled: false
22
- Style/OptionalBooleanParameter:
23
- Enabled: false
data/spec/constants.rb CHANGED
@@ -12,10 +12,9 @@ TW = 80
12
12
 
13
13
  ENDPOINT = 'metrics.wavefront.com'
14
14
  TOKEN = '0123456789-ABCDEF'
15
- RES_DIR = ROOT + 'spec' + 'wavefront-cli' + 'resources'
16
- CF = RES_DIR + 'wavefront.conf'
15
+ RES_DIR = ROOT.join('spec', 'wavefront-cli', 'resources')
16
+ CF = RES_DIR.join('wavefront.conf')
17
17
  CF_VAL = IniFile.load(CF)
18
- JSON_POST_HEADERS = {
19
- 'Content-Type': 'application/json', Accept: 'application/json'
20
- }.freeze
18
+ JSON_POST_HEADERS = { 'Content-Type': 'application/json',
19
+ Accept: 'application/json' }.freeze
21
20
  TEE_ZERO = Time.now.freeze
@@ -9,11 +9,13 @@ require_relative '../../lib/wavefront-cli/controller'
9
9
  # commands.
10
10
  #
11
11
  class EndToEndTest < MiniTest::Test
12
+ attr_accessor :single_perm
12
13
  attr_reader :wf
13
14
 
14
15
  def setup
15
16
  before_setup if respond_to?(:before_setup)
16
17
  @wf = WavefrontCliController
18
+ @single_perm = false
17
19
  end
18
20
 
19
21
  def api_path
@@ -79,4 +81,14 @@ class EndToEndTest < MiniTest::Test
79
81
  { status: { result: 'OK', message: '', code: 200 },
80
82
  items: [] }.to_json
81
83
  end
84
+
85
+ def blank_envvars
86
+ %w[WAVEFRONT_ENDPOINT WAVEFRONT_PROXY WAVEFRONT_TOKEN].each do |v|
87
+ ENV[v] = nil
88
+ end
89
+ end
90
+
91
+ def config?
92
+ Pathname.new(Dir.home).join('.wavefront').exist?
93
+ end
82
94
  end
@@ -147,10 +147,13 @@ module Minitest
147
147
  end
148
148
 
149
149
  def assert_cmd_posts(command, api_path, payload = 'null',
150
- response = dummy_response)
150
+ response = nil, extra_headers = {})
151
+ response ||= dummy_response
151
152
  all_permutations do |p|
152
153
  assert_posts("https://#{p[:endpoint]}#{api_path}",
153
- mk_headers(p[:token]), payload, response) do
154
+ mk_headers(p[:token], extra_headers),
155
+ payload,
156
+ response) do
154
157
  wf.new("#{cmd_word} #{command} #{p[:cmdline]}".split)
155
158
  end
156
159
  end
@@ -166,7 +169,7 @@ module Minitest
166
169
  end
167
170
 
168
171
  def assert_cmd_deletes(command, api_path, response = dummy_response)
169
- permutations.each do |p|
172
+ all_permutations do |p|
170
173
  assert_deletes("https://#{p[:endpoint]}#{api_path}",
171
174
  mk_headers(p[:token]), response) do
172
175
  wf.new("#{cmd_word} #{command} #{p[:cmdline]}".split)
@@ -188,13 +191,14 @@ module Minitest
188
191
  assert_empty(err)
189
192
  end
190
193
 
191
- # Run tests with all available permutations. We'll always need
192
- # to mock out display, unless we don't, when even if we do, it
193
- # won't matter.
194
+ # Run tests with all available permutations, unless the single_perm class
195
+ # variable is set. This lets us run tests faster by running fewer (but
196
+ # still a good random selection) and lets us run tests which must only be
197
+ # run once, like tests which pop stuff off the event stack.
194
198
  #
195
199
  def all_permutations
196
200
  perms = permutations
197
- perms = [perms[2]]
201
+ perms = perms.shuffle.take(1) if @single_perm || ENV['FAST_TESTS']
198
202
 
199
203
  perms.each do |p|
200
204
  yield(p)
@@ -213,11 +217,11 @@ module Minitest
213
217
 
214
218
  private
215
219
 
216
- def mk_headers(token = nil)
217
- { 'Accept': /.*/,
220
+ def mk_headers(token = nil, extra_headers = {})
221
+ { Accept: /.*/,
218
222
  'Accept-Encoding': /.*/,
219
- 'Authorization': 'Bearer ' + (token || '0123456789-ABCDEF'),
220
- 'User-Agent': "wavefront-cli-#{WF_CLI_VERSION}" }
223
+ Authorization: "Bearer #{token || '0123456789-ABCDEF'}",
224
+ 'User-Agent': "wavefront-cli-#{WF_CLI_VERSION}" }.merge(extra_headers)
221
225
  end
222
226
 
223
227
  # Every command we simulate running is done under the following
@@ -14,7 +14,7 @@ class OutputTester
14
14
  # @return [Object] canned raw responses used to test outputs
15
15
  #
16
16
  def load_input(file, only_items = true)
17
- ret = JSON.parse(IO.read(RES_DIR + 'display' + file),
17
+ ret = JSON.parse(File.read(RES_DIR.join('display', file)),
18
18
  symbolize_names: true)
19
19
  only_items ? ret[:items] : ret
20
20
  end
@@ -23,7 +23,7 @@ class OutputTester
23
23
  # @return [String]
24
24
  #
25
25
  def load_expected(file)
26
- IO.read(RES_DIR + 'display' + file)
26
+ File.read(RES_DIR.join('display', file))
27
27
  end
28
28
 
29
29
  def in_and_out(input, expected, only_items = true)