splunk-client 0.5.1 → 0.6

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.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in splunk-client.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ splunk-client (0.5.3)
5
+ nokogiri
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.3)
11
+ json (1.7.3)
12
+ multi_json (1.3.5)
13
+ nokogiri (1.5.2)
14
+ rake (0.9.2.2)
15
+ rspec (2.10.0)
16
+ rspec-core (~> 2.10.0)
17
+ rspec-expectations (~> 2.10.0)
18
+ rspec-mocks (~> 2.10.0)
19
+ rspec-core (2.10.0)
20
+ rspec-expectations (2.10.0)
21
+ diff-lcs (~> 1.1.3)
22
+ rspec-mocks (2.10.1)
23
+ simplecov (0.6.4)
24
+ multi_json (~> 1.0)
25
+ simplecov-html (~> 0.5.3)
26
+ simplecov-html (0.5.3)
27
+ simplecov-rcov (0.2.3)
28
+ simplecov (>= 0.4.1)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ json
35
+ rake
36
+ rspec
37
+ simplecov-rcov
38
+ splunk-client!
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # SplunkClient
2
+
3
+ Ruby library for dealing with Splunk searches and results using the Splunk REST API.
4
+
5
+ ## Installation
6
+
7
+ gem install splunk-client
8
+
9
+ ## Usage
10
+
11
+ Creating and using a client is easy:
12
+
13
+ require 'splunk-client.rb'
14
+
15
+ # Create the client
16
+ splunk = SplunkClient.new("username", "password", "hostname")
17
+
18
+ # Create the Search
19
+ search = splunk.search("test_search")
20
+
21
+ # Wait for the Splunk search to complete
22
+ search.wait # Blocks until the search returns
23
+
24
+ #Print the raw XML results
25
+ puts search.results
26
+
27
+ #Print the time and host of each result
28
+ search.parsedResults.each do |result|
29
+ puts result.host + " : " + result.time
30
+ end
31
+
32
+ ## Tips
33
+
34
+ * Want to spawn multiple jobs without blocking on each? Use `search.complete?` to poll for job status.
35
+
36
+ * Looking for more or less results? Use `search.results(maxResults)` to control how much is returned. (A value of 0 returns all results (this is the default.))
37
+
38
+ * Access Splunk fields in results via method calls
39
+ `result = search.parsedResults`
40
+ `puts result[0].fieldName`
41
+
42
+ ## Revision History
43
+
44
+ #### 0.6
45
+ * Added two new objects: SplunkResults and SplunkResult for to support:
46
+ * Accessing Splunk fields via method calls
47
+ `search.parsedResults.each {|result| puts result.$$FIELD_NAME$$}`
48
+
49
+ #### 0.5
50
+ WARNING: Compatibility with prior versions will break as SplunkClient no longer returns a sid. It now returns a SplunkJob object.
51
+
52
+ * Separated SplunkClient and SplunkJob into two separate objects.
53
+
54
+ #### 0.1
55
+ * Initial Release
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run specs"
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
8
+ # Put spec opts in a file named .rspec in root
9
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6
data/lib/splunk-client.rb CHANGED
@@ -1,93 +1,3 @@
1
1
  # Author:: Christopher Brito (cbrito@gmail.com)
2
2
  # Original Repo:: https://github.com/cbrito/splunk-client
