wavefront-cli 6.1.0 → 7.1.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 (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
@@ -34,9 +34,4 @@ class WavefrontCommandSpy < WavefrontCommandBase
34
34
  '-T, --tag-key=TAG only show metrics with the given point tag key',
35
35
  '-y, --type=STRING one of METRIC, SPAN, HOST, or STRING']
36
36
  end
37
-
38
- def postscript
39
- "\nNOTE: This command uses the unofficial 'spy' API endpoint, which " \
40
- 'is not guaranteed to remain stable.'.cmd_fold(TW, 0)
41
- end
42
37
  end
@@ -24,17 +24,18 @@ class WavefrontCommandUsergroup < WavefrontCommandBase
24
24
  def _commands
25
25
  ["list #{CMN} [-al] [-O fields] [-o offset] [-L limit]",
26
26
  "describe #{CMN} <id>",
27
- "create #{CMN} [-p permission...] <name>",
27
+ "create #{CMN} [-r role_id...] <name>",
28
28
  "delete #{CMN} <id>",
29
29
  "dump #{CMN}",
30
30
  "import #{CMN} [-uU] <file>",
31
31
  "set #{CMN} <key=value> <id>",
32
+ "add to #{CMN} <id> <user>...",
33
+ "remove from #{CMN} <id> <user>...",
32
34
  "users #{CMN} <id>",
35
+ "add role #{CMN} <id> <role>...",
36
+ "remove role #{CMN} <id> <role>...",
37
+ "roles #{CMN} <id>",
33
38
  "permissions #{CMN} <id>",
34
- "add user #{CMN} <id> <user>...",
35
- "remove user #{CMN} <id> <user>...",
36
- "grant #{CMN} <permission> to <id>",
37
- "revoke #{CMN} <permission> from <id>",
38
39
  "search #{CMN} [-al] [-o offset] [-L limit] [-O fields] <condition>..."]
39
40
  end
40
41
 
@@ -47,11 +48,6 @@ class WavefrontCommandUsergroup < WavefrontCommandBase
47
48
  '-O, --fields=F1,F2,... only show given fields',
48
49
  "-u, --update update an existing #{thing}",
49
50
  "-U, --upsert import new or update existing #{thing}",
50
- '-p, --permission=STRING Wavefront permission']
51
- end
52
-
53
- def postscript
54
- "'wf settings list permissions' will give you a list of all " \
55
- 'currently supported permissions.'.fold(TW, 0)
51
+ '-r, --role-id=STRING Wavefront role ID']
56
52
  end
57
53
  end
@@ -18,7 +18,9 @@ class WavefrontCommandWrite < WavefrontCommandBase
18
18
  '<metric> [--] <val>...',
19
19
  'file [-DnViq] [-c file] [-P profile] [-E proxy] [-H host] ' \
20
20
  '[-p port] [-F infileformat] [-m metric] [-T tag...] [-I interval] ' \
21
- '[-u method] [-S socket] <file>']
21
+ '[-u method] [-S socket] <file>',
22
+ 'noise [-DnViq] [-P profile] [-E proxy] [-H host] [-p port] ' \
23
+ '[-T tag...] [-I interval] [-x value] [-X value] <metric>']
22
24
  end
23
25
 
24
26
  def _options
@@ -33,9 +35,12 @@ class WavefrontCommandWrite < WavefrontCommandBase
33
35
  'a file will be assigned. If the file contains a metric name, ' \
34
36
  'the two will be dot-concatenated, with this value first',
35
37
  '-i, --delta increment metric by given value',
36
- "-I, --interval=INTERVAL interval of distribution (default 'm')",
38
+ "-I, --interval=INTERVAL interval of distribution (default 'm'), or " \
39
+ 'time in seconds between noise values (default 1)',
37
40
  '-u, --using=METHOD method by which to send points',
38
41
  '-S, --socket=FILE Unix datagram socket',
42
+ '-x, --min=NUMERIC lower bound of random values (default -10)',
43
+ '-X, --max=NUMERIC upper bound of random values (default 10)',
39
44
  "-q, --quiet don't report the points sent summary " \
