wavefront-cli 8.5.0 → 9.0.0

Sign up to get free protection for your applications and to get access to all the features.
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)