3
-
4
- require 'net/https'
5
- require 'cgi'
6
- require 'rubygems'
7
- require 'nokogiri'
8
-
9
- class SplunkJob
10
- attr_reader :jobId
11
-
12
- def initialize(jobId, clientPointer)
13
- @jobId = jobId
14
- @client = clientPointer #SplunkClient object pointer
15
- end
16
-
17
- def wait
18
- wait_for_results
19
- end
20
-
21
- def wait_for_results
22
- # Wait for the Splunk search to complete
23
- while (@client.get_search_status(@jobId).to_i == 0)
24
- sleep 2
25
- end
26
- end
27
-
28
- def complete?
29
- # Return status of job
30
- @client.get_search_status(@jobId).to_i == 0
31
- end
32
-
33
- def results(maxResults=0)
34
- # Return search results
35
- @client.get_search_results(@jobId, maxResults)
36
- end
37
-
38
- end #class SplunkJob
39
-
40
- class SplunkClient
41
-
42
- def initialize(username, password, host, port=8089)
43
- @USER=username; @PASS=password; @HOST=host; @PORT=port
44
-
45
- @SESSION_KEY = { 'authorization' => "Splunk #{get_session_key}" }
46
- end
47
-
48
- def create_search(search)
49
- # Returns a SplunkJob
50
- xml = splunk_post_request("/services/search/jobs",
51
- "search=#{CGI::escape("search #{search}")}",
52
- @SESSION_KEY)
53
-
54
- @doc = Nokogiri::Slop(xml)
55
-
56
- return SplunkJob.new(@doc.xpath("//sid").text, self)
57
- end
58
-
59
- def get_search_status(sid)
60
- xml = splunk_get_request("/services/search/jobs/#{sid}")
61
- @doc = Nokogiri::Slop(xml)
62
- return @doc.xpath("//s:key[@name='isDone']").text
63
- end
64
-
65
- def get_search_results(sid, maxResults=0)
66
- splunk_get_request("/services/search/jobs/#{sid}/results?count=#{maxResults}")
67
- end
68
-
69
- private ###############################################################################
70
-
71
- def splunk_http_request
72
- http = Net::HTTP.new(@HOST, @PORT)
73
- http.use_ssl = true
74
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
75
- return http
76
- end
77
-
78
- def splunk_get_request(path)
79
- splunk_http_request.get(path, @SESSION_KEY).body
80
- end
81
-
82
- def splunk_post_request(path, data=nil, headers=nil)
83
- splunk_http_request.post(path,data,headers).body
84
- end
85
-
86
- def get_session_key
87
- xml = splunk_post_request("/services/auth/login",
88
- "username=#{@USER}&password=#{@PASS}")
89
- @doc = Nokogiri::Slop(xml)
90
- return @doc.xpath("//sessionKey").text
91
- end
92
-
93
- end #class SplunkClient
3
+ require File.expand_path File.join(File.dirname(__FILE__), 'splunk_client/splunk_client')
@@ -0,0 +1,76 @@
1
+ # Author:: Christopher Brito (cbrito@gmail.com)
2
+ # Original Repo:: https://github.com/cbrito/splunk-client
3
+
4
+ require 'net/https'
5
+ require 'cgi'
6
+ require 'rubygems'
7
+ require 'nokogiri'
8
+ require File.expand_path File.join(File.dirname(__FILE__), 'splunk_job')
9
+
10
+ class SplunkClient
11
+
12
+ def initialize(username, password, host, port=8089)
13
+ @USER=username; @PASS=password; @HOST=host; @PORT=port
14
+
15
+ @SESSION_KEY = { 'authorization' => "Splunk #{get_session_key}" }
16
+ end
17
+
18
+ def search(search)
19
+ create_search(search)
20
+ end
21
+
22
+ def create_search(search)
23
+ # Returns a SplunkJob
24
+ xml = splunk_post_request("/services/search/jobs",
25
+ "search=#{CGI::escape("search #{search}")}",
26
+ @SESSION_KEY)
27
+
28
+ @doc = Nokogiri::Slop(xml)
29
+
30
+ return SplunkJob.new(@doc.xpath("//sid").text, self)
31
+ end
32
+
33
+ def get_search_status(sid)
34
+ xml = splunk_get_request("/services/search/jobs/#{sid}")
35
+ @doc = Nokogiri::Slop(xml)
36
+ return @doc.xpath("//s:key[@name='isDone']").text
37
+ end
38
+
39
+ def get_search_results(sid, maxResults=0, mode=nil)
40
+ url = "/services/search/jobs/#{sid}/results?count=#{maxResults}"
41
+ url += "&output_mode=#{mode}" unless mode.nil?
42
+ splunk_get_request(url)
43
+ end
44
+
45
+ def control_job(sid, action)
46
+ xml = splunk_post_request("/services/search/jobs/#{sid}/control",
47
+ "action=#{CGI::escape(action)}",
48
+ @SESSION_KEY)
49
+ @doc = Nokogiri::Slop(xml)
50
+ end
51
+
52
+ private ###############################################################################
53
+
54
+ def splunk_http_request
55
+ http = Net::HTTP.new(@HOST, @PORT)
56
+ http.use_ssl = true
57
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
58
+ return http
59
+ end
60
+
61
+ def splunk_get_request(path)
62
+ splunk_http_request.get(path, @SESSION_KEY).body
63
+ end
64
+
65
+ def splunk_post_request(path, data=nil, headers=nil)
66
+ splunk_http_request.post(path,data,headers).body
67
+ end
68
+
69
+ def get_session_key
70
+ xml = splunk_post_request("/services/auth/login",
71
+ "username=#{@USER}&password=#{@PASS}")
72
+ @doc = Nokogiri::Slop(xml)
73
+ return @doc.xpath("//sessionKey").text
74
+ end
75
+
76
+ end #class SplunkClient
@@ -0,0 +1,43 @@
1
+ # Author:: Christopher Brito (cbrito@gmail.com)
2
+ # Original Repo:: https://github.com/cbrito/splunk-client
3
+
4
+ require File.expand_path File.join(File.dirname(__FILE__), 'splunk_results')
5
+
6
+
7
+ class SplunkJob
8
+ attr_reader :jobId
9
+
10
+ def initialize(jobId, clientPointer)
11
+ @jobId = jobId
12
+ @client = clientPointer #SplunkClient object pointer
13
+ end
14
+
15
+ def wait
16
+ wait_for_results
17
+ end
18
+
19
+ def wait_for_results
20
+ # Wait for the Splunk search to complete
21
+ sleep 1 until complete?
22
+ end
23
+
24
+ def complete?
25
+ # Return status of job
26
+ @client.get_search_status(@jobId).to_i == 1
27
+ end
28
+
29
+ def results(maxResults=0, mode=nil)
30
+ # Return search results
31
+ @client.get_search_results(@jobId, maxResults, mode)
32
+ end
33
+
34
+ def cancel
35
+ @client.control_job(@jobId, 'cancel')
36
+ end
37
+
38
+ def parsedResults
39
+ # Return a SplunkResults object with methods for the result fields
40
+ SplunkResults.new(results).results
41
+ end
42
+
43
+ end #class SplunkJob
@@ -0,0 +1,34 @@
1
+ # Author:: Christopher Brito (cbrito@gmail.com)
2
+ # Original Repo:: https://github.com/cbrito/splunk-client
3
+
4
+ # Simplify the calling of single result data from xpaths into an object
5
+ # http://stackoverflow.com/questions/2240535/how-do-i-use-hash-keys-as-methods-on-a-class
6
+ class SplunkResult
7
+
8
+ def initialize(nokogiriNode)
9
+ @result = nokogiriNode
10
+ end
11
+
12
+ # Ex: splunkResult.time => nokogiriNode.result.field("[@k=\"_time\"]").value.text
13
+ def time
14
+ @result.field("[@k=\"_time\"]").value.text
15
+ end
16
+
17
+ # Ex: splunkResult.sourceIp => nokogiriNode.result.field("[@k=\"sourceIp\"]").value.text
18
+ def method_missing(name, *args, &blk)
19
+ if args.empty? && blk.nil? && @result.field("[@k=\"#{name}\"]")
20
+ @result.field("[@k=\"#{name}\"]").value.text
21
+ else
22
+ super
23
+ end
24
+ end
25
+
26
+ def respond_to?(name)
27
+ begin
28
+ unless @result.field("[@k=\"#{name}\"]").nil? then true else super end
29
+ rescue NoMethodError
30
+ super
31
+ end
32
+ end
33
+
34
+ end #class SplunkResult
@@ -0,0 +1,29 @@
1
+ # Author:: Christopher Brito (cbrito@gmail.com)
2
+ # Original Repo:: https://github.com/cbrito/splunk-client
3
+
4
+ require 'rubygems'
5
+ require 'nokogiri'
6
+ require File.expand_path File.join(File.dirname(__FILE__), 'splunk_result')
7
+
8
+ # Simplify the calling of single result data from xpaths into an objects
9
+ class SplunkResults
10
+ attr_reader :results
11
+
12
+ def initialize(rawResults)
13
+ nokoResults = Nokogiri::Slop(rawResults)
14
+ @results = Array.new
15
+
16
+ if nokoResults.results.result.respond_to?("length")
17
+ # Multiple Results, build array
18
+ nokoResults.results.result.each do |resultObj|
19
+ @results.push SplunkResult.new(resultObj)
20
+ end
21
+ else
22
+ # Single results object
23
+ @results.push Splunkresults.new(nokoResults.results.result)
24
+ end
25
+
26
+ return @results
27
+ end
28
+
29
+ end #class SplunkResults
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'simplecov'
3
+ require 'simplecov-rcov'
4
+ class SimpleCov::Formatter::MergedFormatter
5
+ def format(result)
6
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
7
+ SimpleCov::Formatter::RcovFormatter.new.format(result)
8
+ end
9
+ end
10
+ SimpleCov.formatter = SimpleCov::Formatter::MergedFormatter
11
+ SimpleCov.start
12
+ require 'rspec/autorun'
13
+
14
+ require 'json'
15
+ require File.expand_path File.join(File.dirname(__FILE__), '../lib/splunk-client')
@@ -0,0 +1,58 @@
1
+ require File.expand_path File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe SplunkClient do
4
+
5
+ before :each do
6
+ @user = ENV['SPLUNK_USER']
7
+ @pass = ENV['SPLUNK_PASSWD']
8
+ @host = ENV['SPLUNK_HOST']
9
+ @splunk_client = SplunkClient.new(@user, @pass, @host)
10
+ end
11
+
12
+ context "initialization" do
13
+
14
+ it "creates a session key" do
15
+ splunk_client = @splunk_client
16
+ splunk_client.should_not be(nil)
17
+ splunk_client.send(:get_session_key).should_not be(nil)
18
+ end
19
+
20
+ end
21
+
22
+ context "searching" do
23
+
24
+ it "creates a search job and returns results" do
25
+ splunk_client = @splunk_client
26
+ splunk_client.should_not be(nil)
27
+ search = 'source="/var/log/messages" "kernel" earliest=-10m'
28
+ job = splunk_client.search(search)
29
+ job.should_not be(nil)
30
+ job.wait
31
+ job.results(0, 'json')
32
+ job.cancel
33
+ end
34
+
35
+ end
36
+
37
+ context "parsing_results" do
38
+ it "uses the parsedResults 'host' method of a SplunkJob" do
39
+ splunk_client = @splunk_client
40
+ splunk_client.should_not be(nil)
41
+ search = 'source="/var/log/messages" "kernel" earliest=-10m'
42
+ job = splunk_client.search(search)
43
+ job.should_not be(nil)
44
+ job.wait
45
+ results = job.parsedResults
46
+
47
+ # Test the auto generated methods
48
+ results.each do |result|
49
+ result.respond_to?("time").should be(true)
50
+ result.respond_to?("host").should be(true)
51
+ result.time.should_not be(nil)
52
+ result.host.should_not be(nil)
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+ end
metadata CHANGED
@@ -1,78 +1,139 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: splunk-client
3
- version: !ruby/object:Gem::Version
4
- hash: 9
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.6'
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 5
9
- - 1
10
- version: 0.5.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Christopher Brito
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-04-24 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-05-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: nokogiri
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
32
22
  type: :runtime