40
45
  '(unless there were errors)']
41
46
  end
@@ -17,6 +17,7 @@ require_relative 'version'
17
17
  require_relative 'constants'
18
18
  require_relative 'exception'
19
19
  require_relative 'opt_handler'
20
+ require_relative 'exception_handler'
20
21
  require_relative 'stdlib/string'
21
22
 
22
23
  CMD_DIR = Pathname.new(__dir__) + 'commands'
@@ -28,6 +29,7 @@ class WavefrontCliController
28
29
  attr_reader :args, :usage, :opts, :cmds, :tw
29
30
 
30
31
  include WavefrontCli::Constants
32
+ include WavefrontCli::ExceptionMixins
31
33
 
32
34
  def initialize(args)
33
35
  @args = args
@@ -107,12 +109,8 @@ class WavefrontCliController
107
109
  #
108
110
  def cli_class(cmd, opts)
109
111
  load_cli_class(cmd, opts)
110
- rescue WavefrontCli::Exception::UnhandledCommand
111
- abort 'Fatal error. Unsupported command. Please open a Github issue.'
112
- rescue WavefrontCli::Exception::InvalidInput => e
113
- abort "Invalid input. #{e.message}"
114
- rescue RuntimeError => e
115
- abort "Unable to run command. #{e.message}."
112
+ rescue StandardError => e
113
+ exception_handler(e)
116
114
  end
117
115
 
118
116
  def load_cli_class(cmd, opts)
@@ -120,68 +118,12 @@ class WavefrontCliController
120
118
  Object.const_get('WavefrontCli').const_get(cmds[cmd].sdk_class).new(opts)
121
119
  end
122
120
 
123
- # rubocop:disable Metrics/MethodLength
124
- # rubocop:disable Metrics/AbcSize
125
121
  def run_command(cli_class_obj)
126
122
  cli_class_obj.validate_opts
127
123
  cli_class_obj.run
128
- rescue Interrupt
129
- abort "\nOperation aborted at user request."
130
- rescue WavefrontCli::Exception::ConfigFileNotFound => e
131
- abort "Configuration file #{e}' not found."
132
- rescue WavefrontCli::Exception::CredentialError => e
133
- handle_missing_credentials(e)
134
- rescue WavefrontCli::Exception::MandatoryValue
135
- abort 'A value must be supplied.'
136
- rescue Wavefront::Exception::NetworkTimeout
137
- abort 'Connection timed out.'
138
- rescue Wavefront::Exception::InvalidPermission => e
139
- abort "'#{e}' is not a valid privilege."
140
- rescue Wavefront::Exception::InvalidUserGroupId => e
141
- abort "'#{e}' is not a valid user group id."
142
- rescue WavefrontCli::Exception::InvalidValue => e
143
- abort "Invalid value for #{e}."
144
- rescue WavefrontCli::Exception::ProfileExists => e
145
- abort "Profile '#{e}' already exists."
146
- rescue WavefrontCli::Exception::ProfileNotFound => e
147
- abort "Profile '#{e}' not found."
148
- rescue WavefrontCli::Exception::FileNotFound
149
- abort 'File not found.'
150
- rescue WavefrontCli::Exception::InsufficientData => e
151
- abort "Insufficient data. #{e.message}"
152
- rescue WavefrontCli::Exception::InvalidQuery => e
153
- abort "Invalid query. API message: '#{e.message}'."
154
- rescue WavefrontCli::Exception::SystemError => e
155
- abort "Host system error. #{e.message}"
156
- rescue WavefrontCli::Exception::UnparseableInput => e
157
- abort "Cannot parse input. #{e.message}"
158
- rescue WavefrontCli::Exception::UnparseableSearchPattern
159
- abort 'Searches require a key, a value, and a match operator.'
160
- rescue WavefrontCli::Exception::UnsupportedFileFormat
161
- abort 'Unsupported file format.'
162
- rescue WavefrontCli::Exception::UnsupportedOperation => e
163
- abort "Unsupported operation.\n#{e.message}"
164
- rescue WavefrontCli::Exception::UnsupportedOutput => e
165
- abort e.message
166
- rescue WavefrontCli::Exception::UnsupportedNoop
167
- abort 'Multiple API call operations cannot be performed as no-ops.'
168
- rescue WavefrontCli::Exception::UserGroupNotFound => e
169
- abort "Cannot find user group '#{e.message}'."
170
- rescue Wavefront::Exception::UnsupportedWriter => e
171
- abort "Unsupported writer '#{e.message}'."
172
- rescue WavefrontCli::Exception::UserError => e
173
- abort "User error: #{e.message}."
174
- rescue WavefrontCli::Exception::ImpossibleSearch
175
- abort 'Search on non-existent key. Please use a top-level field.'
176
- rescue Wavefront::Exception::InvalidSamplingValue
177
- abort 'Sampling rates must be between 0 and 0.05.'
178
124
  rescue StandardError => e
