splunk-sdk-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. data/CHANGELOG.md +160 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE +177 -0
  4. data/README.md +310 -0
  5. data/Rakefile +40 -0
  6. data/examples/1_connect.rb +51 -0
  7. data/examples/2_manage.rb +103 -0
  8. data/examples/3_blocking_searches.rb +82 -0
  9. data/examples/4_asynchronous_searches.rb +79 -0
  10. data/examples/5_stream_data_to_splunk.rb +79 -0
  11. data/lib/splunk-sdk-ruby.rb +47 -0
  12. data/lib/splunk-sdk-ruby/ambiguous_entity_reference.rb +28 -0
  13. data/lib/splunk-sdk-ruby/atomfeed.rb +323 -0
  14. data/lib/splunk-sdk-ruby/collection.rb +417 -0
  15. data/lib/splunk-sdk-ruby/collection/apps.rb +35 -0
  16. data/lib/splunk-sdk-ruby/collection/case_insensitive_collection.rb +58 -0
  17. data/lib/splunk-sdk-ruby/collection/configuration_file.rb +50 -0
  18. data/lib/splunk-sdk-ruby/collection/configurations.rb +80 -0
  19. data/lib/splunk-sdk-ruby/collection/jobs.rb +136 -0
  20. data/lib/splunk-sdk-ruby/collection/messages.rb +51 -0
  21. data/lib/splunk-sdk-ruby/context.rb +522 -0
  22. data/lib/splunk-sdk-ruby/entity.rb +260 -0
  23. data/lib/splunk-sdk-ruby/entity/index.rb +191 -0
  24. data/lib/splunk-sdk-ruby/entity/job.rb +339 -0
  25. data/lib/splunk-sdk-ruby/entity/message.rb +36 -0
  26. data/lib/splunk-sdk-ruby/entity/saved_search.rb +71 -0
  27. data/lib/splunk-sdk-ruby/entity/stanza.rb +45 -0
  28. data/lib/splunk-sdk-ruby/entity_not_ready.rb +26 -0
  29. data/lib/splunk-sdk-ruby/illegal_operation.rb +27 -0
  30. data/lib/splunk-sdk-ruby/namespace.rb +239 -0
  31. data/lib/splunk-sdk-ruby/resultsreader.rb +716 -0
  32. data/lib/splunk-sdk-ruby/service.rb +339 -0
  33. data/lib/splunk-sdk-ruby/splunk_http_error.rb +49 -0
  34. data/lib/splunk-sdk-ruby/synonyms.rb +50 -0
  35. data/lib/splunk-sdk-ruby/version.rb +27 -0
  36. data/lib/splunk-sdk-ruby/xml_shim.rb +117 -0
  37. data/splunk-sdk-ruby.gemspec +27 -0
  38. data/test/atom_test_data.rb +472 -0
  39. data/test/data/atom/atom_feed_with_message.xml +19 -0
  40. data/test/data/atom/atom_with_feed.xml +99 -0
  41. data/test/data/atom/atom_with_several_entries.xml +101 -0
  42. data/test/data/atom/atom_with_simple_entries.xml +30 -0
  43. data/test/data/atom/atom_without_feed.xml +248 -0
  44. data/test/data/export/4.2.5/export_results.xml +88 -0
  45. data/test/data/export/4.3.5/export_results.xml +87 -0
  46. data/test/data/export/5.0.1/export_results.xml +78 -0
  47. data/test/data/export/5.0.1/nonreporting.xml +232 -0
  48. data/test/data/results/4.2.5/results-empty.xml +0 -0
  49. data/test/data/results/4.2.5/results-preview.xml +255 -0
  50. data/test/data/results/4.2.5/results.xml +336 -0
  51. data/test/data/results/4.3.5/results-empty.xml +0 -0
  52. data/test/data/results/4.3.5/results-preview.xml +1057 -0
  53. data/test/data/results/4.3.5/results.xml +626 -0
  54. data/test/data/results/5.0.2/results-empty.xml +1 -0
  55. data/test/data/results/5.0.2/results-empty_preview.xml +1 -0
  56. data/test/data/results/5.0.2/results-preview.xml +448 -0
  57. data/test/data/results/5.0.2/results.xml +501 -0
  58. data/test/export_test_data.json +360 -0
  59. data/test/resultsreader_test_data.json +1119 -0
  60. data/test/services.server.info.xml +43 -0
  61. data/test/services.xml +111 -0
  62. data/test/test_atomfeed.rb +71 -0
  63. data/test/test_collection.rb +278 -0
  64. data/test/test_configuration_file.rb +124 -0
  65. data/test/test_context.rb +119 -0
  66. data/test/test_entity.rb +95 -0
  67. data/test/test_helper.rb +250 -0
  68. data/test/test_http_error.rb +52 -0
  69. data/test/test_index.rb +91 -0
  70. data/test/test_jobs.rb +319 -0
  71. data/test/test_messages.rb +17 -0
  72. data/test/test_namespace.rb +188 -0
  73. data/test/test_restarts.rb +49 -0
  74. data/test/test_resultsreader.rb +106 -0
  75. data/test/test_roles.rb +41 -0
  76. data/test/test_saved_searches.rb +119 -0
  77. data/test/test_service.rb +65 -0
  78. data/test/test_users.rb +33 -0
  79. data/test/test_xml_shim.rb +28 -0
  80. data/test/testfile.txt +1 -0
  81. metadata +200 -0