33
- version_requirements: *id001
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: simplecov-rcov
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: json
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
34
94
  description: Simple Ruby library for interfacing with Splunk's REST API.
35
- email: cbrito@gmail.com
95
+ email:
96
+ - cbrito@gmail.com
36
97
  executables: []
37
-
38
98
  extensions: []
39
-
40
99
  extra_rdoc_files: []
41
-
42
- files:
100
+ files:
43
101
  - lib/splunk-client.rb
102
+ - lib/splunk_client/splunk_client.rb
103
+ - lib/splunk_client/splunk_job.rb
104
+ - lib/splunk_client/splunk_result.rb
105
+ - lib/splunk_client/splunk_results.rb
106
+ - spec/spec_helper.rb
107
+ - spec/splunk_client_spec.rb
108
+ - VERSION
109
+ - README.md
110
+ - Rakefile
111
+ - Gemfile
112
+ - Gemfile.lock
44
113
  homepage: http://github.com/cbrito/splunk-client
45
114
  licenses: []
46
-
47
115
  post_install_message:
48
116
  rdoc_options: []
49
-
50
- require_paths:
117
+ require_paths:
51
118
  - lib
52
- required_ruby_version: !ruby/object:Gem::Requirement
119
+ required_ruby_version: !ruby/object:Gem::Requirement
53
120
  none: false
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- hash: 3
58
- segments:
59
- - 0
60
- version: "0"
61
- required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
126
  none: false
63
- requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- hash: 3
67
- segments:
68
- - 0
69
- version: "0"
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
70
131
  requirements: []
71
-
72
132
  rubyforge_project:
73
- rubygems_version: 1.8.15
133
+ rubygems_version: 1.8.24
74
134
  signing_key:
75
135
  specification_version: 3
76
136
  summary: Ruby Library for interfacing with Splunk's REST API
77
- test_files: []
78
-
137
+ test_files:
138
+ - spec/spec_helper.rb
139
+ - spec/splunk_client_spec.rb