179
- warn "general error: #{e}"
180
- backtrace_message(e)
181
- abort
125
+ exception_handler(e)
182
126
  end
183
- # rubocop:enable Metrics/MethodLength
184
- # rubocop:enable Metrics/AbcSize
185
127
 
186
128
  def backtrace_message(err)
187
129
  if opts[:debug]
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module WavefrontDisplay
6
+ #
7
+ # Format human-readable output for account management.
8
+ #
9
+ class Account < Base
10
+ def do_list_brief
11
+ filter_user_list
12
+ puts(data.map { |account| account[:identifier] })
13
+ end
14
+
15
+ def do_list
16
+ filter_user_list
17
+ super
18
+ end
19
+
20
+ def do_role_add_to
21
+ puts format("Gave %<quoted_roles>s to '%<id>s'.",
22
+ id: options[:'<id>'],
23
+ quoted_roles: quoted(options[:'<role>']))
24
+ end
25
+
26
+ def do_role_remove_from
27
+ puts format("Removed %<quoted_roles>s from '%<id>s'.",
28
+ id: options[:'<id>'],
29
+ quoted_roles: quoted(options[:'<role>']))
30
+ end
31
+
32
+ def do_roles
33
+ roles = data.fetch(:roles, [])
34
+ puts roles.empty? ? "'#{options[:'<id>']}' has no roles." : roles
35
+ end
36
+
37
+ def do_group_add_to
38
+ puts format("Added '%<id>s' to %<quoted_group>s.",
39
+ id: options[:'<id>'],
40
+ quoted_group: quoted(options[:'<group>']))
41
+ end
42
+
43
+ def do_group_remove_from
44
+ puts format("Removed '%<id>s' from %<quoted_group>s.",
45
+ id: options[:'<id>'],
46
+ quoted_group: quoted(options[:'<group>']))
47
+ end
48
+
49
+ def do_groups
50
+ groups = data.fetch(:userGroups, [])
51
+
52
+ if groups.empty?
53
+ puts "'#{options[:'<id>']}' does not belong to any groups."
54
+ else
55
+ puts groups.sort
56
+ end
57
+ end
58
+
59
+ def do_business_functions
60
+ puts data.sort
61
+ end
62
+
63
+ def do_grant_to
64
+ puts format("Granted '%<permission>s' to %<quoted_accounts>s.",
65
+ permission: options[:'<permission>'],
66
+ quoted_accounts: quoted(options[:'<account>']))
67
+ end
68
+
69
+ def do_revoke_from
70
+ puts format("Revoked '%<permission>s' from %<quoted_accounts>s.",
71
+ permission: options[:'<permission>'],
72
+ quoted_accounts: quoted(options[:'<account>']))
73
+ end
74
+
75
+ def do_permissions
76
+ perms = data.fetch(:groups, [])
77
+
78
+ if perms.empty?
79
+ puts "'#{options[:'<id>']}' does not have any permissions directly " \
80
+ 'attached.'
81
+ else
82
+ puts perms.sort
83
+ end
84
+ end
85
+
86
+ def do_ingestionpolicy_add_to
87
+ puts format("Added '%<policy>s' to '%<id>s'.",
88
+ id: options[:'<id>'],
89
+ policy: options[:'<policy>'])
90
+ end
91
+
92
+ def do_ingestionpolicy_remove_from
93
+ puts format("Removed '%<policy>s' from '%<id>s'.",
94
+ id: options[:'<id>'],
95
+ policy: options[:'<policy>'])
96
+ end
97
+
98
+ def do_ingestionpolicy
99
+ policy = data.fetch(:ingestionPolicyId, [])
100
+
101
+ if policy.empty?
102
+ puts "'#{options[:'<id>']}' has no ingestion policy."
103
+ else
104
+ puts policy
105
+ end
106
+ end
107
+
108
+ def do_invite_user
109
+ puts format("Sent invitation to '%<id>s'.", id: options[:'<id>'])
110
+ end
111
+
112
+ private
113
+
114
+ def filter_user_list
115
+ if options[:user]
116
+ data.delete_if { |a| a[:identifier].start_with?('sa::') }
117
+ elsif options[:service]
118
+ data.delete_if { |a| !a[:identifier].start_with?('sa::') }
119
+ end
120
+ end
121
+ end
122
+ end
@@ -74,5 +74,13 @@ module WavefrontDisplay
74
74
  def do_version