@@ -0,0 +1,52 @@
1
+ require_relative 'test_helper'
2
+
3
+ require 'splunk-sdk-ruby'
4
+
5
+ class MockResponse
6
+ include Enumerable
7
+
8
+ attr_reader :code, :message, :body
9
+
10
+ def initialize(code, message, headers, body)
11
+ @code = code
12
+ @message = message
13
+ @headers = headers
14
+ @body = body
15
+ end
16
+
17
+ def each(&block)
18
+ @headers.each(&block)
19
+ end
20
+ end
21
+
22
+ include Splunk
23
+
24
+ class TestHTTPError < TestCaseWithSplunkConnection
25
+ def test_error_with_empty_message
26
+ response = MockResponse.new(code=400, message="Meep",
27
+ headers={}, body="")
28
+ err = SplunkHTTPError.new(response)
29
+ assert_nil(err.detail)
30
+ assert_equal(response.code, err.code)
31
+ assert_equal(response.message, err.reason)
32
+ assert_equal("HTTP 400 Meep: ", err.message)
33
+ end
34
+
35
+ def test_error_with_message
36
+ response = MockResponse.new(
37
+ code=400, message="Index Error", headers={},
38
+ body = "<response><messages>" +
39
+ "<msg type=\"ERROR\">In handler &apos;indexes&apos;: " +
40
+ "Index name=boris already exists</msg></messages></response>")
41
+ err = SplunkHTTPError.new(response)
42
+ assert_equal("In handler 'indexes': Index name=boris already exists",
43
+ err.detail)
44
+ assert_equal(400, err.code)
45
+ assert_equal("Index Error", err.reason)
46
+ assert_equal([], err.headers)
47
+ assert_equal("HTTP 400 Index Error: In handler 'indexes': " +
48
+ "Index name=boris already exists",
49
+ err.message)
50
+ end
51
+
52
+ end
@@ -0,0 +1,91 @@
1
+ require_relative 'test_helper'
2
+ require 'splunk-sdk-ruby'
3
+
4
+ include Splunk
5
+
6
+ class IndexTestCase < TestCaseWithSplunkConnection
7
+ def setup
8
+ super
9
+
10
+ @index_name = temporary_name()
11
+ @index = @service.indexes.create(@index_name)
12
+ assert_eventually_true() do
13
+ @index.refresh()["disabled"] == "0"
14
+ end
15
+ end
16
+
17
+ def teardown
18
+ if @service.splunk_version[0] >= 5
19
+ @service.indexes.
20
+ select() { |index| index.name.start_with?("delete-me")}.
21
+ each() do |index|
22
+ if index.fetch("disabled") == "1"
23
+ index.enable()
24
+ end
25
+ index.delete()
26
+ end
27
+ end
28
+
29
+ super
30
+ end
31
+
32
+ def test_delete
33
+ if @service.splunk_version[0] < 5
34
+ return
35
+ end
36
+ assert_true(@service.indexes.has_key?(@index_name))
37
+ @service.indexes.delete(@index_name)
38
+ assert_eventually_true() do
39
+ !@service.indexes.has_key?(@index_name)
40
+ end
41
+ end
42
+
43
+ def test_disable_enable
44
+ @index.disable()
45
+ checked_restart(@service)
46
+ @index.refresh()
47
+ assert_equal('1', @index["disabled"])
48
+
49
+ @index.enable()
50
+ @index.refresh()
51
+ assert_equal("0", @index["disabled"])
52
+ end
53
+
54
+ def test_submit_via_attach
55
+ event_count = Integer(@index["totalEventCount"])
56
+ socket = @index.attach()
57
+ socket.write("Hello, Boris!\r\n")
58
+ socket.close()
59
+ assert_eventually_true(10) do
60
+ Integer(@index.refresh()["totalEventCount"]) == event_count+1
61
+ end
62
+ end
63
+
64
+ def test_submit_and_clean
65
+ original_count = Integer(@index.refresh()["totalEventCount"])
66
+ @index.submit("Boris 1", :sourcetype => "Boris", :host => "Meep")
67
+ @index.submit("Boris 2", :sourcetype => "Boris", :host => "Meep")
68
+ assert_eventually_true(100) do
69
+ Integer(@index.refresh()["totalEventCount"]) == original_count + 2
70
+ end
71
+
72
+ @index.clean(timeout=500)
73
+ assert_equal(0, Integer(@index.refresh()["totalEventCount"]))
74
+ end
75
+
76
+ def test_upload
77
+ if !has_app_collection?(@service)
78
+ print "Test requires sdk-app-collection. Skipping."
79
+ return
80
+ end
81
+
82
+ install_app_from_collection("file_to_upload")
83
+
84
+ original_count = Integer(@index.refresh().fetch("totalEventCount"))
85
+ @index.upload(path_in_app("file_to_upload", ["log.txt"]))
86
+
87
+ assert_eventually_true() do
88
+ Integer(@index.refresh()["totalEventCount"]) == original_count + 4
89
+ end
90
+ end
91
+ end
data/test/test_jobs.rb ADDED
@@ -0,0 +1,319 @@
1
+ require_relative 'test_helper'
2
+ require 'splunk-sdk-ruby'
3
+
4
+ include Splunk
5
+
6
+ QUERY = "search index=_internal | head 3"
7
+ JOB_ARGS = {:earliest_time => "-1m", :latest_time => "now",
8
+ :status_buckets => 10}
9
+
10
+ class JobsTestCase < TestCaseWithSplunkConnection
11
+ def test_create_with_garbage_fails
12
+ assert_raises(SplunkHTTPError) do
13
+ @service.jobs.create("aweaj;awfaw faf'adf")
14
+ end
15
+ end
16
+
17
+ def test_create_and_idempotent_cancel
18
+ jobs = @service.jobs
19
+ job = jobs.create(QUERY)
20
+ assert_true(jobs.has_key?(job.sid))
21
+ job.cancel()
22
+ assert_eventually_true() { !jobs.has_key?(job.sid) }
23
+ job.cancel() # Cancel twice should be a nop
24
+ end
25
+
26
+ ##
27
+ # There is a convenience method on service to create an asynchronous
28
+ # search job. Test it the same way.
29
+ #
30
+ def service_create_and_idempotent_cancel
31
+ jobs = @service.jobs
32
+ job = @service.create(QUERY)
33
+ assert_true(jobs.has_key?(job.sid))
34
+ job.cancel()
35
+ assert_eventually_true() { !jobs.has_key?(job.sid) }
36
+ job.cancel() # Cancel twice should be a nop
37
+ end
38
+
39
+ def test_create_with_exec_mode_fails
40
+ assert_raises(ArgumentError) do
41
+ @service.jobs.create(QUERY, :exec_mode => "oneshot")
42
+ end
43
+ end
44
+
45
+ def test_oneshot
46
+ jobs = @service.jobs
47
+ stream = jobs.create_oneshot(QUERY)
48
+ results = ResultsReader.new(stream)
49
+ assert_false(results.is_preview?)
50
+ events = results.to_a()
51
+ assert_equal(3, events.length())
52
+ end
53
+
54
+ ##
55
+ # Test that Service#create_oneshot properly creates a oneshot search.
56
+ #
57
+ def test_oneshot_on_service
58
+ jobs = @service.jobs
59
+ stream = @service.create_oneshot(QUERY)
60
+ results = ResultsReader.new(stream)
61
+ assert_false(results.is_preview?)
62
+ events = results.to_a()
63
+ assert_equal(3, events.length())
64
+ end
65
+
66
+ def test_oneshot_with_garbage_fails
67
+ assert_raises(SplunkHTTPError) do
68
+ @service.jobs.create_oneshot("abcwrawerafawf 'adfad'faw")
69
+ end
70
+ end
71
+
72
+ def test_export_with_garbage_fails
73
+ assert_raises(SplunkHTTPError) do
74
+ @service.jobs.create_export("abavadfa;ejwfawfasdfadf wfw").to_a()
75
+ end
76
+ end
77
+
78
+ def test_export
79
+ stream = @service.jobs.create_export(QUERY)
80
+ assert_true(stream.is_a?(ExportStream))
81
+ results = ResultsReader.new(stream).to_a()
82
+ assert_equal(3, results.length())
83
+ end
84
+
85
+ ##
86
+ # Test that the convenience method Service#create_export behaves the same
87
+ # way as Jobs#create_export.
88
+ #
89
+ def test_export_on_service
90
+ stream = @service.create_export(QUERY)
91
+ results = ResultsReader.new(stream).to_a()
92
+ assert_equal(3, results.length())
93
+ end
94
+
95
+ ##
96
+ # Test that ResultsReader parses reporting export searches correctly
97
+ # (by only returning the final, nonpreview results).
98
+ #
99
+ def test_export_on_reporting_search
100
+ stream = @service.create_export("search index=_internal earliest=-2d | stats count(_raw) by method")
101
+ results = ResultsReader.new(stream).to_a()
102
+ assert_true(3 >= results.length())
103
+ end
104
+
105
+ def test_each_and_values
106
+ jobs = Jobs.new(@service)
107
+
108
+ created_jobs = []
109
+
110
+ (1..3).each() do |i|
111
+ job = jobs.create("search index=_internal | head #{i}")
112
+ while !job.is_ready?
113
+ sleep(0.1)
114
+ end
115
+ created_jobs << job
116
+ end
117
+
118
+ each_jobs = []
119
+ jobs.each() do |job|
120
+ assert_false(job.name.empty?)
121
+ each_jobs << job.sid
122
+ end
123
+
124
+ values_jobs = jobs.values().map() { |j| j.sid }
125
+ assert_equal(each_jobs, values_jobs)
126
+
127
+ created_jobs.each do |job|
128
+ job.cancel()
129
+ end
130
+ end
131
+
132
+ def test_preview_and_events
133
+ job = @service.jobs.create(QUERY, JOB_ARGS)
134
+ assert_eventually_true() { job.is_done?() }
135
+ assert_true(Integer(job['eventCount']) <= 3)
136
+
137
+ preview_stream = job.preview()
138
+ preview_results = ResultsReader.new(preview_stream)
139
+ assert_false(preview_results.is_preview?)
140
+ preview_array = preview_results.to_a()
141
+
142
+ events_stream = job.events()
143
+ events_results = ResultsReader.new(events_stream)
144
+ assert_false(events_results.is_preview?)
145
+ events_array = events_results.to_a()
146
+
147
+ results_stream = job.results()
148
+ results_results = ResultsReader.new(results_stream)
149
+ assert_false(results_results.is_preview?)
150
+ results_array = results_results.to_a()
151
+
152
+ assert_equal(events_array, preview_array)
153
+ assert_equal(results_array, preview_array)
154
+
155
+ job.cancel()
156
+ end
157
+
158
+ def test_timeline
159
+ original_xml_library = $splunk_xml_library
160
+ job = @service.jobs.create(QUERY, JOB_ARGS)
161
+ assert_eventually_true() { job.is_done?() }
162
+
163
+ begin
164
+ Splunk::require_xml_library(:rexml)
165
+ timeline = job.timeline()
166
+ assert_true(timeline.is_a?(Array))
167
+
168
+ Splunk::require_xml_library(:nokogiri)
169
+ timeline = job.timeline()
170
+ assert_true(timeline.is_a?(Array))
171
+ ensure
172
+ # Have to reset the XML library or test_resultsreader gets unhappy.
173
+ Splunk::require_xml_library(original_xml_library)
174
+ job.cancel()
175
+ end
176
+ end
177
+
178
+ def test_enable_preview
179
+ begin
180
+ install_app_from_collection("sleep_command")
181
+ job = @service.jobs.create("search index=_internal | sleep 2 | join [sleep 2]")
182
+ while !job.is_ready?()
183
+ sleep(0.1)
184
+ end
185
+ assert_equal("0", job["isPreviewEnabled"])
186
+ job.enable_preview()
187
+ assert_eventually_true(1000) do
188
+ job.refresh()
189
+ fail("Job finished before preview enabled") if job.is_done?()
190
+ job["isPreviewEnabled"] == "1"
191
+ end
192
+ ensure
193
+ job.cancel()
194
+ assert_eventually_true do
195
+ !@service.jobs.contains?(job.sid)
196
+ end
197
+ # We have to wait for jobs to be properly killed or we can't delete
198
+ # the sleep_command app in teardown on Windows.
199
+ sleep(4)
200
+ end
201
+ end
202
+ end
203
+
204
+ class LongJobTestCase < JobsTestCase
205
+ def setup
206
+ super
207
+
208
+ install_app_from_collection("sleep_command")
209
+ @job = @service.jobs.create("search index=_internal | sleep 20")
210
+ while !@job.is_ready?()
211
+ sleep(0.1)
212
+ end
213
+ end
214
+
215
+ def teardown
216
+ if @job
217
+ @job.cancel()
218
+ assert_eventually_true(50) do
219
+ !@service.jobs.has_key?(@job.sid)
220
+ end
221
+ end
222
+
223
+ super
224
+ end
225
+
226
+ def test_setttl
227
+ old_ttl = Integer(@job["ttl"])
228
+ new_ttl = old_ttl + 1000
229
+
230
+ @job.set_ttl(new_ttl)
231
+ assert_eventually_true() do
232
+ @job.refresh()
233
+ ttl = Integer(@job["ttl"])
234
+ ttl <= new_ttl && ttl > old_ttl
235
+ end
236
+ end
237
+
238
+ def test_touch
239
+ i = 2
240
+ while i < 20
241
+ sleep(i)
242
+ old_ttl = Integer(@job.refresh()["ttl"])
243
+ @job.touch()
244
+ new_ttl = Integer(@job.refresh()["ttl"])
245
+ if new_ttl > old_ttl
246
+ break
247
+ else
248
+ i += 1
249
+ end
250
+ end
251
+ assert_true(new_ttl > old_ttl)
252
+ end
253
+ end
254
+
255
+ class RealTimeJobTestCase < JobsTestCase
256
+ def setup
257
+ super
258
+ query = "search index=_internal"
259
+ @job = @service.jobs.create(query,
260
+ :earliest_time => "rt-1d",
261
+ :latest_time => "rt",
262
+ :priority => 5)
263
+ while !@job.is_ready?
264
+ sleep(0.2)
265
+ end
266
+ end
267
+
268
+ def teardown
269
+ if @job
270
+ @job.cancel()
271
+ assert_eventually_true() do
272
+ !@service.jobs.has_key?(@job.sid)
273
+ end
274
+ end
275
+
276
+ super
277
+ end
278
+
279
+ def test_set_priority
280
+ assert_equal("5", @job["priority"])
281
+ sleep(1)
282
+ new_priority = 3
283
+ @job.set_priority(new_priority)
284
+ assert_eventually_true(50) do
285
+ @job.refresh()
286
+ fail("Job finished before priority was set.") if @job.is_done?()
287
+ @job["priority"] == "3"
288
+ end
289
+ end
290
+
291
+ def test_get_preview
292
+ assert_equal("1", @job["isPreviewEnabled"])
293
+ assert_eventually_true do
294
+ response = @job.preview()
295
+ results = Splunk::ResultsReader.new(response)
296
+ results.is_preview?
297
+ end
298
+ end
299
+
300
+ def test_pause_unpause_finalize
301
+ assert_equal("0", @job["isPaused"])
302
+
303
+ @job.pause()
304
+ assert_eventually_true() { @job.refresh()["isPaused"] == "1" }
305
+
306
+ @job.unpause()
307
+ assert_eventually_true() { @job.refresh()["isPaused"] == "0" }
308
+
309
+ assert_equal("0", @job["isFinalized"])
310
+
311
+ @job.finalize()
312
+ assert_eventually_true() { @job.refresh()["isFinalized"] == "1" }
313
+ end
314
+
315
+ def test_searchlog
316
+ log_stream = @job.searchlog
317
+ assert_false(log_stream.empty?)
318
+ end
319
+ end