wavefront-cli 6.1.0 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +34 -1
  3. data/HISTORY.md +17 -1
  4. data/README.md +2 -3
  5. data/lib/wavefront-cli/account.rb +119 -0
  6. data/lib/wavefront-cli/alert.rb +29 -0
  7. data/lib/wavefront-cli/base.rb +0 -2
  8. data/lib/wavefront-cli/commands/.rubocop.yml +34 -0
  9. data/lib/wavefront-cli/commands/account.rb +61 -0
  10. data/lib/wavefront-cli/commands/alert.rb +1 -0
  11. data/lib/wavefront-cli/commands/base.rb +1 -1
  12. data/lib/wavefront-cli/commands/query.rb +4 -1
  13. data/lib/wavefront-cli/commands/role.rb +44 -0
  14. data/lib/wavefront-cli/commands/spy.rb +0 -5
  15. data/lib/wavefront-cli/commands/usergroup.rb +7 -11
  16. data/lib/wavefront-cli/commands/write.rb +7 -2
  17. data/lib/wavefront-cli/controller.rb +5 -63
  18. data/lib/wavefront-cli/display/account.rb +122 -0
  19. data/lib/wavefront-cli/display/alert.rb +8 -0
  20. data/lib/wavefront-cli/display/base.rb +1 -1
  21. data/lib/wavefront-cli/display/cloudintegration.rb +3 -2
  22. data/lib/wavefront-cli/display/printer/long.rb +2 -1
  23. data/lib/wavefront-cli/display/role.rb +66 -0
  24. data/lib/wavefront-cli/display/settings.rb +1 -0
  25. data/lib/wavefront-cli/display/usergroup.rb +18 -14
  26. data/lib/wavefront-cli/exception_handler.rb +87 -0
  27. data/lib/wavefront-cli/output/hcl/base.rb +1 -1
  28. data/lib/wavefront-cli/query.rb +13 -7
  29. data/lib/wavefront-cli/role.rb +54 -0
  30. data/lib/wavefront-cli/serviceaccount.rb +0 -6
  31. data/lib/wavefront-cli/spy.rb +0 -8
  32. data/lib/wavefront-cli/usergroup.rb +8 -8
  33. data/lib/wavefront-cli/version.rb +1 -1
  34. data/lib/wavefront-cli/write.rb +28 -4
  35. data/spec/.rubocop.yml +34 -0
  36. data/spec/test_mixins/delete.rb +1 -2
  37. data/spec/wavefront-cli/account_spec.rb +303 -0
  38. data/spec/wavefront-cli/alert_spec.rb +28 -0
  39. data/spec/wavefront-cli/commands/write_spec.rb +1 -1
  40. data/spec/wavefront-cli/event_spec.rb +1 -1
  41. data/spec/wavefront-cli/output/csv/query_spec.rb +1 -1
  42. data/spec/wavefront-cli/output/wavefront/query_spec.rb +2 -2
  43. data/spec/wavefront-cli/query_spec.rb +20 -3
  44. data/spec/wavefront-cli/role_spec.rb +187 -0
  45. data/spec/wavefront-cli/serviceaccount_spec.rb +3 -3
  46. data/spec/wavefront-cli/usergroup_spec.rb +48 -43
  47. data/spec/wavefront-cli/write_spec.rb +44 -0
  48. data/wavefront-cli.gemspec +3 -3
  49. metadata +30 -27
  50. data/lib/wavefront-cli/commands/user.rb +0 -54
  51. data/lib/wavefront-cli/display/user.rb +0 -103
  52. data/lib/wavefront-cli/user.rb +0 -92
  53. data/spec/wavefront-cli/resources/responses/user-list.json +0 -1
  54. data/spec/wavefront-cli/user_spec.rb +0 -311
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WavefrontCli
4
+ #
5
+ # Handle fatal errors.
6
+ #
7
+ module ExceptionMixins
8
+ # rubocop:disable Metrics/MethodLength
9
+ # rubocop:disable Metrics/AbcSize
10
+ # rubocop:disable Metrics/CyclomaticComplexity
11
+ # rubocop:disable Metrics/PerceivedComplexity
12
+ def exception_handler(exception)
13
+ case exception
14
+ when WavefrontCli::Exception::UnhandledCommand
15
+ abort 'Fatal error. Unsupported command. Please open a Github issue.'
16
+ when WavefrontCli::Exception::InvalidInput
17
+ abort "Invalid input. #{exception.message}"
18
+ when Interrupt
19
+ abort "\nOperation aborted at user request."
20
+ when WavefrontCli::Exception::ConfigFileNotFound
21
+ abort "Configuration file #{exception}' not found."
22
+ when WavefrontCli::Exception::CredentialError
23
+ handle_missing_credentials(exception)
24
+ when WavefrontCli::Exception::MandatoryValue
25
+ abort 'A value must be supplied.'
26
+ when Wavefront::Exception::NetworkTimeout
27
+ abort 'Connection timed out.'
28
+ when Wavefront::Exception::InvalidPermission
29
+ abort "'#{exception}' is not a valid Wavefront permission."
30
+ when Wavefront::Exception::InvalidUserGroupId
31
+ abort "'#{exception}' is not a valid user group ID."
32
+ when Wavefront::Exception::InvalidAccountId
33
+ abort "'#{exception}' is not a valid system or user account ID."
34
+ when Wavefront::Exception::InvalidRoleId
35
+ abort "'#{exception}' is not a valid role ID."
36
+ when Wavefront::Exception::InvalidApiTokenId
37
+ abort "'#{exception}' is not a valid API token ID."
38
+ when Wavefront::Exception::InvalidIngestionPolicyId
39
+ abort "'#{exception}' is not a valid ingestion policy ID."
40
+ when WavefrontCli::Exception::InvalidValue
41
+ abort "Invalid value for #{exception}."
42
+ when WavefrontCli::Exception::ProfileExists
43
+ abort "Profile '#{exception}' already exists."
44
+ when WavefrontCli::Exception::ProfileNotFound
45
+ abort "Profile '#{exception}' not found."
46
+ when WavefrontCli::Exception::FileNotFound
47
+ abort 'File not found.'
48
+ when WavefrontCli::Exception::InsufficientData
49
+ abort "Insufficient data. #{exception.message}"
50
+ when WavefrontCli::Exception::InvalidQuery
51
+ abort "Invalid query. API message: '#{exception.message}'."
52
+ when WavefrontCli::Exception::SystemError
53
+ abort "Host system error. #{exception.message}"
54
+ when WavefrontCli::Exception::UnparseableInput
55
+ abort "Cannot parse input. #{exception.message}"
56
+ when WavefrontCli::Exception::UnparseableSearchPattern
57
+ abort 'Searches require a key, a value, and a match operator.'
58
+ when WavefrontCli::Exception::UnsupportedFileFormat
59
+ abort 'Unsupported file format.'
60
+ when WavefrontCli::Exception::UnsupportedOperation
61
+ abort "Unsupported operation.\n#{exception.message}"
62
+ when WavefrontCli::Exception::UnsupportedOutput
63
+ abort exception.message
64
+ when WavefrontCli::Exception::UnsupportedNoop
65
+ abort 'Multiple API call operations cannot be performed as no-ops.'
66
+ when WavefrontCli::Exception::UserGroupNotFound
67
+ abort "Cannot find user group '#{exception.message}'."
68
+ when Wavefront::Exception::UnsupportedWriter
69
+ abort "Unsupported writer '#{exception.message}'."
70
+ when WavefrontCli::Exception::UserError
71
+ abort "User error: #{exception.message}."
72
+ when WavefrontCli::Exception::ImpossibleSearch
73
+ abort 'Search on non-existent key. Please use a top-level field.'
74
+ when Wavefront::Exception::InvalidSamplingValue
75
+ abort 'Sampling rates must be between 0 and 0.05.'
76
+ else
77
+ warn "general error: #{exception}"
78
+ backtrace_message(exception)
79
+ abort
80
+ end
81
+ end
82
+ # rubocop:enable Metrics/MethodLength
83
+ # rubocop:enable Metrics/AbcSize
84
+ # rubocop:enable Metrics/PerceivedComplexity
85
+ # rubocop:enable Metrics/CyclomaticComplexity
86
+ end
87
+ end
@@ -92,7 +92,7 @@ module WavefrontHclOutput
92
92
  def quote_value(val)
