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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d96bb27765c031f9998dfa45406581de1852f0fbdc0abff4bcea45b679963299
4
- data.tar.gz: d40011ef4d521dd738fb594095366ee7e506bc35c9bad83e2ad421eeedab16bb
3
+ metadata.gz: 363b1be94331165aacf1538c797d07bdbefda71e801335bb4e35df97cb0bd950
4
+ data.tar.gz: 5563b27f93c679dde5947c220d80c37816ba6faf8844d08111cbf7dcc65a76c1
5
5
  SHA512:
6
- metadata.gz: f4777538a7b6f116f56c24382b9f3ea54ca78d5306009a3876857ff963f481561ff28e5c925cf0e62152e686caaa3c54e3abe90f48f16cb6e7cd6f87ede9f857
7
- data.tar.gz: 1bfab61e86f92ff9284207627615f07a701092afb6bd6f839471833db3610fb60c8e013c56b57a50329c67650e1a778c6581adb61804f4365675cb1838cb7c4f
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 offset] [-L limit] [-l] [-O fields] <condition>...",
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 permission...] [-g group...] " \
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
- "permissions #{CMN} <id>",
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
- "-p, --permission=STRING give #{thing} this permission",
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 do_permissions
42
- if data[:groups].empty?
43
- puts 'Account does not have any Wavefront permissions.'
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[:groups]
53
+ puts format('%<id>s (%<name>s)', data[:ingestionPolicy])
46
54
  end
47
55
  end
48
56
 
@@ -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 :state_dir
13
+ attr_reader :state
16
14
 
17
15
  include Wavefront::Mixins
18
16
  include WavefrontCli::Mixin::Tag
19
17
 
20
- def post_initialize(_options)
21
- @state_dir = event_state_dir + (Etc.getlogin || 'notty')
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
- create_state_file(resp.response[:id]) if state_file_needed?(opts)
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
- def event_file(id)
62
- id =~ /^\d{13}:.+/ ? state_dir + id : nil
34
+ state.create!(resp.response[:id])
35
+ resp
63
36
  end
64
37
 
65
38
  def do_show
66
- events = local_event_list
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
- # We can override the temp directory with the WF_EVENT_STATE_DIR. This is
88
- # primarily for testing.
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 event_state_dir
91
- if ENV['WF_EVENT_STATE_DIR']
92
- Pathname.new(ENV['WF_EVENT_STATE_DIR'])
93
- else
94
- EVENT_STATE_DIR
95
- end
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 do_permissions do_describe
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
- validate_perms
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
- groups: options[:permission],
165
+ ingestionPolicyId: options[:policy],
164
166
  tokens: options[:usertoken],
165
- userGroups: options[:group] }.tap do |b|
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 validate_perms
183
- options[:permission].each { |p| wf_permission?(p) }
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
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- WF_CLI_VERSION = '8.4.1'
3
+ WF_CLI_VERSION = '8.5.0'
@@ -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::Tags
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
- "mytag #{event_name}",
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 test_show
216
- setup_test_state_dir
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
- out, err = capture_io do
219
- assert_raises(SystemExit) { wf.new("event show -c #{CF}".split) }
220
- end
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
- assert_empty(err)
223
- assert_equal("1568133440530:ev3:0\n1568133440520:ev2:0\n" \
224
- "1568133440515:ev1:1\n1568133440510:ev1:0\n", out)
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 import_fields
250
- %i[method title creatorId triggers template]
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
- private
355
-
356
- def wall_time
357
- [Time.at(1_568_112_000), Time.at(1_568_112_999)]
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 test_permissions
44
+ def test_roles
45
45
  quietly do
46
- assert_cmd_gets("permissions #{id}", "/api/v2/#{api_path}/#{id}")
46
+ assert_cmd_gets("roles #{id}", "/api/v2/#{api_path}/#{id}")
47
47
  end
48
48
 
49
- assert_invalid_id("permissions #{invalid_id}")
50
- assert_usage('permissions')
49
+ assert_invalid_id("roles #{invalid_id}")
50
+ assert_usage('roles')
51
51
 
52
52
  assert_noop(
53
- "permissions #{id}",
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("permissions #{id}")
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
- groups: [],
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
- groups: [],
130
+ roles: [],
115
131
  tokens: [],
116
132
  userGroups: [])
117
133
  end
118
134
  end
119
135
 
120
- def test_create_account_in_usergroups
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 test_create_account_with_permissions
172
+ def test_create_account_with_ingestion_policy
145
173
  quietly do
146
- assert_cmd_posts("create -p #{permissions[0]} -p #{permissions[1]} #{id}",
174
+ assert_cmd_posts("create -p #{ingestion_policy} #{id}",
147
175
  '/api/v2/account/serviceaccount',
148
176
  identifier: id,
149
177
  active: true,
150
- groups: permissions,
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 test_create_invalid_permission
162
- assert_exits_with("'123456' is not a valid Wavefront permission.",
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 permissions
362
- %w[alerts_management events_management]
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
@@ -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.1'
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.1
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-04 00:00:00.000000000 Z
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.1
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.1
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