75
75
  puts data.max
76
76
  end
77
+
78
+ def do_affected_hosts
79
+ if data == [nil]
80
+ puts 'Alert event is not attached to any hosts.'
81
+ else
82
+ long_output
83
+ end
84
+ end
77
85
  end
78
86
  end
@@ -112,7 +112,7 @@ module WavefrontDisplay
112
112
  # long listing objects. Subclasses may define their own.
113
113
  #
114
114
  def priority_keys
115
- %i[id name]
115
+ %i[id name identifier]
116
116
  end
117
117
 
118
118
  def prioritize_keys(data, keys)
@@ -8,11 +8,12 @@ module WavefrontDisplay
8
8
  #
9
9
  class CloudIntegration < Base
10
10
  def do_list_brief
11
- multicolumn(:id, :service)
11
+ multicolumn(:id, :service, :name)
12
12
  end
13
13
 
14
14
  def do_describe
15
- readable_time(:lastReceivedDataPointMs, :lastProcessingTimestamp)
15
+ readable_time(:lastReceivedDataPointMs, :lastProcessingTimestamp,
16
+ :createdEpochMillis, :updatedEpochMillis)
16
17
  drop_fields(:forceSave, :inTrash, :deleted)
17
18
  long_output
18
19
  end
@@ -8,6 +8,7 @@ module WavefrontDisplayPrinter
8
8
  #
9
9
  class Long
10
10
  attr_reader :opts, :list, :kw
11
+
11
12
  #
12
13
  # @param data [Hash] of data to display
13
14
  # @param fields [Array[Symbol]] requred fields
@@ -55,7 +56,7 @@ module WavefrontDisplayPrinter
55
56
  def preened_value(value)
56
57
  return value unless value.is_a?(String) && value =~ /<.*>/
57
58
 
58
- value.gsub(%r{<\/?[^>]*>}, '').delete("\n")
59
+ value.gsub(%r{</?[^>]*>}, '').delete("\n")
59
60
  end
60
61
 
