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,339 @@
1
+ #--
2
+ # Copyright 2011-2013 Splunk, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"): you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #++
16
+
17
+ require_relative 'atomfeed'
18
+ require_relative 'collection'
19
+ require_relative 'collection/apps'
20
+ require_relative 'collection/configurations'
21
+ require_relative 'collection/jobs'
22
+ require_relative 'collection/messages'
23
+ require_relative 'collection/case_insensitive_collection'
24
+ require_relative 'context'
25
+ require_relative 'entity'
26
+ require_relative 'entity/index'
27
+ require_relative 'entity/job'
28
+ require_relative 'entity/message'
29
+ require_relative 'entity/saved_search'
30
+ require_relative 'entity/stanza'
31
+
32
+ ##
33
+ # This module provides the +Service+ class, which encapsulates the interaction
34
+ # with Splunk.
35
+ #
36
+
37
+ module Splunk
38
+ # The paths used by service.
39
+ PATH_APPS_LOCAL = ["apps", "local"]
40
+ PATH_CAPABILITIES = ["authorization", "capabilities"]
41
+ PATH_LOGGER = ["server","logger"]
42
+ PATH_ROLES = ["authentication", "roles"]
43
+ PATH_USERS = ['authentication','users']
44
+ PATH_MESSAGES = ['messages']
45
+ PATH_INFO = ["server", "info"]
46
+ PATH_SETTINGS = ["server", "settings"]
47
+ PATH_INDEXES = ["data","indexes"]
48
+ PATH_CONFS = ["properties"]
49
+ PATH_CONF = ["configs"]
50
+ PATH_SAVED_SEARCHES = ["saved", "searches"]
51
+ PATH_STANZA = ["configs","conf-%s","%s"]
52
+ PATH_JOBS = ["search", "jobs"]
53
+ PATH_EXPORT = ["search", "jobs", "export"]
54
+
55
+ ##
56
+ # Create a logged in reference to a Splunk instance.
57
+ #
58
+ # +connect+ takes a hash of values as its sole argument. The keys it
59
+ # understands are:
60
+ #
61
+ # * `:username` - log in to Splunk as this user (no default)
62
+ # * `:password` - password to use when logging in (no default)
63
+ # * `:host` - Splunk host (e.g. "10.1.2.3") (defaults to 'localhost')
64
+ # * `:port` - the Splunk management port (defaults to '8089')
65
+ # * `:protocol` - either 'https' or 'http' (defaults to 'https')
66
+ # * `:namespace` - application namespace option. 'username:appname'
67
+ # (defaults to nil)
68
+ # * `:token` - a preauthenticated Splunk token (default to nil)
69
+ #
70
+ # Returns: a logged in +Service+ object.
71
+ #
72
+ # *Example:*
73
+ #
74
+ # require 'splunk-sdk-ruby'
75
+ # service = Splunk::connect(:username => "admin", :password => "changeme")
76
+ #
77
+ def self.connect(args)
78
+ Service.new(args).login()
79
+ end
80
+
81
+ ##
82
+ # A user friendly interface to the Splunk REST API.
83
+ #
84
+ # +Service+ subclasses +Context+ (which provides the methods to login to
85
+ # Splunk and make requests to the REST API), and adds convenience methods
86
+ # for accessing the major collections of entities, such as indexes,
87
+ # search jobs, and configurations.
88
+ #
89
+ class Service < Context
90
+ ##
91
+ # Returns a collection of all the apps installed on Splunk.
92
+ #
93
+ # Returns a +Collection+ containing +Entity+ objects.
94
+ #
95
+ # *Examples:*:
96
+ #
97
+ # require 'splunk-sdk-ruby'
98
+ # service = Splunk::connect(:username => 'admin',
99
+ # :password => 'changeme')
100
+ # service.apps.each do |app|
101
+ # puts app.name
102
+ # end
103
+ #
104
+ def apps
105
+ Apps.new(self, PATH_APPS_LOCAL)
106
+ end
107
+
108
+ ##
109
+ # Returns an +Array+ of all the capabilities roles may have in Splunk.
110
+ #
111
+ # Capabilities are a fixed list on the server, so this method returns
112
+ # an +Array+ rather than an +Entity+.
113
+ #
114
+ # Returns: an +Array+ of +Strings+.
115
+ #
116
+ # *Example:*
117
+ #
118
+ # service = Splunk::connect(:username => 'admin',
119
+ # :password => 'changeme')
120
+ # puts service.capabilities
121
+ # # Prints: ["admin_all_objects", "change_authentication",
122
+ # # "change_own_password", "delete_by_keyword", ...]
123
+ def capabilities
124
+ response = request(:resource => PATH_CAPABILITIES)
125
+ feed = AtomFeed.new(response.body)
126
+ feed.entries[0]["content"]["capabilities"]
127
+ end
128
+
129
+ ##
130
+ # Returns a +Collection+ of all the configuration files visible on Splunk.
131
+ #
132
+ # The configurations you see are dependent on the namespace your +Service+
133
+ # is connected with. So if you are connected in the system namespace, you
134
+ # may see different values than if you're connected in the app namespace
135
+ # associated with a particular app, since the app may override some values
136
+ # within its scope.
137
+ #
138
+ # The configuration files which are the contents of this +Collection+ are
139
+ # not +Entity+ objects, but +Collection+ objects in their own right. They
140
+ # contain +Entity+ objects representing the stanzas in that configuration
141
+ # file.
142
+ #
143
+ # Returns: +Configurations+ (a subclass of +Collection+ containing
144
+ # +ConfigurationFile+ objects).
145
+ #
146
+ def confs
147
+ Configurations.new(self)
148
+ end
149
+
150
+ ##
151
+ # Creates a blocking search.
152
+ #
153
+ # The +create_oneshot+ method starts a search _query_, and any optional
154
+ # arguments specified in a hash (which are identical to those taken by
155
+ # +create+). It then blocks until the job finished, and returns the
156
+ # results, as transformed by any transforming search commands in _query_
157
+ # (equivalent to calling the +results+ method on a +Job+).
158
+ #
159
+ # Returns: a stream readable by +ResultsReader+.
160
+ #
161
+ def create_oneshot(query, args={})
162
+ jobs.create_oneshot(query, args)
163
+ end
164
+
165
+ ##
166
+ # Creates an asynchronous search job.
167
+ #
168
+ # The search job requires a _query_, and takes a hash of other, optional
169
+ # arguments, which are documented in the {Splunk REST documentation}[http://docs.splunk.com/Documentation/Splunk/latest/RESTAPI/RESTsearch#search.2Fjobs].
170
+ #
171
+ def create_search(query, args={})
172
+ jobs.create(query, args)
173
+ end
174
+
175
+ ##
176
+ # Creates a blocking search without transforming search commands.
177
+ #
178
+ # The +create_export+ method starts a search _query_, and any optional
179
+ # arguments specified in a hash (which are identical to those taken by
180
+ # the +create+ methods). It then blocks until the job is finished, and
181
+ # returns the events found by the job before any transforming search
182
+ # commands (equivalent to calling +events+ on a +Job+).
183
+ #
184
+ # Returns: a stream readable by +MultiResultsReader+.
185
+ #
186
+ def create_export(query, args={}) # :nodoc:
187
+ jobs.create_export(query, args)
188
+ end
189
+
190
+ # DEPRECATED. Use create_export instead.
191
+ def create_stream(query, args={})
192
+ warn "[DEPRECATION] Service#create_stream is deprecated. Use Service#create_export instead."
193
+ jobs.create_export(query, args)
194
+ end
195
+
196
+ ##
197
+ # Returns a +Collection+ of all +Index+ objects.
198
+ #
199
+ # +Index+ is a subclass of +Entity+, with additional methods for
200
+ # manipulating indexes in particular.
201
+ #
202
+ def indexes
203
+ Collection.new(self, PATH_INDEXES, entity_class=Index)
204
+ end
205
+
206
+ ##
207
+ # Returns a +Hash+ containing Splunk's runtime information.
208
+ #
209
+ # The +Hash+ has keys such as "+build+" (the number of the build of this
210
+ # Splunk instance) and "+cpu_arch+" (what CPU Splunk is running on), and
211
+ # "+os_name+" (the name of the operating system Splunk is running on).
212
+ #
213
+ # Returns: A +Hash+ that has +Strings+ as both keys and values.
214
+ #
215
+ def info
216
+ response = request(:namespace => Splunk::namespace(:sharing => "default"),
217
+ :resource => PATH_INFO)
218
+ feed = AtomFeed.new(response.body)
219
+ feed.entries[0]["content"]
220
+ end
221
+
222
+ ##
223
+ # Returns a collection of all the search jobs running on Splunk.
224
+ #
225
+ # The +Jobs+ object returned is a subclass of +Collection+, but also has
226
+ # convenience methods for starting oneshot and streaming jobs as well as
227
+ # creating normal, asynchronous jobs.
228
+ #
229
+ # Returns: A +Jobs+ object.
230
+ def jobs
231
+ Jobs.new(self)
232
+ end
233
+
234
+ ##
235
+ # Returns a collection of the loggers in Splunk.
236
+ #
237
+ # Each logger logs errors, warnings, debug info, or informational
238
+ # information about a specific part of the Splunk system (e.g.,
239
+ # +WARN+ on +DeploymentClient+).
240
+ #
241
+ # Returns: a +Collection+ of +Entity+ objects representing loggers.
242
+ #
243
+ # *Example*:
244
+ # service = Splunk::connect(:username => 'admin', :password => 'foo')
245
+ # service.loggers.each do |logger|
246
+ # puts logger.name + ":" + logger['level']
247
+ # end
248
+ # # Prints:
249
+ # # ...
250
+ # # DedupProcessor:WARN
251
+ # # DeployedApplication:INFO
252
+ # # DeployedServerClass:WARN
253
+ # # DeploymentClient:WARN
254
+ # # DeploymentClientAdminHandler:WARN
255
+ # # DeploymentMetrics:INFO
256
+ # # ...
257
+ #
258
+ def loggers
259
+ Collection.new(self, PATH_LOGGER)
260
+ end
261
+
262
+ ##
263
+ # Returns a collection of the global messages on Splunk.
264
+ #
265
+ # Messages include such things as warnings and notices that Splunk needs to
266
+ # restart.
267
+ #
268
+ # Returns: A +Collection+ of +Message+ objects (which are subclasses
269
+ # of +Entity+).
270
+ #
271
+ def messages
272
+ Messages.new(self, PATH_MESSAGES, entity_class=Message)
273
+ end
274
+
275
+ ##
276
+ # Returns a collection of the roles on the system.
277
+ #
278
+ # Returns: A +Collection+ of +Entity+ objects representing the roles on
279
+ # this Splunk instance.
280
+ #
281
+ def roles
282
+ CaseInsensitiveCollection.new(self, PATH_ROLES)
283
+ end
284
+
285
+ ##
286
+ #
287
+ #
288
+ #
289
+ def saved_searches
290
+ Collection.new(self, PATH_SAVED_SEARCHES, entity_class=SavedSearch)
291
+ end
292
+
293
+ ##
294
+ # Returns an +Entity+ of Splunk's mutable runtime information.
295
+ #
296
+ # The +settings+ method includes values such as "+SPLUNK_DB+"
297
+ # and "+SPLUNK_HOME+". Unlike the values returned by the +info+ method,
298
+ # these settings can be updated.
299
+ #
300
+ # Returns: an +Entity+ with all server settings.
301
+ #
302
+ # *Example*:
303
+ # service = Splunk::connect(:username => 'admin', :password => 'foo')
304
+ # puts svc.settings.read
305
+ # # Prints:
306
+ # # {"SPLUNK_DB" => "/path/to/splunk_home/var/lib/splunk",
307
+ # # "SPLUNK_HOME" => "/path/to/splunk_home",
308
+ # # ...}
309
+ #
310
+ def settings
311
+ # Though settings looks like a collection on the server, it always has
312
+ # a single entity, of the same name, giving the actual settings. We access
313
+ # that entity directly rather than putting a collection inbetween.
314
+ Entity.new(self, Splunk::namespace(:sharing => "default"),
315
+ PATH_SETTINGS, "settings").refresh()
316
+ end
317
+
318
+ ##
319
+ # Returns the version of Splunk this +Service+ is connected to.
320
+ #
321
+ # The version is represented as an +Array+ of length 3, with each
322
+ # of its components an integer. For example, on Splunk 4.3.5,
323
+ # +splunk_version+ would return [+4, 3, 5+], while on Splunk 5.0.2,
324
+ # +splunk_version+ would return [+5, 0, 2+].
325
+ #
326
+ # Returns: An +Array+ of +Integers+ of length 3.
327
+ #
328
+ def splunk_version
329
+ info["version"].split(".").map() {|v| Integer(v)}
330
+ end
331
+
332
+ ##
333
+ # Return a +Collection+ of the users defined on Splunk.
334
+ #
335
+ def users
336
+ CaseInsensitiveCollection.new(self, PATH_USERS)
337
+ end
338
+ end
339
+ end
@@ -0,0 +1,49 @@
1
+ #--
2
+ # Copyright 2011-2013 Splunk, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"): you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #++
16
+
17
+ ##
18
+ # Defines an exception to carry all errors returned by Splunk.
19
+
20
+ require_relative 'xml_shim'
21
+
22
+ module Splunk
23
+ ##
24
+ # Exception to represent all errors returned from Splunkd.
25
+ #
26
+ # The important information about the error is available as a set of
27
+ # accessors:
28
+ #
29
+ # * +code+: The HTTP error code returned.
30
+ # * +reason+: The reason field of the HTTP response header.
31
+ # * +detail+: The detailed error message Splunk sent in the response body.
32
+ #
33
+ # You can also get the original response body from +body+ and any HTTP
34
+ # headers returns from +headers+.
35
+ #
36
+ class SplunkHTTPError < StandardError
37
+ attr_reader :reason, :code, :headers, :body, :detail
38
+
39
+ def initialize(response)
40
+ @body = response.body
41
+ @detail = Splunk::text_at_xpath("//msg", response.body)
42
+ @reason = response.message
43
+ @code = Integer(response.code)
44
+ @headers = response.each().to_a()
45
+
46
+ super("HTTP #{@code.to_s} #{@reason}: #{@detail || ""}")
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,50 @@
1
+ # :stopdoc:
2
+ # Copyright 2011-2013 Splunk, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"): you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+
16
+ ##
17
+ # Easy creation of synonyms for methods.
18
+ #
19
+ # To make it easy to create Ruby's synonym sets (such as
20
+ # +has_key?+/+include?+/+member?+/etc. on +Hash+), we provide a mixin
21
+ # +Synonyms+ with one method, +synonym+. +synonym+ defines a new method
22
+ # named by its first parameter, with the same behavior as the method named
23
+ # by its second parameter.
24
+ #
25
+ # *Example:*
26
+ #
27
+ # require 'synonyms'
28
+ #
29
+ # class A
30
+ # extend Synonyms
31
+ # def f(...) ... end
32
+ # synonym "g" "f"
33
+ #
34
+
35
+ module Synonyms
36
+ # Make method _new_name_ a synonym for method _old_name_ on this class.
37
+ #
38
+ # Arguments:
39
+ # * _new_name_: (+String+ or +Symbol+) The name of the method to create.
40
+ # * _old_name_: (+String+ or +Symbol+) The name of the method to make the
41
+ # new method a synonym for.
42
+ #
43
+ private
44
+ def synonym(new_name, old_name)
45
+ define_method(new_name) do |*args, &block|
46
+ old_method = old_name.intern
47
+ send(old_method, *args, &block)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,27 @@
1
+ #--
2
+ # Copyright 2011-2013 Splunk, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"): you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #++
16
+
17
+ # :stopdoc:
18
+
19
+ ##
20
+ # The version of the Splunk SDK for Ruby.
21
+ #
22
+ # We put it here so we only have to change it in one place as we
23
+ # release new versions.
24
+ #
25
+ module Splunk
26
+ VERSION = '0.1.0'
27
+ end