splunker 0.0.0 → 0.0.1
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/README.md +67 -2
- data/VERSION +1 -1
- data/lib/splunker.rb +17 -0
- data/lib/splunker/auth.rb +9 -2
- data/lib/splunker/auth/http_auth.rb +1 -0
- data/lib/splunker/client.rb +12 -0
- data/lib/splunker/connection.rb +2 -0
- data/lib/splunker/errors.rb +8 -0
- data/lib/splunker/faraday_middleware.rb +1 -1
- data/lib/splunker/models/resource.rb +0 -5
- data/lib/splunker/request.rb +51 -4
- data/spec/functional/request_spec.rb +40 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/unit/request_spec.rb +17 -0
- data/splunker.gemspec +1 -0
- metadata +22 -2
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
A Ruby client for the [RESTful Splunk API](http://dev.splunk.com/view/rest-api-overview/SP-CAAADP8)
|
4
4
|
|
5
|
+
Consider this largely functional but alpha. See the TODO list below.
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add this line to your application's Gemfile:
|
@@ -18,17 +20,75 @@ Or install it yourself as:
|
|
18
20
|
|
19
21
|
## Usage
|
20
22
|
|
21
|
-
Models are on
|
23
|
+
Models are on the way, but you can access resources by directly invoking the
|
22
24
|
HTTP helper methods.
|
23
25
|
|
26
|
+
# Console
|
27
|
+
To make playing around with the API client a smooth(er) experience, you can fire up our IRB wrapper by:
|
28
|
+
|
29
|
+
$ bundle exec script/console
|
30
|
+
Enabling console mode for local gem
|
31
|
+
Loading splunker gem...
|
32
|
+
Splunker:001:0> c = Splunker.client(:auth_mode => :http_auth)
|
33
|
+
#<Splunker::Client:0x007f9782b0d238 @endpoint="https://localhost:8089", @app="search", @ssl_verify=true, @request_handler=#<Splunker::Auth::HttpAuth:0x007f9782b0cf68 @client=#<Splunker::Client:0x007f9782b0d238 ...>>, @password=nil, @username=nil>
|
34
|
+
|
24
35
|
# Basic Auth
|
25
36
|
c = Splunker.client(:auth_mode => :http_auth, :username => "MYUSERNAME",
|
26
37
|
:password => "MYPASSWORD", :endpoint => "https://splunk.mysite.com")
|
27
38
|
# Returns Nokogiri::XML::Document
|
28
|
-
|
39
|
+
# Note that /servicesNS/YOUR_USERNAME/YOUR_APPNAME is prepended automatically
|
40
|
+
# to your resource.
|
41
|
+
r = c.get("/saved/searches/MySearch/history")
|
29
42
|
# Process away
|
30
43
|
r.xpath("...")
|
31
44
|
|
45
|
+
## Exceptions
|
46
|
+
|
47
|
+
The API client raises an exception when a non-2XX [response codes](http://docs.splunk.com/Documentation/Splunk/latest/RESTAPI/RESTusing#Response_status) is received.
|
48
|
+
|
49
|
+
<table>
|
50
|
+
<thead>
|
51
|
+
<tr>
|
52
|
+
<th>HTTP Code</th>
|
53
|
+
<th>Splunk API Error Code</th>
|
54
|
+
</tr>
|
55
|
+
</thead>
|
56
|
+
<tbody>
|
57
|
+
<tr>
|
58
|
+
<td>401</td>
|
59
|
+
<td>Splunker::Errors::AuthenticationFailureError</td>
|
60
|
+
</tr>
|
61
|
+
<tr>
|
62
|
+
<td>402</td>
|
63
|
+
<td>Splunker::Errors::FeatureDisabledError</td>
|
64
|
+
</tr>
|
65
|
+
<tr>
|
66
|
+
<td>403</td>
|
67
|
+
<td>Splunker::Errors::PermissionDeniedError</td>
|
68
|
+
</tr>
|
69
|
+
<tr>
|
70
|
+
<td>404</td>
|
71
|
+
<td>Splunker::Errors::ObjectDoesNotExistError</td>
|
72
|
+
</tr>
|
73
|
+
<tr>
|
74
|
+
<td>405</td>
|
75
|
+
<td>Splunker::Errors::MethodNotAllowedError</td>
|
76
|
+
</tr>
|
77
|
+
<tr>
|
78
|
+
<td>409</td>
|
79
|
+
<td>Splunker::Errors::InvalidOperationError</td>
|
80
|
+
</tr>
|
81
|
+
<tr>
|
82
|
+
<td>500</td>
|
83
|
+
<td>Splunker::Errors::InternalServerError </td>
|
84
|
+
</tr>
|
85
|
+
<tr>
|
86
|
+
<td>Any other non-2xx response</td>
|
87
|
+
<td>Splunker::Errors::ClientError</td>
|
88
|
+
</tr>
|
89
|
+
</tbody>
|
90
|
+
</table>
|
91
|
+
|
32
92
|
## Contributing
|
33
93
|
|
34
94
|
1. Fork it
|
@@ -36,3 +96,8 @@ HTTP helper methods.
|
|
36
96
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
37
97
|
4. Push to the branch (`git push origin my-new-feature`)
|
38
98
|
5. Create new Pull Request
|
99
|
+
|
100
|
+
# TODO
|
101
|
+
* Token Auth
|
102
|
+
* Resource creation handling, blocking & polling options, with a timeout.
|
103
|
+
* Build console into gem (bin/)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.1
|
data/lib/splunker.rb
CHANGED
@@ -3,7 +3,21 @@ require "splunker/version"
|
|
3
3
|
require "splunker/client"
|
4
4
|
require "splunker/errors"
|
5
5
|
|
6
|
+
# The parent Splunker module can directly invoke any method invokable by the
|
7
|
+
# client returned in Splunker.client, so long as Splunker.client has been
|
8
|
+
# called once with options to instantiate a new client.
|
9
|
+
#
|
10
|
+
# If using the helper models, you must first configure Splunker with
|
11
|
+
# Splunker.client({ :options => "..." }), as they all reference Splunker.client
|
12
|
+
# when they make requests.
|
6
13
|
module Splunker
|
14
|
+
|
15
|
+
# Returns a reference to the current Splunk API client if no options are
|
16
|
+
# supplied. Otherwise, generates a new Splunker client.
|
17
|
+
#
|
18
|
+
# Parameters:
|
19
|
+
# * options => See Splunker::Client's initialize method for details.
|
20
|
+
# Returns an instance of Splunker::Client
|
7
21
|
def self.client(options={})
|
8
22
|
unless options.empty?
|
9
23
|
Thread.current[:splunker_client] = Splunker::Client.new(options)
|
@@ -12,6 +26,7 @@ module Splunker
|
|
12
26
|
Thread.current[:splunker_client]
|
13
27
|
end
|
14
28
|
|
29
|
+
# A reference to the Splunker logger
|
15
30
|
def self.logger
|
16
31
|
if @logger.nil?
|
17
32
|
@logger = Logger.new(STDOUT)
|
@@ -20,6 +35,8 @@ module Splunker
|
|
20
35
|
@logger
|
21
36
|
end
|
22
37
|
|
38
|
+
# Parameters:
|
39
|
+
# * custom_logger => A custom logger to use instead of Logger
|
23
40
|
def self.logger=(custom_logger)
|
24
41
|
@logger = custom_logger
|
25
42
|
end
|
data/lib/splunker/auth.rb
CHANGED
@@ -7,9 +7,16 @@ end
|
|
7
7
|
|
8
8
|
module Splunker
|
9
9
|
module Auth
|
10
|
-
|
10
|
+
# Factory to create a authenticated Request wrapper for a specified auth type.
|
11
|
+
# Parameters:
|
12
|
+
# * auth_type => A symbol representing the auth type to generate. Should be a symbolized
|
13
|
+
# class name for an existing implementation. (e.g. :http_auth, :token_auth)
|
14
|
+
# * client => A reference to the Splunker client instance.
|
15
|
+
# Returns an instance of the authenticated request wrapper noted by auth_type
|
16
|
+
# Raises ArgumentError if auth_type is invalid
|
17
|
+
def self.create(auth_type, client)
|
11
18
|
if (obj = Splunker::Auth.const_get("#{auth_type}".split('_').collect(&:capitalize).join))
|
12
|
-
obj.new(
|
19
|
+
obj.new(client)
|
13
20
|
else
|
14
21
|
raise ArgumentError, "Unknown auth type of #{auth_type}"
|
15
22
|
end
|
data/lib/splunker/client.rb
CHANGED
@@ -2,9 +2,21 @@ require 'splunker/configuration'
|
|
2
2
|
require 'splunker/auth'
|
3
3
|
|
4
4
|
module Splunker
|
5
|
+
# The Splunk API client.
|
6
|
+
# Methods include get, post, put, and delete HTTP helpers:
|
7
|
+
# c.get("...")
|
8
|
+
# See Splunker::Request for more details.
|
5
9
|
class Client
|
6
10
|
include Configuration
|
7
11
|
|
12
|
+
# Creates a new Splunker client instance.
|
13
|
+
# Options are:
|
14
|
+
# * :username => Required. The username to make requests on behalf of
|
15
|
+
# * :password => Required. The password to authenticate with
|
16
|
+
# * :auth_mode => Required. The authentication method to use. :http_auth or :token_auth.
|
17
|
+
# * :endpoint => ("https://localhost:8089") The host of the Splunk API
|
18
|
+
# * :ssl_verify => (true) If false, the SSL cert fro the Splunk server will not be verified.
|
19
|
+
# * :app => ("search")
|
8
20
|
def initialize(options={})
|
9
21
|
self.reset
|
10
22
|
|
data/lib/splunker/connection.rb
CHANGED
data/lib/splunker/errors.rb
CHANGED
@@ -23,6 +23,14 @@ module Splunker
|
|
23
23
|
500 => InternalServerError
|
24
24
|
}
|
25
25
|
|
26
|
+
# Parameters:
|
27
|
+
# * http_status => The integer representing the HTTP status
|
28
|
+
# * body => The response body. Will be passed to the
|
29
|
+
# error instance when raised, for additional
|
30
|
+
# information.
|
31
|
+
# Returns nil if no exception will be raised.
|
32
|
+
# Raises an error mapped to http_status in STATUS_CODE_TO_ERROR_MAP,
|
33
|
+
# or ClientError if status is not 2xx but no mapped error exists.
|
26
34
|
def self.raise_error_for_status!(http_status, body)
|
27
35
|
return nil if (200..299).include?(http_status)
|
28
36
|
|
@@ -6,7 +6,7 @@ module Splunker
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def on_complete(env)
|
9
|
-
env[:body] = Nokogiri::
|
9
|
+
env[:body] = Nokogiri::Slop(env[:body])
|
10
10
|
Splunker.logger.debug("Response Body: #{env[:body]}")
|
11
11
|
Splunker::Errors.raise_error_for_status!(env[:status], env[:body])
|
12
12
|
Splunker.logger.debug "Request successful!"
|
@@ -16,11 +16,6 @@ module Splunker
|
|
16
16
|
|
17
17
|
protected
|
18
18
|
|
19
|
-
# Basic path validation. Does nothing useful atm.
|
20
|
-
def self.assemble_path(path_str)
|
21
|
-
path_str.gsub(/\/+/,"/")
|
22
|
-
end
|
23
|
-
|
24
19
|
# Escapes a object ID for use in a URI
|
25
20
|
def self.escape_object_id(id_str)
|
26
21
|
CGI.escape(id_str)
|
data/lib/splunker/request.rb
CHANGED
@@ -1,34 +1,81 @@
|
|
1
1
|
require 'splunker/connection'
|
2
2
|
|
3
3
|
module Splunker
|
4
|
+
# The Request module, to be used by classes that will make requests to
|
5
|
+
# the Splunk API.
|
6
|
+
#
|
7
|
+
# Note that any class that mixes in the Request module will also mix in
|
8
|
+
# Splunker::Connection automatically (see Splunker::Request.included)
|
4
9
|
module Request
|
10
|
+
require 'addressable/uri'
|
5
11
|
|
12
|
+
# Authenticates the user (not the request) identified by
|
13
|
+
# :username and :password in the configuration.
|
6
14
|
def authenticate; end
|
7
15
|
|
16
|
+
# true if #authenticate does _not_ need to be called.
|
8
17
|
def authenticated?
|
9
18
|
true
|
10
19
|
end
|
11
20
|
|
21
|
+
# Attaches credentials to the supplied Faraday connection object.
|
12
22
|
def authenticate_connection(conn)
|
13
23
|
conn
|
14
24
|
end
|
15
25
|
|
26
|
+
# HTTP GET helper method.
|
27
|
+
# Parameters:
|
28
|
+
# * resource => The resource under configuration[:endpoint] to make the
|
29
|
+
# request
|
30
|
+
# * parameters => GET parameters to supply with the request.
|
31
|
+
# Returns Nokogiri:XML:Document object, parsed from the response body.
|
32
|
+
# Raises an exception from Splunker::Errors in accordance with the status code.
|
16
33
|
def get(resource, parameters={})
|
17
34
|
request(:get, resource, parameters)
|
18
35
|
end
|
19
36
|
|
20
|
-
|
21
|
-
|
22
|
-
|
37
|
+
def post(resource, body={})
|
38
|
+
request(:post, resource, nil, body)
|
39
|
+
end
|
23
40
|
|
24
41
|
###
|
25
42
|
# put/delete can come as needed.
|
26
43
|
###
|
27
44
|
|
45
|
+
# HTTP request helper method.
|
46
|
+
# Parameters:
|
47
|
+
# * method => A symbol representing the HTTP method (:get, :post, :put, :delete)
|
48
|
+
# * resource => The resource under configuration[:endpoint] to make the
|
49
|
+
# request
|
50
|
+
# * parameters => GET parameters to supply with the request.
|
51
|
+
# * body => POST/PUT data
|
52
|
+
# Returns Nokogiri:XML:Document object, parsed from the response body.
|
53
|
+
# Raises an exception from Splunker::Errors in accordance with the status code.
|
28
54
|
def request(method, resource, parameters={}, body={})
|
29
55
|
authenticate unless authenticated?
|
30
56
|
authenticate_connection(self.connection)
|
31
|
-
|
57
|
+
final_resource = resource_builder(resource, parameters)
|
58
|
+
self.connection.send(method, final_resource, body).body
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns a string representing the final resource path
|
62
|
+
def resource_builder(resource, parameters={})
|
63
|
+
u = Addressable::URI.new
|
64
|
+
u.path = assemble_path("/servicesNS/#{configuration[:username]}/#{configuration[:app]}/#{resource}")
|
65
|
+
unless parameters.nil? || parameters.empty?
|
66
|
+
# Let's remap and cast everything to a string.
|
67
|
+
# Addressable doesn't handle values like true well.
|
68
|
+
final_parameters = {}
|
69
|
+
parameters.map do |key, value|
|
70
|
+
final_parameters[key] = "#{value}"
|
71
|
+
end
|
72
|
+
u.query_values = final_parameters
|
73
|
+
end
|
74
|
+
u.to_s
|
75
|
+
end
|
76
|
+
|
77
|
+
def assemble_path(path_str)
|
78
|
+
path_str.gsub(/\/+/,"/")
|
32
79
|
end
|
33
80
|
|
34
81
|
def self.included(base)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe Splunker::Request do
|
3
|
+
context "successful requests" do
|
4
|
+
it "should return the response body as an Nokogiri::XML::Document" do
|
5
|
+
stub_fixture(client, "generic/search/results/get", "search_results_from_job.xml",
|
6
|
+
:parameters => {:parameter1 => "OK"})
|
7
|
+
client.get("generic/search/results/get").should be_a(Nokogiri::XML::Document)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should successfully perform post requests" do
|
11
|
+
stub_fixture(client, "generic/search/results/post", "search_results_from_job.xml",
|
12
|
+
:method => :post, :data => {:parameter1 => "OK"})
|
13
|
+
client.post("generic/search/results/post", :parameter1 => "OK").should be_a(Nokogiri::XML::Document)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "authentication" do # TODO: Once we have token_auth in place.
|
18
|
+
it "should not authenticate unless needed" do
|
19
|
+
end
|
20
|
+
it "should authenticated if needed" do
|
21
|
+
end
|
22
|
+
it "should retry authentication once if a 401 is returned" do
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "http errors" do
|
27
|
+
it "should raise a mapped exception with a known HTTP error" do
|
28
|
+
stub_http_error(client, 405)
|
29
|
+
expect {
|
30
|
+
client.get("error/405")
|
31
|
+
}.to raise_error Splunker::Errors::MethodNotAllowedError
|
32
|
+
end
|
33
|
+
it "should raise a client error with an unknown status code" do
|
34
|
+
stub_http_error(client, 499)
|
35
|
+
expect {
|
36
|
+
client.get("error/499")
|
37
|
+
}.to raise_error Splunker::Errors::ClientError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rspec'
|
2
|
+
require 'webmock/rspec'
|
2
3
|
require 'splunker'
|
3
4
|
require 'rspec_let_definitions'
|
4
5
|
|
@@ -6,4 +7,34 @@ RSpec.configure do |config|
|
|
6
7
|
config.color_enabled = true
|
7
8
|
config.formatter = 'documentation'
|
8
9
|
config.include Splunker::RspecLetDefinitions
|
10
|
+
config.include WebMock::API
|
11
|
+
end
|
12
|
+
|
13
|
+
def fixture(file)
|
14
|
+
File.new( File.expand_path('../fixtures', __FILE__) + "/" + file)
|
15
|
+
end
|
16
|
+
|
17
|
+
def basic_auth_resource_builder(client, resource)
|
18
|
+
path = client.resource_builder(resource)
|
19
|
+
endpoint = client.configuration[:endpoint]
|
20
|
+
endpoint.gsub!("https://", "https://#{client.configuration[:username]}:#{client.configuration[:password]}@")
|
21
|
+
|
22
|
+
"#{endpoint}#{path}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def stub_basic_auth_request(client, resource, method=:get)
|
26
|
+
uri = basic_auth_resource_builder(client,resource)
|
27
|
+
stub_request(method, uri)
|
28
|
+
end
|
29
|
+
|
30
|
+
def stub_http_error(client, code, method=:get)
|
31
|
+
stub_basic_auth_request(client, "error/#{code}", method).to_return(:status => code)
|
32
|
+
end
|
33
|
+
|
34
|
+
def stub_fixture(client, resource, fixture_file, options={:method => :get, :status=>200, :parameters => {},
|
35
|
+
:post_data => {}})
|
36
|
+
code = (options[:status] || 200)
|
37
|
+
method = (options[:method] || :get)
|
38
|
+
stub_basic_auth_request(client, resource, method).to_return(:status => code,
|
39
|
+
:body => fixture(fixture_file))
|
9
40
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
describe Splunker::Request do
|
2
|
+
context "assembling a path" do
|
3
|
+
it "should strip repeated slashes" do
|
4
|
+
client.assemble_path("//search//joshua/saved/searches").should eq("/search/joshua/saved/searches")
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
context "building a resource path" do
|
9
|
+
it "should assemble the path from the username and app name" do
|
10
|
+
client.resource_builder("saved/searches").should eq("/servicesNS/tido/search/saved/searches")
|
11
|
+
end
|
12
|
+
it "should assemble the path with query parameters" do
|
13
|
+
client.resource_builder("saved/searches", :parameter1 => "me",
|
14
|
+
:parameter2 => true).should eq("/servicesNS/tido/search/saved/searches?parameter1=me¶meter2=true")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/splunker.gemspec
CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_dependency "nokogiri"
|
19
19
|
gem.add_dependency "faraday"
|
20
|
+
gem.add_dependency "addressable"
|
20
21
|
gem.add_development_dependency "rspec", "~> 2.11"
|
21
22
|
gem.add_development_dependency "rake", "~> 0.9.2"
|
22
23
|
gem.add_development_dependency "webmock"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: splunker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: addressable
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: rspec
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -125,6 +141,7 @@ files:
|
|
125
141
|
- lib/splunker/version.rb
|
126
142
|
- script/console
|
127
143
|
- spec/fixtures/search_results_from_job.xml
|
144
|
+
- spec/functional/request_spec.rb
|
128
145
|
- spec/rspec_let_definitions.rb
|
129
146
|
- spec/spec_helper.rb
|
130
147
|
- spec/unit/auth/http_auth_spec.rb
|
@@ -132,6 +149,7 @@ files:
|
|
132
149
|
- spec/unit/client_spec.rb
|
133
150
|
- spec/unit/configuration_spec.rb
|
134
151
|
- spec/unit/errors_spec.rb
|
152
|
+
- spec/unit/request_spec.rb
|
135
153
|
- spec/unit/splunker_spec.rb
|
136
154
|
- splunker.gemspec
|
137
155
|
homepage: ''
|
@@ -160,6 +178,7 @@ specification_version: 3
|
|
160
178
|
summary: A Ruby client for the Splunk API
|
161
179
|
test_files:
|
162
180
|
- spec/fixtures/search_results_from_job.xml
|
181
|
+
- spec/functional/request_spec.rb
|
163
182
|
- spec/rspec_let_definitions.rb
|
164
183
|
- spec/spec_helper.rb
|
165
184
|
- spec/unit/auth/http_auth_spec.rb
|
@@ -167,4 +186,5 @@ test_files:
|
|
167
186
|
- spec/unit/client_spec.rb
|
168
187
|
- spec/unit/configuration_spec.rb
|
169
188
|
- spec/unit/errors_spec.rb
|
189
|
+
- spec/unit/request_spec.rb
|
170
190
|
- spec/unit/splunker_spec.rb
|