61
62
  # A recursive function which takes a structure, most likely a
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module WavefrontDisplay
6
+ #
7
+ # Format human-readable output for role command
8
+ #
9
+ class Role < Base
10
+ def do_list_brief
11
+ data.map! do |d|
12
+ d.merge(acct_count: "#{d[:linkedAccountsCount]} accounts",
13
+ group_count: "#{d[:linkedGroupsCount]} groups")
14
+ end
15
+ multicolumn(:id, :name, :acct_count, :group_count)
16
+ end
17
+
18
+ def do_accounts
19
+ if data.empty?
20
+ puts "No accounts have role '#{options[:'<id>']}'."
21
+ else
22
+ multicolumn(:identifier)
23
+ end
24
+ end
25
+
26
+ def do_groups
27
+ if data.empty?
28
+ puts "No groups have role '#{options[:'<id>']}'."
29
+ else
30
+ multicolumn(:id, :name)
31
+ end
32
+ end
33
+
34
+ def do_permissions
35
+ if data[:permissions].empty?
36
+ puts "Role '#{options[:'<id>']}' has no permissions."
37
+ else
38
+ puts data[:permissions]
39
+ end
40
+ end
41
+
42
+ def do_grant
43
+ puts format("Granted '%<perm>s' permission to '%<id>s'.",
44
+ perm: options[:'<permission>'],
45
+ id: options[:'<id>'])
46
+ end
47
+
48
+ def do_revoke
49
+ puts format("Revoked '%<perm>s' permission from '%<id>s'.",
50
+ perm: options[:'<permission>'],
51
+ id: options[:'<id>'])
52
+ end
53
+
54
+ def do_give_to
55
+ puts format("Gave '%<role>s' to %<members>s.",
56
+ members: quoted(options[:'<member>']),
57
+ role: options[:'<id>']).fold(TW, 0)
58
+ end
59
+
60
+ def do_take_from
61
+ puts format("Took '%<role>s' from %<members>s.",
62
+ members: quoted(options[:'<member>']),
63
+ role: options[:'<id>']).fold(TW, 0)
64
+ end
65
+ end
66
+ end
@@ -8,6 +8,7 @@ module WavefrontDisplay
8
8
  #
9
9
  class Settings < Base
10
10
  def do_list_permissions
11
+ data.sort_by! { |p| p[:groupName] }
11
12
  options[:long] ? long_output : multicolumn(:groupName)
12
13
  end
13
14
 
@@ -15,28 +15,28 @@ module WavefrontDisplay
15
15
  puts "Deleted user group '#{options[:'<id>']}'."
16
16
  end
17
17
 
18
- def do_add_user
18
+ def do_add_to
19
19
  puts format("Added %<quoted_user>s to '%<group_id>s'.",
20
20
  quoted_user: quoted(options[:'<user>']),
21
21
  group_id: options[:'<id>']).fold(TW, 0)
22
22
  end
23
23
 
24
- def do_remove_user
24
+ def do_remove_from
25
25
  puts format("Removed %<quoted_user>s from '%<group_id>s'.",
26
26
  quoted_user: quoted(options[:'<user>']),
27
27
  group_id: options[:'<id>']).fold(TW, 0)
28
28
  end
29
29
 
30
- def do_grant
31
- puts format("Granted '%<perm>s' permission to '%<group_id>s'.",
32
- perm: options[:'<permission>'],
33
- group_id: options[:'<id>'])
30
+ def do_add_role
31
+ puts format("Added %<quoted_role>s to '%<group_id>s'.",
32
+ quoted_role: quoted(options[:'<role>']),
33
+ group_id: options[:'<id>']).fold(TW, 0)
34
34
  end
35
35
 
36
- def do_revoke
37
- puts format("Revoked '%<perm>s' permission from '%<group_id>s'.",
38
- perm: options[:'<permission>'],
39
- group_id: options[:'<id>'])
36
+ def do_remove_role
37
+ puts format("Removed %<quoted_role>s from '%<group_id>s'.",
38
+ quoted_role: quoted(options[:'<role>']),
39
+ group_id: options[:'<id>']).fold(TW, 0)
40
40
  end
41
41
 
42
42
  def do_users
@@ -47,12 +47,16 @@ module WavefrontDisplay
47
47
  end)
48
48
  end
49
49
 
50
- def do_permissions
51
- puts(if !data.include?(:permissions) || data[:permissions].empty?
52
- "Group '#{options[:'<id>']}' has no permissions."
50
+ def do_roles
51
+ puts(if !data.include?(:roles) || data[:roles].empty?
52
+ "Group '#{options[:'<id>']}' has no roles attached."
53
53
  else
54
- data[:permissions]
54
+ data[:roles].map { |r| r[:id] }
55
55
  end)
56
56
  end
57
+
58
+ def do_permissions
59
+ puts data[:roles].map { |r| r[:permissions] }.flatten.sort.uniq
60
+ end
57
61
  end
58
62
  end