splunk-sdk-ruby 0.1.0

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