wavefront-cli 8.2.0 → 8.5.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.
- checksums.yaml +4 -4
- data/HISTORY.md +21 -1
- data/lib/wavefront-cli/base.rb +3 -0
- data/lib/wavefront-cli/commands/event.rb +8 -6
- data/lib/wavefront-cli/commands/proxy.rb +1 -0
- data/lib/wavefront-cli/commands/serviceaccount.rb +6 -4
- data/lib/wavefront-cli/controller.rb +9 -0
- data/lib/wavefront-cli/display/proxy.rb +4 -0
- data/lib/wavefront-cli/display/serviceaccount.rb +12 -4
- data/lib/wavefront-cli/event.rb +50 -166
- data/lib/wavefront-cli/event_store.rb +177 -0
- data/lib/wavefront-cli/proxy.rb +4 -0
- data/lib/wavefront-cli/serviceaccount.rb +16 -6
- data/lib/wavefront-cli/version.rb +1 -1
- data/spec/spec_helper.rb +0 -1
- data/spec/wavefront-cli/controller_spec.rb +12 -0
- data/spec/wavefront-cli/event_spec.rb +69 -109
- data/spec/wavefront-cli/event_store_spec.rb +186 -0
- data/spec/wavefront-cli/proxy_spec.rb +13 -0
- data/spec/wavefront-cli/serviceaccount_spec.rb +53 -19
- data/wavefront-cli.gemspec +1 -1
- metadata +13 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 363b1be94331165aacf1538c797d07bdbefda71e801335bb4e35df97cb0bd950
|
4
|
+
data.tar.gz: 5563b27f93c679dde5947c220d80c37816ba6faf8844d08111cbf7dcc65a76c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce61f68ba09a6ba395143fa92abeadcdb0de127f8991fe61b979ae49379d026973c5d47a09d6d4f0b306006a15f95a717cac02160af0b727f2858ba66a9fddae
|
7
|
+
data.tar.gz: 111d9d52a0e0c3955164e1872198531b9e2bd61184dc430050029efdf8d19f9cd845885a7f1d5d5685d03dbf7de0845453d95f888e13eb0195b83fd25437116d
|
data/HISTORY.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 8.5.0 (2021-01-12)
|
4
|
+
* Allow attachment of roles and ingestion policies when creating service
|
5
|
+
accounts.
|
6
|
+
* Improved introspection of service accounts.
|
7
|
+
* Refactor `event` command. This improves test coverage, fixes handling
|
8
|
+
event names with numeric suffix, and fixes searching.
|
9
|
+
|
10
|
+
## 8.4.1 (2021-01-04)
|
11
|
+
* Bugfix docopt error on `event` command.
|
12
|
+
|
13
|
+
## 8.4.0 (2020-12-16)
|
14
|
+
* Add `-f raw` option to dump the raw API response.
|
15
|
+
* Bugfix `set` subcommand, which was not reliable on certain object types.
|
16
|
+
* Require >=5.4.1 of [the SDK](https://github.com/snltd/wavefront-sdk).
|
17
|
+
|
18
|
+
## 8.3.1 (2020-11-17)
|
19
|
+
* Catch ctrl-c properly.
|
20
|
+
|
21
|
+
## 8.3.0 (2020-10-31)
|
22
|
+
* Add `wf proxy shutdown` command.
|
23
|
+
|
3
24
|
## 8.2.0 (2020-10-06)
|
4
25
|
* Display spans in human-readable query output.
|
5
26
|
|
@@ -12,7 +33,6 @@
|
|
12
33
|
|
13
34
|
## 8.0.0 (2020-09-20
|
14
35
|
* Drop Ruby 2.4.0 support. (Breaking change.)
|
15
|
-
>>>>>>> master
|
16
36
|
|
17
37
|
## 7.2.0 (2020-08-12)
|
18
38
|
* Add `cloudintegration awsid generate` command.
|
data/lib/wavefront-cli/base.rb
CHANGED
@@ -147,6 +147,7 @@ module WavefrontCli
|
|
147
147
|
noop: options[:noop] }
|
148
148
|
|
149
149
|
ret[:verbose] = options[:noop] ? true : options[:verbose]
|
150
|
+
ret[:raw_response] = true if options[:format] == 'raw'
|
150
151
|
|
151
152
|
ret.merge!(extra_options) if respond_to?(:extra_options)
|
152
153
|
ret
|
@@ -228,6 +229,8 @@ module WavefrontCli
|
|
228
229
|
|
229
230
|
exit if options[:noop]
|
230
231
|
|
232
|
+
ok_exit data if options[:format] == 'raw'
|
233
|
+
|
231
234
|
check_response_blocks(data)
|
232
235
|
warning_message(data.status)
|
233
236
|
status_error_handler(data, method)
|
@@ -10,15 +10,14 @@ class WavefrontCommandEvent < WavefrontCommandBase
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def _commands
|
13
|
-
["list #{CMN} [-l] [-O fields] [-s start] [-e end] "
|
14
|
-
'[-L limit] [-o cursor]',
|
13
|
+
["list #{CMN} [-l] [-O fields] [-s start] [-e end] [-L limit] [-o cursor]",
|
15
14
|
"describe #{CMN} <id>",
|
16
|
-
"create #{CMN} [-d description] [-s
|
15
|
+
"create #{CMN} [-d description] [-s start] [-i | -e end] " \
|
17
16
|
'[-S severity] [-T type] [-H host...] [-g tag...] [-N] <event>',
|
18
17
|
"close #{CMN} [<id>]",
|
19
18
|
"delete #{CMN} <id>",
|
20
19
|
"set #{CMN} <key=value> <id>",
|
21
|
-
"search #{CMN} [-o
|
20
|
+
"search #{CMN} [-al] [-o cursor] [-L limit] [-O fields] <condition>...",
|
22
21
|
"wrap #{CMN} [-C command] [-d description] [-S severity] [-T type] " \
|
23
22
|
'[-H host...] [-g tag...] <event>',
|
24
23
|
tag_commands,
|
@@ -28,11 +27,14 @@ class WavefrontCommandEvent < WavefrontCommandBase
|
|
28
27
|
def _options
|
29
28
|
[common_options,
|
30
29
|
"-l, --long list #{things} in detail",
|
30
|
+
"-a, --all list all #{things}",
|
31
31
|
"-o, --cursor=EVENT start listing from given #{thing}",
|
32
32
|
'-O, --fields=F1,F2,... only show given fields',
|
33
33
|
"-L, --limit=COUNT number of #{things} to list",
|
34
|
-
"-s, --start=TIME
|
35
|
-
"
|
34
|
+
"-s, --start=TIME start of listed #{things} or time at which " \
|
35
|
+
"#{thing} begins",
|
36
|
+
"-e, --end=TIME end of listed #{things} or time at which " \
|
37
|
+
"#{thing} ends",
|
36
38
|
"-S, --severity=SEVERITY severity of #{thing}",
|
37
39
|
"-i, --instant create an instantaneous #{thing}",
|
38
40
|
"-T, --type=TYPE type of #{thing}",
|
@@ -20,14 +20,15 @@ class WavefrontCommandServiceaccount < WavefrontCommandBase
|
|
20
20
|
def _commands
|
21
21
|
["list #{CMN} [-l] [-O fields]",
|
22
22
|
"describe #{CMN} <id>",
|
23
|
-
"create #{CMN} [-I] [-d description] [-p
|
24
|
-
'[-k usertoken...] <id>',
|
23
|
+
"create #{CMN} [-I] [-d description] [-p policy] [-r role...] " \
|
24
|
+
'[-g group...] [-k usertoken...] <id>',
|
25
25
|
"activate #{CMN} <id>",
|
26
26
|
"delete #{CMN} <account>...",
|
27
27
|
"deactivate #{CMN} <id>",
|
28
28
|
"dump #{CMN}",
|
29
29
|
"groups #{CMN} <id>",
|
30
|
-
"
|
30
|
+
"roles #{CMN} <id>",
|
31
|
+
"ingestionpolicy #{CMN} <id>",
|
31
32
|
"join #{CMN} <id> <group>...",
|
32
33
|
"leave #{CMN} <id> <group>...",
|
33
34
|
"grant #{CMN} <permission> to <id>",
|
@@ -52,7 +53,8 @@ class WavefrontCommandServiceaccount < WavefrontCommandBase
|
|
52
53
|
"-U, --upsert import new or update existing #{thing}",
|
53
54
|
"-I, --inactive create an inactive #{thing}",
|
54
55
|
"-d, --desc=STRING description of #{thing}",
|
55
|
-
"-
|
56
|
+
"-r, --role=STRING give #{thing} this role",
|
57
|
+
"-p, --policy=STRING give #{thing} this ingestion policy",
|
56
58
|
"-g, --group=STRING add #{thing} to this user group",
|
57
59
|
'-N, --name=STRING name of token',
|
58
60
|
'-k, --usertoken=STRING API token']
|
@@ -39,6 +39,15 @@ class WavefrontCliController
|
|
39
39
|
@opts = parse_opts(opts)
|
40
40
|
cli_class_obj = cli_class(cmd, @opts)
|
41
41
|
run_command(cli_class_obj)
|
42
|
+
rescue Interrupt
|
43
|
+
handle_interrupt!
|
44
|
+
end
|
45
|
+
|
46
|
+
def handle_interrupt!
|
47
|
+
raise if opts[:debug]
|
48
|
+
|
49
|
+
puts "\nCancelled at user's request."
|
50
|
+
exit 0
|
42
51
|
end
|
43
52
|
|
44
53
|
# What you see when you do 'wf --help'
|
@@ -35,14 +35,22 @@ module WavefrontDisplay
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
def do_roles
|
39
|
+
if data[:roles].empty?
|
40
|
+
puts 'Account does not have any roles attached.'
|
41
|
+
else
|
42
|
+
data[:roles].each { |r| puts format('%<id>s (%<name>s)', r) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
38
46
|
alias do_join do_groups
|
39
47
|
alias do_leave do_groups
|
40
48
|
|
41
|
-
def
|
42
|
-
if data[:
|
43
|
-
puts 'Account does not have
|
49
|
+
def do_ingestionpolicy
|
50
|
+
if data[:ingestionPolicy].empty?
|
51
|
+
puts 'Account does not have an ingestion policy attached.'
|
44
52
|
else
|
45
|
-
puts data[:
|
53
|
+
puts format('%<id>s (%<name>s)', data[:ingestionPolicy])
|
46
54
|
end
|
47
55
|
end
|
48
56
|
|
data/lib/wavefront-cli/event.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'fileutils'
|
4
|
-
require 'open3'
|
5
3
|
require 'wavefront-sdk/support/mixins'
|
6
4
|
require_relative 'base'
|
5
|
+
require_relative 'event_store'
|
7
6
|
require_relative 'command_mixins/tag'
|
8
7
|
|
9
8
|
module WavefrontCli
|
@@ -11,14 +10,13 @@ module WavefrontCli
|
|
11
10
|
# CLI coverage for the v2 'event' API.
|
12
11
|
#
|
13
12
|
class Event < Base
|
14
|
-
attr_reader :
|
13
|
+
attr_reader :state
|
15
14
|
|
16
15
|
include Wavefront::Mixins
|
17
16
|
include WavefrontCli::Mixin::Tag
|
18
17
|
|
19
|
-
def post_initialize(
|
20
|
-
@
|
21
|
-
create_dir(state_dir)
|
18
|
+
def post_initialize(options)
|
19
|
+
@state = WavefrontCli::EventStore.new(options)
|
22
20
|
end
|
23
21
|
|
24
22
|
def do_list
|
@@ -31,38 +29,14 @@ module WavefrontCli
|
|
31
29
|
t_start = parse_time(opts[:start], true)
|
32
30
|
body = create_body(opts, t_start)
|
33
31
|
resp = wf.create(body)
|
34
|
-
|
35
|
-
resp
|
36
|
-
end
|
37
|
-
|
38
|
-
def state_file_needed?(opts)
|
39
|
-
!(opts[:nostate] || opts[:end] || opts[:instant])
|
40
|
-
end
|
41
|
-
|
42
|
-
# The user doesn't have to give us an event ID. If no event
|
43
|
-
# name is given, we'll pop the last event off the stack. If an
|
44
|
-
# event name is given and it doesn't look like a full WF event
|
45
|
-
# name, we'll look for something on the stack. If it does look
|
46
|
-
# like a real event, we'll make an API call straight away.
|
47
|
-
#
|
48
|
-
def do_close(id = nil)
|
49
|
-
id ||= options[:'<id>']
|
50
|
-
ev = local_event(id)
|
51
|
-
ev_file = event_file(id)
|
52
|
-
|
53
|
-
abort "No locally stored event matches '#{id}'." unless ev
|
54
|
-
|
55
|
-
res = wf.close(ev)
|
56
|
-
ev_file.unlink if ev_file&.exist? && res.status.code == 200
|
57
|
-
res
|
58
|
-
end
|
32
|
+
return if opts[:noop]
|
59
33
|
|
60
|
-
|
61
|
-
|
34
|
+
state.create!(resp.response[:id])
|
35
|
+
resp
|
62
36
|
end
|
63
37
|
|
64
38
|
def do_show
|
65
|
-
events =
|
39
|
+
events = state.list
|
66
40
|
|
67
41
|
if events.size.zero?
|
68
42
|
puts 'No open events.'
|
@@ -77,21 +51,54 @@ module WavefrontCli
|
|
77
51
|
create_opts = options
|
78
52
|
create_opts[:desc] ||= create_opts[:command]
|
79
53
|
event_id = do_create(create_opts).response.id
|
80
|
-
exit_code = run_wrapped_cmd(options[:command])
|
54
|
+
exit_code = state.run_wrapped_cmd(options[:command])
|
81
55
|
do_close(event_id)
|
82
56
|
puts "Command exited #{exit_code}."
|
83
57
|
exit exit_code
|
84
58
|
end
|
85
59
|
|
86
|
-
#
|
87
|
-
#
|
60
|
+
# The user doesn't have to give us an event ID. If no event name is given,
|
61
|
+
# we'll pop the last event off the stack. If an event name is given and it
|
62
|
+
# doesn't look like a full WF event name, we'll look for something on the
|
63
|
+
# stack. If it does look like a real event, we'll make an API call
|
64
|
+
# straight away.
|
88
65
|
#
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
66
|
+
def do_close(id = nil)
|
67
|
+
id ||= options[:'<id>']
|
68
|
+
ev = state.event(id)
|
69
|
+
ev_file = state.event_file(id)
|
70
|
+
|
71
|
+
abort "No locally stored event matches '#{id}'." unless ev
|
72
|
+
|
73
|
+
res = wf.close(ev)
|
74
|
+
ev_file.unlink if ev_file&.exist? && res.status.code == 200
|
75
|
+
res
|
76
|
+
end
|
77
|
+
|
78
|
+
# We have to override the normal validation methods because an event can
|
79
|
+
# be referred to by only a part of its name. This happens when the user
|
80
|
+
# refers to events on the local stack.
|
81
|
+
#
|
82
|
+
def validate_input
|
83
|
+
validate_id if options[:'<id>'] && !options[:close]
|
84
|
+
validate_tags if options[:'<tag>']
|
85
|
+
validate_tags(:evtag) if options[:evtag]
|
86
|
+
send(:extra_validation) if respond_to?(:extra_validation)
|
87
|
+
end
|
88
|
+
|
89
|
+
def list_args
|
90
|
+
[window_start,
|
91
|
+
window_end,
|
92
|
+
options[:limit] || 100,
|
93
|
+
options[:cursor] || nil]
|
94
|
+
end
|
95
|
+
|
96
|
+
def window_start
|
97
|
+
parse_time((options[:start] || Time.now - 600), true)
|
98
|
+
end
|
99
|
+
|
100
|
+
def window_end
|
101
|
+
parse_time((options[:end] || Time.now), true)
|
95
102
|
end
|
96
103
|
|
97
104
|
# return [Hash] body for #create() method
|
@@ -122,128 +129,5 @@ module WavefrontCli
|
|
122
129
|
r[:type] = opts[:type] if opts[:type]
|
123
130
|
end
|
124
131
|
end
|
125
|
-
|
126
|
-
# @return a local event from the stack directory
|
127
|
-
#
|
128
|
-
def local_event(id)
|
129
|
-
if !id
|
130
|
-
pop_event
|
131
|
-
elsif id =~ /^\d{13}:.+/
|
132
|
-
id
|
133
|
-
else
|
134
|
-
pop_event(id)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def local_event_list
|
139
|
-
events = state_dir.children
|
140
|
-
abort 'No locally recorded events.' if events.empty?
|
141
|
-
|
142
|
-
events
|
143
|
-
rescue Errno::ENOENT
|
144
|
-
raise(WavefrontCli::Exception::SystemError,
|
145
|
-
'There is no event state directory on this host.')
|
146
|
-
end
|
147
|
-
|
148
|
-
# Run a command, stream stderr and stdout to the screen (they
|
149
|
-
# get combined -- could be an issue for someone somewhere) and
|
150
|
-
# return the command's exit code
|
151
|
-
#
|
152
|
-
def run_wrapped_cmd(cmd)
|
153
|
-
separator = '-' * (TW - 4)
|
154
|
-
|
155
|
-
puts "Command output follows, on STDERR:\n#{separator}"
|
156
|
-
ret = nil
|
157
|
-
|
158
|
-
Open3.popen2e(cmd) do |_in, out, thr|
|
159
|
-
# rubocop:disable Lint/AssignmentInCondition
|
160
|
-
while l = out.gets do warn l end
|
161
|
-
# rubocop:enable Lint/AssignmentInCondition
|
162
|
-
ret = thr.value.exitstatus
|
163
|
-
end
|
164
|
-
|
165
|
-
puts separator
|
166
|
-
ret
|
167
|
-
end
|
168
|
-
|
169
|
-
# Write a state file. We put the hosts bound to the event into the
|
170
|
-
# file. These aren't currently used by anything in the CLI, but they
|
171
|
-
# might be useful to someone, somewhere, someday.
|
172
|
-
#
|
173
|
-
def create_state_file(id)
|
174
|
-
fname = state_dir + id
|
175
|
-
File.open(fname, 'w') { |fh| fh.puts(event_file_data) }
|
176
|
-
puts "Event state recorded at #{fname}."
|
177
|
-
rescue StandardError
|
178
|
-
puts 'NOTICE: event was created but state file was not.'
|
179
|
-
end
|
180
|
-
|
181
|
-
# Record event data in the state file. We don't currently use it, but it
|
182
|
-
# might be useful to someone someday.
|
183
|
-
#
|
184
|
-
# @return [String]
|
185
|
-
#
|
186
|
-
def event_file_data
|
187
|
-
{ hosts: options[:host],
|
188
|
-
description: options[:desc],
|
189
|
-
severity: options[:severity],
|
190
|
-
tags: options[:evtag] }.to_json
|
191
|
-
end
|
192
|
-
|
193
|
-
def create_dir(state_dir)
|
194
|
-
FileUtils.mkdir_p(state_dir)
|
195
|
-
raise unless state_dir.exist? && state_dir.directory? &&
|
196
|
-
state_dir.writable?
|
197
|
-
rescue StandardError
|
198
|
-
raise(WavefrontCli::Exception::SystemError,
|
199
|
-
"Cannot create writable system directory at '#{state_dir}'.")
|
200
|
-
end
|
201
|
-
|
202
|
-
def validate_input
|
203
|
-
validate_id if options[:'<id>'] && !options[:close]
|
204
|
-
validate_tags if options[:'<tag>']
|
205
|
-
validate_tags(:evtag) if options[:evtag]
|
206
|
-
send(:extra_validation) if respond_to?(:extra_validation)
|
207
|
-
end
|
208
|
-
|
209
|
-
# Get the last event this script created. If you supply a name, you
|
210
|
-
# get the last event with that name. If not, you get the last event.
|
211
|
-
# Chances are you'll only ever have one in-play at once.
|
212
|
-
#
|
213
|
-
# @param name [String] name of event
|
214
|
-
# @eturn an array of [timestamp, event_name]
|
215
|
-
#
|
216
|
-
def pop_event(name = nil)
|
217
|
-
return false unless state_dir.exist?
|
218
|
-
|
219
|
-
list = local_events_with_name(name)
|
220
|
-
return false if list.empty?
|
221
|
-
|
222
|
-
ev_file = list.max
|
223
|
-
File.unlink(ev_file)
|
224
|
-
ev_file.basename.to_s
|
225
|
-
end
|
226
|
-
|
227
|
-
def local_events_with_name(name = nil)
|
228
|
-
list = local_event_list
|
229
|
-
return list unless name
|
230
|
-
|
231
|
-
list.select { |f| f.basename.to_s.split(':').last == name }
|
232
|
-
end
|
233
|
-
|
234
|
-
def list_args
|
235
|
-
[window_start,
|
236
|
-
window_end,
|
237
|
-
options[:limit] || 100,
|
238
|
-
options[:cursor] || nil]
|
239
|
-
end
|
240
|
-
|
241
|
-
def window_start
|
242
|
-
parse_time((options[:start] || Time.now - 600), true)
|
243
|
-
end
|
244
|
-
|
245
|
-
def window_end
|
246
|
-
parse_time((options[:end] || Time.now), true)
|
247
|
-
end
|
248
132
|
end
|
249
133
|
end
|