93
93
  case val.class.to_s.to_sym
94
94
  when :String
95
- format('"%<value>s"', value: val.gsub(/\"/, '\"'))
95
+ format('"%<value>s"', value: val.gsub(/"/, '\"'))
96
96
  else
97
97
  val
98
98
  end
@@ -51,20 +51,26 @@ module WavefrontCli
51
51
 
52
52
  # @return [Hash] options for the SDK query method
53
53
  #
54
- # rubocop:disable Metrics/AbcSize
55
54
  def q_opts
55
+ basic_q_opts.tap do |o|
56
+ o[:n] = options[:name]
57
+ o[:p] = options[:points]
58
+ o[:view] = 'HISTOGRAM' if options[:histogramview]
59
+ o[:cached] = false if options[:nocache]
60
+ end.compact
61
+ end
62
+
63
+ # Every query gets these options. They're modified by q_opts
64
+ #
65
+ def basic_q_opts
56
66
  { autoEvents: options[:events],
57
67
  i: options[:inclusive],
58
68
  summarization: options[:summarize] || 'mean',
59
69
  listMode: true,
60
- strict: true,
70
+ strict: !options[:nostrict],
61
71
  includeObsoleteMetrics: options[:obsolete],
62
- sorted: true }.tap do |o|
63
- o[:n] = options[:name] if options[:name]
64
- o[:p] = options[:points] if options[:points]
65
- end
72
+ sorted: true }
66
73
  end
67
- # rubocop:enable Metrics/AbcSize
68
74
 
69
75
  # @return [Integer] start of query window. If one has been
70
76
  # given, that; if not, ten minutes ago
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module WavefrontCli
6
+ #
7
+ # CLI coverage for the v2 'role' API.
8
+ #
9
+ class Role < WavefrontCli::Base
10
+ alias do_permissions do_describe
11
+
12
+ def do_create
13
+ wf.create({ name: options[:'<name>'],
14
+ description: options[:description],
15
+ permissions: options[:permission] }.compact)
16
+ end
17
+
18
+ def do_accounts
19
+ things_with_role(:account, options[:'<id>'])
20
+ end
21
+
22
+ def do_groups
23
+ things_with_role(:usergroup, options[:'<id>'])
24
+ end
25
+
26
+ def do_give_to
27
+ wf.add_assignees(options[:'<id>'], options[:'<member>'])
28
+ end
29
+
30
+ def do_take_from
31
+ wf.remove_assignees(options[:'<id>'], options[:'<member>'])
32
+ end
33
+
34
+ def do_grant
35
+ wf.grant(options[:'<permission>'], Array(options[:'<id>']))
36
+ end
37
+
38
+ def do_revoke
39
+ wf.revoke(options[:'<permission>'], Array(options[:'<id>']))
40
+ end
41
+
42
+ private
43
+
44
+ # Search for objects of the given type with the given role
45
+ #
46
+ def things_with_role(thing, role)
47
+ require 'wavefront-sdk/search'
48
+ wfs = Wavefront::Search.new(mk_creds, mk_opts)
49
+ wfs.search(thing,
50
+ conds_to_query(["roles~#{role}"]),
51
+ limit: :all, sort_field: :id)
52
+ end
53
+ end
54
+ end
@@ -173,20 +173,14 @@ module WavefrontCli
173
173
 
174
174
  def validate_groups
175
175
  options[:group].each { |g| wf_usergroup_id?(g) }
176
- rescue Wavefront::Exception::InvalidUserGroupId => e
177
- raise e, 'Invalid usergroup ID'
178
176
  end
179
177
 
180
178
  def validate_tokens
181
179
  options[:usertoken].each { |t| wf_apitoken_id?(t) }
182
- rescue Wavefront::Exception::InvalidApiTokenId => e
183
- raise e, 'Invalid API token'
184
180
  end
185
181
 
186
182
  def validate_perms
187
183
  options[:permission].each { |p| wf_permission?(p) }
188
- rescue Wavefront::Exception::InvalidPermission => e
189
- raise e, 'Invalid permission'
190
184
  end
191
185
 
192
186
  def descriptive_name
@@ -42,14 +42,6 @@ module WavefrontCli
42
42
 
43
43
  private
44
44
 
45
- def require_sdk_class
46
- require 'wavefront-sdk/unstable/spy'
47
- end
48
-
49
- def _sdk_class
50
- 'Wavefront::Unstable::Spy'
51
- end
52
-
53
45
  def rate
54
46
  return 0.01 unless options[:rate]
55
47
 
@@ -12,27 +12,27 @@ module WavefrontCli
12
12
  end
13
13
 
14
14
  alias do_users do_describe
15
+ alias do_roles do_describe
15
16
  alias do_permissions do_describe
16
17
 
17
18
  def do_create
18
- wf.create(name: options[:'<name>'],
19
- permissions: options[:permission])
19
+ wf.create(name: options[:'<name>'], roleIDs: options[:roleid])
20
20
  end
21
21
 
22
- def do_add_user
22
+ def do_add_to
23
23
  wf.add_users_to_group(options[:'<id>'], options[:'<user>'])
24
24
  end
25
25
 
26
- def do_remove_user
26
+ def do_remove_from
27
27
  wf.remove_users_from_group(options[:'<id>'], options[:'<user>'])
28
28
  end
29
29
 
30
- def do_grant
31
- wf.grant(options[:'<permission>'], Array(options[:'<id>']))
30
+ def do_add_role
31
+ wf.add_roles_to_group(options[:'<id>'], options[:'<role>'])
32
32
  end
33
33
 
34
- def do_revoke
35
- wf.revoke(options[:'<permission>'], Array(options[:'<id>']))
34
+ def do_remove_role
35
+ wf.remove_roles_from_group(options[:'<id>'], options[:'<role>'])
36
36
  end
37
37
 
38
38
  def import_to_create(raw)
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- WF_CLI_VERSION = '6.1.0'
3
+ WF_CLI_VERSION = '7.1.0'
@@ -9,15 +9,16 @@ module WavefrontCli
9
9
  #
10
10
  class Write < Base
11
11
  attr_reader :fmt
12
+
12
13
  include Wavefront::Mixins
13
14
  SPLIT_PATTERN = /\s(?=(?:[^"]|"[^"]*")*$)/.freeze
14
15
 
15
16
  # rubocop:disable Metrics/AbcSize
16
- def do_point
17
+ def do_point(value = options[:'<value>'])
17
18
  tags = tags_to_hash(options[:tag])
18
19
 
19
20
  p = { path: options[:'<metric>'],
20
- value: options[:'<value>'].delete('\\').to_f }
21
+ value: sane_value(value) }
21
22
 
22
23
  p[:tags] = tags unless tags.empty?
23
24
  p[:source] = options[:host] if options[:host]
@@ -36,6 +37,31 @@ module WavefrontCli
36
37
  send_point(make_distribution_point(tags_to_hash(options[:tag])))
37
38
  end
38
39
 
40
+ def do_noise
41
+ loop do
42
+ do_point(random_value(options[:min] || -10, options[:max] || 10))
43
+ sleep(sleep_time)
44
+ end
45
+ end
46
+
47
+ def random_value(min, max)
48
+ return min if min == max
49
+
50
+ rand(max.to_f - min.to_f) + min.to_f
51
+ end
52
+
53
+ def sane_value(value)
54
+ return value if value.is_a?(Numeric)
55
+
56
+ raise WavefrontCli::Exception::InvalidValue unless value.is_a?(String)
57
+
58
+ value.delete('\\').to_f
59
+ end
60
+
61
+ def sleep_time
62
+ options[:interval] ? options[:interval].to_f : 1
63
+ end
64
+
39
65
  # rubocop:disable Metrics/AbcSize
40
66
  def make_distribution_point(tags)
41
67
  { path: options[:'<metric>'],
@@ -270,7 +296,6 @@ module WavefrontCli
270
296
  # @raise WavefrontCli::Exception::UnparseableInput if the line
271
297
  # doesn't look right
272
298
  #
273
- # rubocop:disable Metrics/CyclomaticComplexity
274
299
  # rubocop:disable Metrics/MethodLength
275
300
  # rubocop:disable Metrics/AbcSize
276
301
  def process_line(line)
@@ -293,7 +318,6 @@ module WavefrontCli
293
318
  end
294
319
  # rubocop:enable Metrics/AbcSize
295
320
  # rubocop:enable Metrics/MethodLength
296
- # rubocop:enable Metrics/CyclomaticComplexity
297
321
 
298
322
  # We can get tags from the file, from the -T option, or both.
299
323
  # Merge them, making the -T win if there is a collision.
@@ -14,3 +14,37 @@ Style/HashTransformKeys:
14
14
  Enabled: true
15
15
  Style/HashTransformValues:
16
16
  Enabled: true
17
+
18
+ # new compatabilities
19
+ Layout/EmptyLinesAroundAttributeAccessor:
20
+ Enabled: true
21
+ Layout/SpaceAroundMethodCallOperator:
22
+ Enabled: true
23
+ Lint/RaiseException:
24
+ Enabled: true
25
+ Lint/StructNewOverride:
26
+ Enabled: true
27
+ Style/ExponentialNotation:
28
+ Enabled: true
29
+ Style/SlicingWithRange:
30
+ Enabled: true
31
+ Lint/DeprecatedOpenSSLConstant:
32
+ Enabled: true
33
+ Lint/MixedRegexpCaptureTypes:
34
+ Enabled: true
35
+ Style/RedundantRegexpCharacterClass:
36
+ Enabled: true
37
+ Style/RedundantRegexpEscape:
38
+ Enabled: true
39
+ Style/AccessorGrouping:
40
+ Enabled: true
41
+ Style/BisectedAttrAccessor:
42
+ Enabled: true
43
+ Style/RedundantAssignment:
44
+ Enabled: true
45
+ Style/RedundantFetchBlock:
46
+ Enabled: true
47
+
48
+ # Is nothing sacred?
49
+ Layout/LineLength:
50
+ Max: 80
@@ -15,8 +15,7 @@ module WavefrontCliTest
15
15
 
16
16
  assert_noop(
17
17
  "delete #{id}",
18
- 'uri: DELETE https://default.wavefront.com/api/v2/' \
19
- "#{api_path}/#{id}"
18
+ "uri: DELETE https://default.wavefront.com/api/v2/#{api_path}/#{id}"
20
19
  )
21
20
 
22
21
  assert_abort_on_missing_creds("delete #{id}")
@@ -0,0 +1,303 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../support/command_base'
5
+ require_relative '../../lib/wavefront-cli/account'
6
+
7
+ # Ensure 'account' commands produce the correct API calls.
8
+ #
9
+ class AccountEndToEndTest < EndToEndTest
10
+ include WavefrontCliTest::List
11
+ include WavefrontCliTest::Delete
12
+ include WavefrontCliTest::Describe
13
+ include WavefrontCliTest::Search
14
+
15
+ def test_role_add_to
16
+ quietly do
17
+ assert_cmd_posts("role add to #{id} #{roles.join(' ')}",
18
+ "/api/v2/account/#{id}/addRoles",
19
+ roles.to_json)
20
+ end
21
+
22
+ assert_invalid_id("role add to #{invalid_id} #{roles.first}")
23
+ assert_invalid_id("role add to #{id} #{invalid_role}")
24
+ assert_abort_on_missing_creds("role add to #{id} #{roles.last}")
25
+ assert_usage("role add to #{roles.first}")
26
+ end
27
+
28
+ def test_role_remove_from
29
+ quietly do
30
+ assert_cmd_posts("role remove from #{id} #{roles.join(' ')}",
31
+ "/api/v2/account/#{id}/removeRoles",
32
+ roles.to_json)
33
+ end
34
+
35
+ assert_invalid_id("role remove from #{invalid_id} #{roles.first}")
36
+ assert_abort_on_missing_creds("role remove from #{id} #{roles.last}")
37
+ assert_usage("role remove from #{roles.first}")
38
+ end
39
+
40
+ def test_add_group_to
41
+ assert_repeated_output("Added '#{id}' to '#{groups.first}'.") do
42
+ assert_cmd_posts("group add to #{id} #{groups.first}",
43
+ "/api/v2/account/#{id}/addUserGroups",
44
+ [groups.first].to_json)
45
+ end
46
+
47
+ assert_invalid_id("group add to #{id} #{invalid_group}")
48
+ assert_invalid_id("group add to #{invalid_id} #{groups.first}")
49
+ assert_abort_on_missing_creds("group add to #{id} #{groups.last}")
50
+ assert_usage("group add to #{groups.first}")
51
+ end
52
+
53
+ def test_remove_group_from
54
+ assert_repeated_output("Removed '#{id}' from '#{groups.first}', " \
55
+ "'#{groups.last}'.") do
56
+ assert_cmd_posts("group remove from #{id} #{groups.join(' ')}",
57
+ "/api/v2/account/#{id}/removeUserGroups",
58
+ groups.to_json)
59
+ end
60
+
61
+ assert_invalid_id("group remove from #{id} #{invalid_group}")
62
+ assert_invalid_id("group remove from #{invalid_id} #{groups.first}")
63
+ assert_abort_on_missing_creds("group remove from #{id} #{groups.last}")
64
+ assert_usage("group remove from #{groups.first}")
65
+ end
66
+
67
+ def test_business_functions
68
+ quietly do
69
+ assert_cmd_gets("business functions #{id}",
70
+ "/api/v2/account/#{id}/businessFunctions")
71
+ end
72
+
73
+ assert_noop("business functions #{id}",
74
+ 'uri: GET https://default.wavefront.com/api/v2/account/' \
75
+ "#{id}/businessFunctions")
76
+ assert_invalid_id("business functions #{invalid_id}")
77
+ assert_abort_on_missing_creds("business functions #{id}")
78
+ assert_usage('business functions')
79
+ end
80
+
81
+ def test_grant_to
82
+ assert_repeated_output("Granted '#{permission}' to '#{id}'.") do
83
+ assert_cmd_posts("grant #{permission} to #{id}",
84
+ "/api/v2/account/grant/#{permission}",
85
+ [id].to_json)
86
+ end
87
+
88
+ assert_invalid_id("grant #{permission} to #{invalid_id}")
89
+ assert_abort_on_missing_creds("grant #{permission} to #{id}")
90
+ assert_usage("grant #{permission}")
91
+ end
92
+
93
+ def test_revoke_from
94
+ assert_repeated_output("Revoked '#{permission}' from '#{id}'.") do
95
+ assert_cmd_posts("revoke #{permission} from #{id}",
96
+ "/api/v2/account/revoke/#{permission}",
97
+ [id].to_json)
98
+ end
99
+
100
+ out, err = capture_io do
101
+ assert_raises(SystemExit) do
102
+ wf.new("account revoke #{invalid_permission} from #{id}".split)
103
+ end
104
+ end
105
+
106
+ assert_empty out
107
+ assert_equal("'made_up_permission' is not a valid Wavefront permission.",
108
+ err.strip)
109
+
110
+ assert_invalid_id("revoke #{permission} from #{invalid_id}")
111
+ assert_abort_on_missing_creds("revoke #{permission} from #{id}")
112
+ assert_usage("revoke #{permission}")
113
+ end
114
+
115
+ def test_roles
116
+ assert_repeated_output("'#{id}' has no roles.") do
117
+ assert_cmd_gets("roles #{id}", "/api/v2/account/#{id}", [])
118
+ end
119
+
120
+ assert_abort_on_missing_creds("roles #{id}")
121
+ assert_invalid_id("roles #{invalid_id}")
122
+ assert_usage('roles')
123
+ end
124
+
125
+ def test_add_ingestionpolicy_to
126
+ assert_repeated_output("Added '#{policy}' to '#{id}'.") do
127
+ assert_cmd_posts("ingestionpolicy add to #{id} #{policy}",
128
+ '/api/v2/account/addingestionpolicy',
129
+ { ingestionPolicyId: policy,
130
+ accounts: [id] }.to_json)
131
+ end
132
+
133
+ assert_invalid_id("ingestionpolicy add to #{invalid_id} #{policy}")
134
+ assert_invalid_id("ingestionpolicy add to #{id} #{invalid_policy}")
135
+ assert_abort_on_missing_creds("ingestionpolicy add to #{id} #{policy}")
136
+ assert_usage("ingestionpolicy add to #{policy}")
137
+ end
138
+
139
+ def test_remove_ingestionpolicy_remove
140
+ assert_repeated_output("Removed '#{policy}' from '#{id}'.") do
141
+ assert_cmd_posts("ingestionpolicy remove from #{id} #{policy}",
142
+ '/api/v2/account/removeingestionpolicies',
143
+ { ingestionPolicyId: policy,
144
+ accounts: [id] }.to_json)
145
+ end
146
+
147
+ assert_invalid_id("ingestionpolicy remove from #{invalid_id} #{policy}")
148
+ assert_invalid_id("ingestionpolicy remove from #{id} #{invalid_policy}")
149
+ assert_abort_on_missing_creds("ingestionpolicy remove from #{id} #{policy}")
150
+ assert_usage("ingestionpolicy remove from #{policy}")
151
+ end
152
+
153
+ def test_ingestionpolicy
154
+ assert_repeated_output("'#{id}' has no ingestion policy.") do
155
+ assert_cmd_gets("ingestionpolicy #{id}", "/api/v2/account/#{id}", [])
156
+ end
157
+
158
+ assert_abort_on_missing_creds("ingestionpolicy #{id}")
159
+ assert_invalid_id("ingestionpolicy #{invalid_id}")
160
+ assert_usage('ingestionpolicy')
161
+ end
162
+
163
+ def test_groups
164
+ assert_repeated_output("'#{id}' does not belong to any groups.") do
165
+ assert_cmd_gets("groups #{id}", "/api/v2/account/#{id}", [])
166
+ end
167
+
168
+ assert_invalid_id("groups #{invalid_id}")
169
+ assert_abort_on_missing_creds("groups #{id}")
170
+ assert_usage('groups')
171
+ end
172
+
173
+ def test_permissions
174
+ assert_repeated_output("'#{id}' does not have any permissions " \
175
+ 'directly attached.') do
176
+ assert_cmd_gets("permissions #{id}", "/api/v2/account/#{id}", [])
177
+ end
178
+
179
+ assert_abort_on_missing_creds("permissions #{id}")
180
+ assert_invalid_id("permissions #{invalid_id}")
181
+ assert_usage('permissions')
182
+ end
183
+
184
+ def test_invite_with_group
185
+ expected_body = [{ emailAddress: id,
186
+ userGroups: [groups.first],
187
+ groups: [] }].to_json
188
+
189
+ assert_repeated_output("Sent invitation to '#{id}'.") do
190
+ assert_cmd_posts("invite user -g #{groups.first} #{id}",
191
+ '/api/v2/account/user/invite',
192
+ expected_body)
193
+ end
194
+
195
+ assert_noop("invite user -g #{groups.first} #{id}",
196
+ 'uri: POST https://default.wavefront.com/api/v2/account/user' \
197
+ '/invite',
198
+ "body: #{expected_body}")
199
+ assert_invalid_id("invite user -g #{groups.first} #{invalid_id}")
200
+ assert_abort_on_missing_creds("invite user -g #{groups.first} #{id}")
201
+ assert_usage('invite user')
202
+ end
203
+
204
+ def test_invite_with_role_and_policy
205
+ expected_body = [{ emailAddress: id,
206
+ roles: roles,
207
+ ingestionPolicyId: policy,
208
+ groups: [] }].to_json
209
+
210
+ assert_repeated_output("Sent invitation to '#{id}'.") do
211
+ assert_cmd_posts(
212
+ "invite user -r #{roles.join(' -r ')} -i #{policy} #{id}",
213
+ '/api/v2/account/user/invite',
214
+ expected_body
215
+ )
216
+ end
217
+
218
+ assert_noop("invite user -r #{roles.join(' -r ')} -i #{policy} #{id}",
219
+ 'uri: POST https://default.wavefront.com/api/v2/account/user' \
220
+ '/invite',
221
+ "body: #{expected_body}")
222
+ assert_invalid_id("invite user -m #{permission} #{invalid_id}")
223
+ assert_abort_on_missing_creds("invite user -m #{permission} #{id}")
224
+ assert_usage('invite user')
225
+ end
226
+
227
+ def test_validate
228
+ cmd = "validate #{user_list.join(' ')}"
229
+
230
+ quietly do
231
+ assert_cmd_posts(cmd,
232
+ '/api/v2/account/validateAccounts',
233
+ user_list.to_json,
234
+ IO.read(RES_DIR + 'responses' + 'user-validate.json'))
235
+ end
236
+
237
+ assert_noop(cmd,
238
+ 'uri: POST https://default.wavefront.com/api/v2/account' \
239
+ '/validateAccounts',
240
+ "body: #{user_list.to_json}")
241
+ assert_abort_on_missing_creds(cmd)
242
+ assert_usage('validate')
243
+ end
244
+
245
+ private
246
+
247
+ def id
248
+ 'someone@example.com'
249
+ end
250
+
251
+ def invalid_id
252
+ 'bad' * 200
253
+ end
254
+
255
+ def cmd_word
256
+ 'account'
257
+ end
258
+
259
+ def groups
260
+ %w[2659191e-aad4-4302-a94e-9667e1517127
261
+ abcdef12-1234-abcd-1234-abcdef012345]
262
+ end
263
+
264
+ def invalid_group
265
+ '__bad_group__'
266
+ end
267
+
268
+ def roles
269
+ %w[87654321-aad4-4302-a94e-9667e1517127
270
+ 12345678-1234-abcd-1234-abcdef012345]
271
+ end
272
+
273
+ def invalid_role
274
+ '__bad_role__'
275
+ end
276
+
277
+ def list_response
278
+ { items: [{ identifier: 'user1@example.com' },
279
+ { identifier: 'user2@example.com' }] }.to_json
280
+ end
281
+
282
+ def permission
283
+ 'alerts_management'
284
+ end
285
+
286
+ def invalid_permission
287
+ 'made_up_permission'
288
+ end
289
+
290
+ def user_list
291
+ %w[someone@example.com
292
+ sa:testsysacct
293
+ no-such-thing]
294
+ end
295
+
296
+ def policy
297
+ 'test-policy-1579802191234'
298
+ end
299
+
300
+ def invalid_policy
301
+ '__some_nonsense_or_other__'
302
+ end
303
+ end