wavefront-cli 8.4.1 → 8.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|