wavefront-cli 8.4.1 → 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 +7 -0
- data/lib/wavefront-cli/commands/event.rb +3 -3
- data/lib/wavefront-cli/commands/serviceaccount.rb +6 -4
- data/lib/wavefront-cli/display/serviceaccount.rb +12 -4
- data/lib/wavefront-cli/event.rb +50 -167
- data/lib/wavefront-cli/event_store.rb +177 -0
- data/lib/wavefront-cli/serviceaccount.rb +16 -6
- data/lib/wavefront-cli/version.rb +1 -1
- data/spec/wavefront-cli/event_spec.rb +69 -109
- data/spec/wavefront-cli/event_store_spec.rb +186 -0
- data/spec/wavefront-cli/serviceaccount_spec.rb +53 -19
- data/wavefront-cli.gemspec +1 -1
- metadata +7 -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,12 @@
|
|
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
|
+
|
3
10
|
## 8.4.1 (2021-01-04)
|
4
11
|
* Bugfix docopt error on `event` command.
|
5
12
|
|
@@ -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
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,6 +27,7 @@ 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",
|
@@ -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']
|
@@ -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,10 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'fileutils'
|
4
|
-
require 'open3'
|
5
|
-
require 'etc'
|
6
3
|
require 'wavefront-sdk/support/mixins'
|
7
4
|
require_relative 'base'
|
5
|
+
require_relative 'event_store'
|
8
6
|
require_relative 'command_mixins/tag'
|
9
7
|
|
10
8
|
module WavefrontCli
|
@@ -12,14 +10,13 @@ module WavefrontCli
|
|
12
10
|
# CLI coverage for the v2 'event' API.
|
13
11
|
#
|
14
12
|
class Event < Base
|
15
|
-
attr_reader :
|
13
|
+
attr_reader :state
|
16
14
|
|
17
15
|
include Wavefront::Mixins
|
18
16
|
include WavefrontCli::Mixin::Tag
|
19
17
|
|
20
|
-
def post_initialize(
|
21
|
-
@
|
22
|
-
create_dir(state_dir)
|
18
|
+
def post_initialize(options)
|
19
|
+
@state = WavefrontCli::EventStore.new(options)
|
23
20
|
end
|
24
21
|
|
25
22
|
def do_list
|
@@ -32,38 +29,14 @@ module WavefrontCli
|
|
32
29
|
t_start = parse_time(opts[:start], true)
|
33
30
|
body = create_body(opts, t_start)
|
34
31
|
resp = wf.create(body)
|
35
|
-
|
36
|
-
resp
|
37
|
-
end
|
38
|
-
|
39
|
-
def state_file_needed?(opts)
|
40
|
-
!(opts[:nostate] || opts[:end] || opts[:instant])
|
41
|
-
end
|
42
|
-
|
43
|
-
# The user doesn't have to give us an event ID. If no event
|
44
|
-
# name is given, we'll pop the last event off the stack. If an
|
45
|
-
# event name is given and it doesn't look like a full WF event
|
46
|
-
# name, we'll look for something on the stack. If it does look
|
47
|
-
# like a real event, we'll make an API call straight away.
|
48
|
-
#
|
49
|
-
def do_close(id = nil)
|
50
|
-
id ||= options[:'<id>']
|
51
|
-
ev = local_event(id)
|
52
|
-
ev_file = event_file(id)
|
53
|
-
|
54
|
-
abort "No locally stored event matches '#{id}'." unless ev
|
55
|
-
|
56
|
-
res = wf.close(ev)
|
57
|
-
ev_file.unlink if ev_file&.exist? && res.status.code == 200
|
58
|
-
res
|
59
|
-
end
|
32
|
+
return if opts[:noop]
|
60
33
|
|
61
|
-
|
62
|
-
|
34
|
+
state.create!(resp.response[:id])
|
35
|
+
resp
|
63
36
|
end
|
64
37
|
|
65
38
|
def do_show
|
66
|
-
events =
|
39
|
+
events = state.list
|
67
40
|
|
68
41
|
if events.size.zero?
|
69
42
|
puts 'No open events.'
|
@@ -78,21 +51,54 @@ module WavefrontCli
|
|
78
51
|
create_opts = options
|
79
52
|
create_opts[:desc] ||= create_opts[:command]
|
80
53
|
event_id = do_create(create_opts).response.id
|
81
|
-
exit_code = run_wrapped_cmd(options[:command])
|
54
|
+
exit_code = state.run_wrapped_cmd(options[:command])
|
82
55
|
do_close(event_id)
|
83
56
|
puts "Command exited #{exit_code}."
|
84
57
|
exit exit_code
|
85
58
|
end
|
86
59
|
|
87
|
-
#
|
88
|
-
#
|
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.
|
89
65
|
#
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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)
|
96
102
|
end
|
97
103
|
|
98
104
|
# return [Hash] body for #create() method
|
@@ -123,128 +129,5 @@ module WavefrontCli
|
|
123
129
|
r[:type] = opts[:type] if opts[:type]
|
124
130
|
end
|
125
131
|
end
|
126
|
-
|
127
|
-
# @return a local event from the stack directory
|
128
|
-
#
|
129
|
-
def local_event(id)
|
130
|
-
if !id
|
131
|
-
pop_event
|
132
|
-
elsif id =~ /^\d{13}:.+/
|
133
|
-
id
|
134
|
-
else
|
135
|
-
pop_event(id)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def local_event_list
|
140
|
-
events = state_dir.children
|
141
|
-
abort 'No locally recorded events.' if events.empty?
|
142
|
-
|
143
|
-
events
|
144
|
-
rescue Errno::ENOENT
|
145
|
-
raise(WavefrontCli::Exception::SystemError,
|
146
|
-
'There is no event state directory on this host.')
|
147
|
-
end
|
148
|
-
|
149
|
-
# Run a command, stream stderr and stdout to the screen (they
|
150
|
-
# get combined -- could be an issue for someone somewhere) and
|
151
|
-
# return the command's exit code
|
152
|
-
#
|
153
|
-
def run_wrapped_cmd(cmd)
|
154
|
-
separator = '-' * (TW - 4)
|
155
|
-
|
156
|
-
puts "Command output follows, on STDERR:\n#{separator}"
|
157
|
-
ret = nil
|
158
|
-
|
159
|
-
Open3.popen2e(cmd) do |_in, out, thr|
|
160
|
-
# rubocop:disable Lint/AssignmentInCondition
|
161
|
-
while l = out.gets do warn l end
|
162
|
-
# rubocop:enable Lint/AssignmentInCondition
|
163
|
-
ret = thr.value.exitstatus
|
164
|
-
end
|
165
|
-
|
166
|
-
puts separator
|
167
|
-
ret
|
168
|
-
end
|
169
|
-
|
170
|
-
# Write a state file. We put the hosts bound to the event into the
|
171
|
-
# file. These aren't currently used by anything in the CLI, but they
|
172
|
-
# might be useful to someone, somewhere, someday.
|
173
|
-
#
|
174
|
-
def create_state_file(id)
|
175
|
-
fname = state_dir + id
|
176
|
-
File.open(fname, 'w') { |fh| fh.puts(event_file_data) }
|
177
|
-
puts "Event state recorded at #{fname}."
|
178
|
-
rescue StandardError
|
179
|
-
puts 'NOTICE: event was created but state file was not.'
|
180
|
-
end
|
181
|
-
|
182
|
-
# Record event data in the state file. We don't currently use it, but it
|
183
|
-
# might be useful to someone someday.
|
184
|
-
#
|
185
|
-
# @return [String]
|
186
|
-
#
|
187
|
-
def event_file_data
|
188
|
-
{ hosts: options[:host],
|
189
|
-
description: options[:desc],
|
190
|
-
severity: options[:severity],
|
191
|
-
tags: options[:evtag] }.to_json
|
192
|
-
end
|
193
|
-
|
194
|
-
def create_dir(state_dir)
|
195
|
-
FileUtils.mkdir_p(state_dir)
|
196
|
-
raise unless state_dir.exist? && state_dir.directory? &&
|
197
|
-
state_dir.writable?
|
198
|
-
rescue StandardError
|
199
|
-
raise(WavefrontCli::Exception::SystemError,
|
200
|
-
"Cannot create writable system directory at '#{state_dir}'.")
|
201
|
-
end
|
202
|
-
|
203
|
-
def validate_input
|
204
|
-
validate_id if options[:'<id>'] && !options[:close]
|
205
|
-
validate_tags if options[:'<tag>']
|
206
|
-
validate_tags(:evtag) if options[:evtag]
|
207
|
-
send(:extra_validation) if respond_to?(:extra_validation)
|
208
|
-
end
|
209
|
-
|
210
|
-
# Get the last event this script created. If you supply a name, you
|
211
|
-
# get the last event with that name. If not, you get the last event.
|
212
|
-
# Chances are you'll only ever have one in-play at once.
|
213
|
-
#
|
214
|
-
# @param name [String] name of event
|
215
|
-
# @eturn an array of [timestamp, event_name]
|
216
|
-
#
|
217
|
-
def pop_event(name = nil)
|
218
|
-
return false unless state_dir.exist?
|
219
|
-
|
220
|
-
list = local_events_with_name(name)
|
221
|
-
return false if list.empty?
|
222
|
-
|
223
|
-
ev_file = list.max
|
224
|
-
File.unlink(ev_file)
|
225
|
-
ev_file.basename.to_s
|
226
|
-
end
|
227
|
-
|
228
|
-
def local_events_with_name(name = nil)
|
229
|
-
list = local_event_list
|
230
|
-
return list unless name
|
231
|
-
|
232
|
-
list.select { |f| f.basename.to_s.split(':').last == name }
|
233
|
-
end
|
234
|
-
|
235
|
-
def list_args
|
236
|
-
[window_start,
|
237
|
-
window_end,
|
238
|
-
options[:limit] || 100,
|
239
|
-
options[:cursor] || nil]
|
240
|
-
end
|
241
|
-
|
242
|
-
def window_start
|
243
|
-
parse_time((options[:start] || Time.now - 600), true)
|
244
|
-
end
|
245
|
-
|
246
|
-
def window_end
|
247
|
-
parse_time((options[:end] || Time.now), true)
|
248
|
-
end
|
249
132
|
end
|
250
133
|
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'etc'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'open3'
|
6
|
+
require 'json'
|
7
|
+
require_relative 'constants'
|
8
|
+
require_relative 'exception'
|
9
|
+
|
10
|
+
module WavefrontCli
|
11
|
+
#
|
12
|
+
# Encapsulation of everything needed to manage the locally stored state of
|
13
|
+
# events opened by the CLI. This is our own addition, entirely separate from
|
14
|
+
# Wavefront's API.
|
15
|
+
#
|
16
|
+
# When the user creates an open-ended event (i.e. one that does not have and
|
17
|
+
# end time, and is not instantaneous) a state file is created in a local
|
18
|
+
# directory. (*)
|
19
|
+
#
|
20
|
+
# That directory is defined by the EVENT_STATE_DIR constant, but may be
|
21
|
+
# overriden with an option in the constructor. The tests do this.
|
22
|
+
#
|
23
|
+
# (*) The user may specifically request that no state file be created with
|
24
|
+
# the --nostate flag.
|
25
|
+
#
|
26
|
+
class EventStore
|
27
|
+
include WavefrontCli::Constants
|
28
|
+
|
29
|
+
attr_reader :dir, :options
|
30
|
+
|
31
|
+
# @param state_dir [Pathname] override the default dir for testing
|
32
|
+
#
|
33
|
+
def initialize(options, state_dir = nil)
|
34
|
+
@options = options
|
35
|
+
@dir = event_state_dir(state_dir) + (Etc.getlogin || 'notty')
|
36
|
+
create_dir(dir)
|
37
|
+
end
|
38
|
+
|
39
|
+
def state_file_needed?
|
40
|
+
!(options[:nostate] || options[:end] || options[:instant])
|
41
|
+
end
|
42
|
+
|
43
|
+
def event_file(id)
|
44
|
+
id =~ /^\d{13}:.+/ ? dir + id : nil
|
45
|
+
end
|
46
|
+
|
47
|
+
# We can override the temp directory with the WF_EVENT_STATE_DIR env var.
|
48
|
+
# This is primarily for testing, though someone may find a valid use for
|
49
|
+
# it.
|
50
|
+
#
|
51
|
+
def event_state_dir(state_dir = nil)
|
52
|
+
if ENV['WF_EVENT_STATE_DIR']
|
53
|
+
Pathname.new(ENV['WF_EVENT_STATE_DIR'])
|
54
|
+
elsif state_dir.nil?
|
55
|
+
EVENT_STATE_DIR
|
56
|
+
else
|
57
|
+
Pathname.new(state_dir)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param id [String,Nil] if this is falsey, returns the event on the top
|
62
|
+
# of the state stack, removing its state file. If it's an exact event
|
63
|
+
# ID, simply pass that ID back, NOT removing the state file. This is
|
64
|
+
# okay: the state file is cleaned up by WavefrontCli::Event when an
|
65
|
+
# event is closed. If it's a name but not an ID, return the ID of the
|
66
|
+
# most recent event with the given name.
|
67
|
+
# @return [String] the name of the most recent suitable event from the
|
68
|
+
# local stack directory.
|
69
|
+
#
|
70
|
+
def event(id)
|
71
|
+
if !id
|
72
|
+
pop_event!
|
73
|
+
elsif id =~ /^\d{13}:.+:\d+/
|
74
|
+
id
|
75
|
+
else
|
76
|
+
pop_event!(id)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# List events on the local stack
|
81
|
+
#
|
82
|
+
def list
|
83
|
+
events = dir.children
|
84
|
+
abort 'No locally recorded events.' if events.empty?
|
85
|
+
|
86
|
+
events
|
87
|
+
rescue Errno::ENOENT
|
88
|
+
raise(WavefrontCli::Exception::SystemError,
|
89
|
+
'There is no event state directory on this host.')
|
90
|
+
end
|
91
|
+
|
92
|
+
# Run a command, stream stderr and stdout to the screen (they
|
93
|
+
# get combined -- could be an issue for someone somewhere) and
|
94
|
+
# return the command's exit code
|
95
|
+
#
|
96
|
+
def run_wrapped_cmd(cmd)
|
97
|
+
separator = '-' * (TW - 4)
|
98
|
+
|
99
|
+
puts "Command output follows, on STDERR:\n#{separator}"
|
100
|
+
ret = nil
|
101
|
+
|
102
|
+
Open3.popen2e(cmd) do |_in, out, thr|
|
103
|
+
# rubocop:disable Lint/AssignmentInCondition
|
104
|
+
while l = out.gets do warn l end
|
105
|
+
# rubocop:enable Lint/AssignmentInCondition
|
106
|
+
ret = thr.value.exitstatus
|
107
|
+
end
|
108
|
+
|
109
|
+
puts separator
|
110
|
+
ret
|
111
|
+
end
|
112
|
+
|
113
|
+
# Write a state file. We put the hosts bound to the event into the file.
|
114
|
+
# These aren't currently used by anything in the CLI, but they might be
|
115
|
+
# useful to someone, somewhere, someday.
|
116
|
+
# @return [Nil]
|
117
|
+
#
|
118
|
+
def create!(id)
|
119
|
+
return unless state_file_needed?
|
120
|
+
|
121
|
+
fname = dir + id
|
122
|
+
File.open(fname, 'w') { |fh| fh.puts(event_file_data) }
|
123
|
+
puts "Event state recorded at #{fname}."
|
124
|
+
rescue StandardError
|
125
|
+
puts 'NOTICE: event was created but state file was not.'
|
126
|
+
end
|
127
|
+
|
128
|
+
# Record event data in the state file. We don't currently use it, but it
|
129
|
+
# might be useful to someone someday.
|
130
|
+
# @return [String]
|
131
|
+
#
|
132
|
+
def event_file_data
|
133
|
+
{ hosts: options[:host],
|
134
|
+
description: options[:desc],
|
135
|
+
severity: options[:severity],
|
136
|
+
tags: options[:evtag] }.to_json
|
137
|
+
end
|
138
|
+
|
139
|
+
def create_dir(state_dir)
|
140
|
+
FileUtils.mkdir_p(state_dir)
|
141
|
+
raise unless state_dir.exist? &&
|
142
|
+
state_dir.directory? &&
|
143
|
+
state_dir.writable?
|
144
|
+
rescue StandardError
|
145
|
+
raise(WavefrontCli::Exception::SystemError,
|
146
|
+
"Cannot create writable system directory at '#{state_dir}'.")
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get the last event this script created. If you supply a name, you get
|
150
|
+
# the last event with that name. If not, you get the last event. Note the
|
151
|
+
# '!': this method (potentially) has side effects.
|
152
|
+
# @param name [String] name of event. This is the middle part of the real
|
153
|
+
# event name: the only part supplied by the user.
|
154
|
+
# @return [Array[timestamp, event_name]]
|
155
|
+
#
|
156
|
+
def pop_event!(name = nil)
|
157
|
+
return false unless dir.exist?
|
158
|
+
|
159
|
+
list = local_events_with_name(name)
|
160
|
+
return false if list.empty?
|
161
|
+
|
162
|
+
ev_file = list.max
|
163
|
+
File.unlink(ev_file)
|
164
|
+
ev_file.basename.to_s
|
165
|
+
end
|
166
|
+
|
167
|
+
# Event names are of the form `1609860826095:name:0`
|
168
|
+
# @param name [String] the user-specified (middle) portion of an event ID
|
169
|
+
# @return [Array[String]] list of matching events
|
170
|
+
#
|
171
|
+
def local_events_with_name(name = nil)
|
172
|
+
return list unless name
|
173
|
+
|
174
|
+
list.select { |f| f.basename.to_s.split(':')[1] == name }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -23,7 +23,8 @@ module WavefrontCli
|
|
23
23
|
end
|
24
24
|
|
25
25
|
alias do_groups do_describe
|
26
|
-
alias
|
26
|
+
alias do_ingestionpolicy do_describe
|
27
|
+
alias do_roles do_describe
|
27
28
|
|
28
29
|
def do_create
|
29
30
|
wf_user_id?(options[:'<id>'])
|
@@ -95,7 +96,7 @@ module WavefrontCli
|
|
95
96
|
def extra_validation
|
96
97
|
validate_groups
|
97
98
|
validate_tokens
|
98
|
-
|
99
|
+
validate_ingestion_policy
|
99
100
|
end
|
100
101
|
|
101
102
|
def validator_exception
|
@@ -157,15 +158,18 @@ module WavefrontCli
|
|
157
158
|
!options[:inactive]
|
158
159
|
end
|
159
160
|
|
161
|
+
# rubocop:disable Metrics/AbcSize
|
160
162
|
def user_body
|
161
163
|
{ identifier: options[:'<id>'],
|
162
164
|
active: active_account?,
|
163
|
-
|
165
|
+
ingestionPolicyId: options[:policy],
|
164
166
|
tokens: options[:usertoken],
|
165
|
-
|
167
|
+
roles: options[:role],
|
168
|
+
userGroups: options[:group] }.compact.tap do |b|
|
166
169
|
b[:description] = options[:desc] if options[:desc]
|
167
170
|
end
|
168
171
|
end
|
172
|
+
# rubocop:enable Metrics/AbcSize
|
169
173
|
|
170
174
|
def item_dump_call
|
171
175
|
wf.list.response
|
@@ -175,12 +179,18 @@ module WavefrontCli
|
|
175
179
|
options[:group].each { |g| wf_usergroup_id?(g) }
|
176
180
|
end
|
177
181
|
|
182
|
+
def validate_roles
|
183
|
+
options[:role].each { |r| wf_role_id?(r) }
|
184
|
+
end
|
185
|
+
|
178
186
|
def validate_tokens
|
179
187
|
options[:usertoken].each { |t| wf_apitoken_id?(t) }
|
180
188
|
end
|
181
189
|
|
182
|
-
def
|
183
|
-
options[:
|
190
|
+
def validate_ingestion_policy
|
191
|
+
return true unless options[:policy]
|
192
|
+
|
193
|
+
wf_ingestionpolicy_id?(options[:policy])
|
184
194
|
end
|
185
195
|
|
186
196
|
def descriptive_name
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'tmpdir'
|
5
5
|
require_relative '../support/command_base'
|
6
|
+
require_relative '../test_mixins/tag'
|
6
7
|
require_relative '../../lib/wavefront-cli/event'
|
7
8
|
require 'wavefront-sdk/support/mixins'
|
8
9
|
|
@@ -15,12 +16,11 @@ class EventEndToEndTest < EndToEndTest
|
|
15
16
|
attr_reader :test_state_dir
|
16
17
|
|
17
18
|
include Wavefront::Mixins
|
18
|
-
include WavefrontCliTest::Describe
|
19
|
-
include WavefrontCliTest::Delete
|
20
|
-
# Ones above work, ones below don't
|
19
|
+
# include WavefrontCliTest::Describe
|
20
|
+
# include WavefrontCliTest::Delete
|
21
21
|
# include WavefrontCliTest::Search
|
22
|
-
# include WavefrontCliTest::Set
|
23
|
-
# include WavefrontCliTest::
|
22
|
+
# #include WavefrontCliTest::Set
|
23
|
+
# include WavefrontCliTest::Tag
|
24
24
|
|
25
25
|
def before_setup
|
26
26
|
@test_state_dir = Pathname.new(Dir.mktmpdir)
|
@@ -31,11 +31,6 @@ class EventEndToEndTest < EndToEndTest
|
|
31
31
|
FileUtils.rm_r(test_state_dir)
|
32
32
|
end
|
33
33
|
|
34
|
-
def cmd_instance
|
35
|
-
cmd_class.new(event_state_dir: TEST_EVENT_DIR)
|
36
|
-
puts cmd_class
|
37
|
-
end
|
38
|
-
|
39
34
|
def test_list_no_options
|
40
35
|
str = '/api/v2/event\?' \
|
41
36
|
'earliestStartTimeEpochMillis=\d{13}+&' \
|
@@ -65,6 +60,22 @@ class EventEndToEndTest < EndToEndTest
|
|
65
60
|
end
|
66
61
|
end
|
67
62
|
|
63
|
+
def test_show_with_no_local_events
|
64
|
+
assert_exits_with('No locally recorded events.', 'show')
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_show
|
68
|
+
setup_test_state_dir
|
69
|
+
|
70
|
+
out, err = capture_io do
|
71
|
+
assert_raises(SystemExit) { wf.new("event show -c #{CF}".split) }
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_empty(err)
|
75
|
+
assert_equal("1568133440530:ev3:0\n1568133440520:ev2:0\n" \
|
76
|
+
"1568133440515:ev1:1\n1568133440510:ev1:0\n", out)
|
77
|
+
end
|
78
|
+
|
68
79
|
def test_create
|
69
80
|
mock_id = "#{start_time}:#{event_name}:1"
|
70
81
|
state_file = state_dir + mock_id
|
@@ -100,8 +111,8 @@ class EventEndToEndTest < EndToEndTest
|
|
100
111
|
refute state_file.exist?
|
101
112
|
|
102
113
|
out, err = capture_io do
|
103
|
-
assert_cmd_posts('create -d reason -H host1 -H host2 -g ' \
|
104
|
-
"
|
114
|
+
assert_cmd_posts('create -d reason -H host1 -H host2 -g mytag ' \
|
115
|
+
"#{event_name}",
|
105
116
|
'/api/v2/event',
|
106
117
|
{ name: event_name,
|
107
118
|
startTime: a_ms_timestamp,
|
@@ -148,15 +159,6 @@ class EventEndToEndTest < EndToEndTest
|
|
148
159
|
assert_match(/\ntags tag1\n tag2\n/, out)
|
149
160
|
end
|
150
161
|
|
151
|
-
def test_close_named_event
|
152
|
-
quietly do
|
153
|
-
assert_cmd_posts('close 1568133440520:ev2:0',
|
154
|
-
'/api/v2/event/1568133440520:ev2:0/close')
|
155
|
-
end
|
156
|
-
|
157
|
-
assert_abort_on_missing_creds("close #{id}")
|
158
|
-
end
|
159
|
-
|
160
162
|
def test_close_with_no_local_events
|
161
163
|
quietly { assert_cmd_posts("close #{id}", "/api/v2/event/#{id}/close") }
|
162
164
|
assert_exits_with('No locally recorded events.', 'close')
|
@@ -212,26 +214,47 @@ class EventEndToEndTest < EndToEndTest
|
|
212
214
|
end
|
213
215
|
end
|
214
216
|
|
215
|
-
def
|
216
|
-
|
217
|
+
def test_window_start
|
218
|
+
wfse = WavefrontCli::Event.new(start: wall_time[0], end: wall_time[1])
|
219
|
+
assert_kind_of(Numeric, wfse.window_start)
|
220
|
+
assert_equal(epoch_ms_time[0], wfse.window_start)
|
221
|
+
end
|
217
222
|
|
218
|
-
|
219
|
-
|
220
|
-
|
223
|
+
def test_window_end
|
224
|
+
wfse = WavefrontCli::Event.new(start: wall_time[0], end: wall_time[1])
|
225
|
+
assert_kind_of(Numeric, wfse.window_end)
|
226
|
+
assert_equal(epoch_ms_time[1], wfse.window_end)
|
227
|
+
end
|
221
228
|
|
222
|
-
|
223
|
-
|
224
|
-
|
229
|
+
def test_list_args_defaults
|
230
|
+
wfe = WavefrontCli::Event.new({})
|
231
|
+
x = wfe.list_args
|
232
|
+
assert_instance_of(Array, x)
|
233
|
+
assert_equal(4, x.size)
|
234
|
+
assert_in_delta(((Time.now - 600).to_i * 1000), x[0], 1000)
|
235
|
+
assert_in_delta((Time.now.to_i * 1000), x[1], 1000)
|
236
|
+
assert_equal(100, x[2])
|
237
|
+
assert_nil(x[3])
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_list_args_options
|
241
|
+
wfse = WavefrontCli::Event.new(limit: 55,
|
242
|
+
start: wall_time[0],
|
243
|
+
cursor: id,
|
244
|
+
end: wall_time[1])
|
245
|
+
x = wfse.list_args
|
246
|
+
assert_instance_of(Array, x)
|
247
|
+
assert_equal(4, x.size)
|
248
|
+
assert_equal(epoch_ms_time[0], x[0])
|
249
|
+
assert_equal(epoch_ms_time[1], x[1])
|
250
|
+
assert_equal(55, x[2])
|
251
|
+
assert_equal(id, x[3])
|
225
252
|
end
|
226
253
|
|
227
254
|
private
|
228
255
|
|
229
256
|
def id
|
230
|
-
'1481553823153:testev'
|
231
|
-
end
|
232
|
-
|
233
|
-
def event_name
|
234
|
-
'test_event'
|
257
|
+
'1481553823153:testev:0'
|
235
258
|
end
|
236
259
|
|
237
260
|
def invalid_id
|
@@ -242,18 +265,24 @@ class EventEndToEndTest < EndToEndTest
|
|
242
265
|
'event'
|
243
266
|
end
|
244
267
|
|
268
|
+
def event_name
|
269
|
+
'test_event'
|
270
|
+
end
|
271
|
+
|
245
272
|
def start_time
|
246
273
|
1_481_553_823_153
|
247
274
|
end
|
248
275
|
|
249
|
-
def
|
250
|
-
|
276
|
+
def epoch_ms_time
|
277
|
+
wall_time.map { |t| (t.to_i * 1000) }
|
251
278
|
end
|
252
279
|
|
253
280
|
def state_dir
|
254
281
|
test_state_dir + (Etc.getlogin || 'notty')
|
255
282
|
end
|
256
283
|
|
284
|
+
# Puts some test events in the state directory
|
285
|
+
#
|
257
286
|
def setup_test_state_dir
|
258
287
|
FileUtils.mkdir_p(state_dir)
|
259
288
|
|
@@ -285,79 +314,10 @@ class EventEndToEndTest < EndToEndTest
|
|
285
314
|
"https://#{perm[:endpoint]}/api/v2/event/#{mock_id}/close")
|
286
315
|
.with(body: 'null')
|
287
316
|
end
|
288
|
-
end
|
289
|
-
|
290
|
-
# Unit tests for class methods
|
291
|
-
#
|
292
|
-
class EventMethodTests < Minitest::Test
|
293
|
-
attr_reader :wf, :wfse
|
294
|
-
|
295
|
-
def setup
|
296
|
-
@wf = WavefrontCli::Event.new({})
|
297
|
-
@wfse = WavefrontCli::Event.new(start: wall_time[0],
|
298
|
-
end: wall_time[1],
|
299
|
-
limit: 55,
|
300
|
-
cursor: '1481553823153:testev')
|
301
|
-
end
|
302
|
-
|
303
|
-
def test_create_dir_ok
|
304
|
-
base = Pathname.new(Dir.mktmpdir)
|
305
|
-
dir = base + 'testdir'
|
306
|
-
refute dir.exist?
|
307
|
-
wf.create_dir(dir)
|
308
|
-
assert dir.exist?
|
309
|
-
dir.unlink
|
310
|
-
base.unlink
|
311
|
-
end
|
312
|
-
|
313
|
-
def test_create_dir_fail
|
314
|
-
spy = Spy.on(FileUtils, :mkdir_p).and_return(false)
|
315
|
-
|
316
|
-
assert_raises(WavefrontCli::Exception::SystemError) do
|
317
|
-
wf.create_dir(Pathname.new('/any/old/directory'))
|
318
|
-
end
|
319
|
-
|
320
|
-
assert spy.has_been_called?
|
321
|
-
spy.unhook
|
322
|
-
end
|
323
|
-
|
324
|
-
def test_list_args_defaults
|
325
|
-
x = wf.list_args
|
326
|
-
assert_instance_of(Array, x)
|
327
|
-
assert_equal(4, x.size)
|
328
|
-
assert_in_delta(((Time.now - 600).to_i * 1000), x[0], 1000)
|
329
|
-
assert_in_delta((Time.now.to_i * 1000), x[1], 1000)
|
330
|
-
assert_equal(100, x[2])
|
331
|
-
assert_nil(x[3])
|
332
|
-
end
|
333
|
-
|
334
|
-
def test_list_args_options
|
335
|
-
x = wfse.list_args
|
336
|
-
assert_instance_of(Array, x)
|
337
|
-
assert_equal(4, x.size)
|
338
|
-
assert_equal(epoch_ms_time[0], x[0])
|
339
|
-
assert_equal(epoch_ms_time[1], x[1])
|
340
|
-
assert_equal(55, x[2])
|
341
|
-
assert_equal('1481553823153:testev', x[3])
|
342
|
-
end
|
343
|
-
|
344
|
-
def test_window_start
|
345
|
-
assert_kind_of(Numeric, wf.window_start)
|
346
|
-
assert_equal(epoch_ms_time[0], wfse.window_start)
|
347
|
-
end
|
348
|
-
|
349
|
-
def test_window_end
|
350
|
-
assert_kind_of(Numeric, wf.window_end)
|
351
|
-
assert_equal(epoch_ms_time[1], wfse.window_end)
|
352
|
-
end
|
353
317
|
|
354
|
-
|
355
|
-
|
356
|
-
def
|
357
|
-
|
358
|
-
end
|
359
|
-
|
360
|
-
def epoch_ms_time
|
361
|
-
wall_time.map { |t| (t.to_i * 1000) }
|
318
|
+
# Event searching uses a cursor, not an offset
|
319
|
+
#
|
320
|
+
def cannot_handle_offsets
|
321
|
+
true
|
362
322
|
end
|
363
323
|
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pathname'
|
5
|
+
require 'spy'
|
6
|
+
require 'minitest/autorun'
|
7
|
+
require_relative '../../lib/wavefront-cli/event_store'
|
8
|
+
|
9
|
+
TEST_EVENT_STORE_DIR = Pathname.new(Dir.mktmpdir)
|
10
|
+
|
11
|
+
# Tests for event store class. This is tested well via the interface of the
|
12
|
+
# events CLI class.
|
13
|
+
#
|
14
|
+
class Test < MiniTest::Test
|
15
|
+
attr_reader :wf
|
16
|
+
|
17
|
+
include WavefrontCli::Constants
|
18
|
+
|
19
|
+
def before_setup
|
20
|
+
FileUtils.mkdir_p(TEST_EVENT_STORE_DIR)
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup
|
24
|
+
@wf = WavefrontCli::EventStore.new({}, TEST_EVENT_STORE_DIR)
|
25
|
+
end
|
26
|
+
|
27
|
+
def teardown
|
28
|
+
FileUtils.rm_r(TEST_EVENT_STORE_DIR)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_state_file_needed?
|
32
|
+
wf1 = WavefrontCli::EventStore.new({}, TEST_EVENT_STORE_DIR)
|
33
|
+
assert wf1.state_file_needed?
|
34
|
+
|
35
|
+
wf2 = WavefrontCli::EventStore.new({ nostate: true }, TEST_EVENT_STORE_DIR)
|
36
|
+
refute wf2.state_file_needed?
|
37
|
+
|
38
|
+
wf3 = WavefrontCli::EventStore.new({ instant: true }, TEST_EVENT_STORE_DIR)
|
39
|
+
refute wf3.state_file_needed?
|
40
|
+
|
41
|
+
wf4 = WavefrontCli::EventStore.new({ start: Time.now - 20, end: Time.now },
|
42
|
+
TEST_EVENT_STORE_DIR)
|
43
|
+
refute wf4.state_file_needed?
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_event_file
|
47
|
+
x = wf.event_file(id)
|
48
|
+
assert_instance_of(Pathname, x)
|
49
|
+
assert_equal(wf.dir, x.dirname)
|
50
|
+
assert_equal(id, x.basename.to_s)
|
51
|
+
|
52
|
+
assert_nil(wf.event_file('not_a_valid_id'))
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_create_dir_ok
|
56
|
+
dir = TEST_EVENT_STORE_DIR + 'testdir'
|
57
|
+
refute dir.exist?
|
58
|
+
wf.create_dir(dir)
|
59
|
+
assert dir.exist?
|
60
|
+
dir.unlink
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_list
|
64
|
+
setup_test_state_dir
|
65
|
+
|
66
|
+
x = wf.list
|
67
|
+
assert(x.all? { |e| e.is_a?(Pathname) })
|
68
|
+
assert_equal(4, x.size)
|
69
|
+
|
70
|
+
empty_test_state_dir
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_list_empty_stack
|
74
|
+
out, err = capture_io { assert_raises(SystemExit) { wf.list } }
|
75
|
+
assert_empty(out)
|
76
|
+
assert_equal("No locally recorded events.\n", err)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_pop_event
|
80
|
+
setup_test_state_dir
|
81
|
+
|
82
|
+
assert (wf.dir + '1568133440530:ev3:0').exist?
|
83
|
+
assert_equal('1568133440530:ev3:0', wf.pop_event!)
|
84
|
+
refute (wf.dir + '1568133440530:ev3:0').exist?
|
85
|
+
|
86
|
+
empty_test_state_dir
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_pop_event_named
|
90
|
+
setup_test_state_dir
|
91
|
+
|
92
|
+
assert (wf.dir + '1568133440515:ev1:1').exist?
|
93
|
+
assert_equal('1568133440515:ev1:1', wf.pop_event!('ev1'))
|
94
|
+
refute (wf.dir + '1568133440515:ev1:1').exist?
|
95
|
+
|
96
|
+
empty_test_state_dir
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_event_specific
|
100
|
+
setup_test_state_dir
|
101
|
+
|
102
|
+
assert (wf.dir + '1568133440515:ev1:1').exist?
|
103
|
+
assert_equal('1568133440515:ev1:1', wf.event('1568133440515:ev1:1'))
|
104
|
+
assert (wf.dir + '1568133440515:ev1:1').exist?
|
105
|
+
|
106
|
+
empty_test_state_dir
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_pop_event_empty_stack
|
110
|
+
out, err = capture_io { assert_raises(SystemExit) { wf.pop_event! } }
|
111
|
+
assert_empty(out)
|
112
|
+
assert_equal("No locally recorded events.\n", err)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_event_state_dir
|
116
|
+
ENV['WF_EVENT_STATE_DIR'] = nil
|
117
|
+
assert_equal(EVENT_STATE_DIR, wf.event_state_dir)
|
118
|
+
|
119
|
+
ENV['WF_EVENT_STATE_DIR'] = '/tmp/tester'
|
120
|
+
assert_equal(Pathname.new('/tmp/tester'), wf.event_state_dir)
|
121
|
+
ENV['WF_EVENT_STATE_DIR'] = nil
|
122
|
+
|
123
|
+
assert_equal(Pathname.new('/tmp/mydir'), wf.event_state_dir('/tmp/mydir'))
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_create_dir_fail
|
127
|
+
spy = Spy.on(FileUtils, :mkdir_p).and_return(false)
|
128
|
+
|
129
|
+
assert_raises(WavefrontCli::Exception::SystemError) do
|
130
|
+
wf.create_dir(Pathname.new('/any/old/directory'))
|
131
|
+
end
|
132
|
+
|
133
|
+
assert spy.has_been_called?
|
134
|
+
spy.unhook
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_event_file_data
|
138
|
+
wf = WavefrontCli::EventStore.new({ desc: 'test event' },
|
139
|
+
TEST_EVENT_STORE_DIR)
|
140
|
+
x = wf.event_file_data
|
141
|
+
assert_instance_of(String, x)
|
142
|
+
y = JSON.parse(x, symbolize_names: true)
|
143
|
+
assert_equal('test event', y[:description])
|
144
|
+
assert_equal(%i[hosts description severity tags], y.keys)
|
145
|
+
assert_nil(y[:tags])
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_create
|
149
|
+
refute (wf.dir + id).exist?
|
150
|
+
out, err = capture_io { wf.create!(id) }
|
151
|
+
assert_match(/Event state recorded at .*1481553823153:testev:0./, out)
|
152
|
+
assert_empty(err)
|
153
|
+
assert (wf.dir + id).exist?
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_create_with_nostate
|
157
|
+
wf1 = WavefrontCli::EventStore.new(nostate: true)
|
158
|
+
assert_nil wf1.create!(id)
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
def id
|
164
|
+
'1481553823153:testev:0'
|
165
|
+
end
|
166
|
+
|
167
|
+
def dummy_event_files
|
168
|
+
%w[1568133440510:ev1:0
|
169
|
+
1568133440515:ev1:1
|
170
|
+
1568133440520:ev2:0
|
171
|
+
1568133440530:ev3:0]
|
172
|
+
end
|
173
|
+
|
174
|
+
def setup_test_state_dir
|
175
|
+
dummy_event_files.each do |f|
|
176
|
+
File.open(wf.dir + f, 'w') { |fh| fh.puts('dummy_data') }
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def empty_test_state_dir
|
181
|
+
dummy_event_files.each do |f|
|
182
|
+
file = wf.dir + f
|
183
|
+
FileUtils.rm(file) if file.exist?
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -41,20 +41,36 @@ class ServiceAccountEndToEndTest < EndToEndTest
|
|
41
41
|
assert_abort_on_missing_creds("groups #{id}")
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
44
|
+
def test_roles
|
45
45
|
quietly do
|
46
|
-
assert_cmd_gets("
|
46
|
+
assert_cmd_gets("roles #{id}", "/api/v2/#{api_path}/#{id}")
|
47
47
|
end
|
48
48
|
|
49
|
-
assert_invalid_id("
|
50
|
-
assert_usage('
|
49
|
+
assert_invalid_id("roles #{invalid_id}")
|
50
|
+
assert_usage('roles')
|
51
51
|
|
52
52
|
assert_noop(
|
53
|
-
"
|
53
|
+
"roles #{id}",
|
54
54
|
"uri: GET https://default.wavefront.com/api/v2/#{api_path}/#{id}"
|
55
55
|
)
|
56
56
|
|
57
|
-
assert_abort_on_missing_creds("
|
57
|
+
assert_abort_on_missing_creds("roles #{id}")
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_ingestionpolicy
|
61
|
+
quietly do
|
62
|
+
assert_cmd_gets("ingestionpolicy #{id}", "/api/v2/#{api_path}/#{id}")
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_invalid_id("ingestionpolicy #{invalid_id}")
|
66
|
+
assert_usage('ingestionpolicy')
|
67
|
+
|
68
|
+
assert_noop(
|
69
|
+
"ingestionpolicy #{id}",
|
70
|
+
"uri: GET https://default.wavefront.com/api/v2/#{api_path}/#{id}"
|
71
|
+
)
|
72
|
+
|
73
|
+
assert_abort_on_missing_creds("ingestionpolicy #{id}")
|
58
74
|
end
|
59
75
|
|
60
76
|
def test_activate
|
@@ -85,7 +101,7 @@ class ServiceAccountEndToEndTest < EndToEndTest
|
|
85
101
|
'/api/v2/account/serviceaccount',
|
86
102
|
identifier: id,
|
87
103
|
active: true,
|
88
|
-
|
104
|
+
roles: [],
|
89
105
|
tokens: [],
|
90
106
|
userGroups: [])
|
91
107
|
end
|
@@ -95,8 +111,8 @@ class ServiceAccountEndToEndTest < EndToEndTest
|
|
95
111
|
'uri: POST https://default.wavefront.com/api/v2/account/serviceaccount',
|
96
112
|
'body: ' + { identifier: id,
|
97
113
|
active: true,
|
98
|
-
groups: [],
|
99
114
|
tokens: [],
|
115
|
+
roles: [],
|
100
116
|
userGroups: [] }.to_json
|
101
117
|
)
|
102
118
|
|
@@ -111,43 +127,56 @@ class ServiceAccountEndToEndTest < EndToEndTest
|
|
111
127
|
identifier: id,
|
112
128
|
description: 'words',
|
113
129
|
active: false,
|
114
|
-
|
130
|
+
roles: [],
|
115
131
|
tokens: [],
|
116
132
|
userGroups: [])
|
117
133
|
end
|
118
134
|
end
|
119
135
|
|
120
|
-
def
|
136
|
+
def test_create_account_with_usergroups
|
121
137
|
quietly do
|
122
138
|
assert_cmd_posts("create -g #{usergroups[0]} -g #{usergroups[1]} #{id}",
|
123
139
|
'/api/v2/account/serviceaccount',
|
124
140
|
identifier: id,
|
125
141
|
active: true,
|
126
|
-
groups: [],
|
127
142
|
tokens: [],
|
143
|
+
roles: [],
|
128
144
|
userGroups: usergroups)
|
129
145
|
end
|
130
146
|
end
|
131
147
|
|
148
|
+
def test_create_account_with_roles
|
149
|
+
quietly do
|
150
|
+
assert_cmd_posts("create -r #{roles[0]} -r #{roles[1]} #{id}",
|
151
|
+
'/api/v2/account/serviceaccount',
|
152
|
+
identifier: id,
|
153
|
+
active: true,
|
154
|
+
tokens: [],
|
155
|
+
roles: roles,
|
156
|
+
userGroups: [])
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
132
160
|
def test_create_account_with_tokens
|
133
161
|
quietly do
|
134
162
|
assert_cmd_posts("create -k #{tokens[0]} -k #{tokens[1]} #{id}",
|
135
163
|
'/api/v2/account/serviceaccount',
|
136
164
|
identifier: id,
|
137
165
|
active: true,
|
138
|
-
groups: [],
|
139
166
|
tokens: tokens,
|
167
|
+
roles: [],
|
140
168
|
userGroups: [])
|
141
169
|
end
|
142
170
|
end
|
143
171
|
|
144
|
-
def
|
172
|
+
def test_create_account_with_ingestion_policy
|
145
173
|
quietly do
|
146
|
-
assert_cmd_posts("create -p #{
|
174
|
+
assert_cmd_posts("create -p #{ingestion_policy} #{id}",
|
147
175
|
'/api/v2/account/serviceaccount',
|
148
176
|
identifier: id,
|
149
177
|
active: true,
|
150
|
-
|
178
|
+
ingestionPolicyId: ingestion_policy,
|
179
|
+
roles: [],
|
151
180
|
tokens: [],
|
152
181
|
userGroups: [])
|
153
182
|
end
|
@@ -158,8 +187,8 @@ class ServiceAccountEndToEndTest < EndToEndTest
|
|
158
187
|
"create -g abcdefg #{id}")
|
159
188
|
end
|
160
189
|
|
161
|
-
def
|
162
|
-
assert_exits_with("'123456' is not a valid
|
190
|
+
def test_create_invalid_ingestion_policy
|
191
|
+
assert_exits_with("'123456' is not a valid ingestion policy ID.",
|
163
192
|
"create -p 123456 #{id}")
|
164
193
|
end
|
165
194
|
|
@@ -358,8 +387,9 @@ class ServiceAccountEndToEndTest < EndToEndTest
|
|
358
387
|
'service account'
|
359
388
|
end
|
360
389
|
|
361
|
-
def
|
362
|
-
%w[
|
390
|
+
def roles
|
391
|
+
%w[07fc5cdd-0979-489e-8f70-325f39d15e55
|
392
|
+
0a42adf6-e738-4c5d-9e53-fd10bd979a31]
|
363
393
|
end
|
364
394
|
|
365
395
|
def tokens
|
@@ -372,6 +402,10 @@ class ServiceAccountEndToEndTest < EndToEndTest
|
|
372
402
|
abcdef12-1234-abcd-1234-abcdef012345]
|
373
403
|
end
|
374
404
|
|
405
|
+
def ingestion_policy
|
406
|
+
'test-policy-1607616352537'
|
407
|
+
end
|
408
|
+
|
375
409
|
def import_fields
|
376
410
|
%i[identifier description active tokens groups userGroups]
|
377
411
|
end
|
data/wavefront-cli.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |gem|
|
|
26
26
|
|
27
27
|
gem.add_runtime_dependency 'docopt', '~> 0.6.0'
|
28
28
|
gem.add_runtime_dependency 'inifile', '~> 3.0'
|
29
|
-
gem.add_runtime_dependency 'wavefront-sdk', '~> 5.4', '>= 5.4.
|
29
|
+
gem.add_runtime_dependency 'wavefront-sdk', '~> 5.4', '>= 5.4.2'
|
30
30
|
|
31
31
|
gem.add_development_dependency 'minitest', '~> 5.14'
|
32
32
|
gem.add_development_dependency 'rake', '~> 13.0'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wavefront-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.
|
4
|
+
version: 8.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Fisher
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docopt
|
@@ -47,7 +47,7 @@ dependencies:
|
|
47
47
|
version: '5.4'
|
48
48
|
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: 5.4.
|
50
|
+
version: 5.4.2
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -57,7 +57,7 @@ dependencies:
|
|
57
57
|
version: '5.4'
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: 5.4.
|
60
|
+
version: 5.4.2
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: minitest
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -232,6 +232,7 @@ files:
|
|
232
232
|
- lib/wavefront-cli/display/webhook.rb
|
233
233
|
- lib/wavefront-cli/display/write.rb
|
234
234
|
- lib/wavefront-cli/event.rb
|
235
|
+
- lib/wavefront-cli/event_store.rb
|
235
236
|
- lib/wavefront-cli/exception.rb
|
236
237
|
- lib/wavefront-cli/exception_handler.rb
|
237
238
|
- lib/wavefront-cli/externallink.rb
|
@@ -322,6 +323,7 @@ files:
|
|
322
323
|
- spec/wavefront-cli/display/printer/long_spec.rb
|
323
324
|
- spec/wavefront-cli/display/printer/terse_spec.rb
|
324
325
|
- spec/wavefront-cli/event_spec.rb
|
326
|
+
- spec/wavefront-cli/event_store_spec.rb
|
325
327
|
- spec/wavefront-cli/externallink_spec.rb
|
326
328
|
- spec/wavefront-cli/integration_spec.rb
|
327
329
|
- spec/wavefront-cli/maintenancewindow_spec.rb
|
@@ -461,6 +463,7 @@ test_files:
|
|
461
463
|
- spec/wavefront-cli/display/printer/long_spec.rb
|
462
464
|
- spec/wavefront-cli/display/printer/terse_spec.rb
|
463
465
|
- spec/wavefront-cli/event_spec.rb
|
466
|
+
- spec/wavefront-cli/event_store_spec.rb
|
464
467
|
- spec/wavefront-cli/externallink_spec.rb
|
465
468
|
- spec/wavefront-cli/integration_spec.rb
|
466
469
|
- spec/wavefront-cli/maintenancewindow_spec.rb
|