Skip to content
This repository has been archived by the owner on May 10, 2018. It is now read-only.

Commit

Permalink
Resolved comments from David's code review.
Browse files Browse the repository at this point in the history
  • Loading branch information
Frederick Ross committed Feb 11, 2013
1 parent 89a42e6 commit 3c7d78e
Show file tree
Hide file tree
Showing 16 changed files with 102 additions and 83 deletions.
46 changes: 20 additions & 26 deletions CHANGELOG
Expand Up @@ -38,22 +38,15 @@
* Job#setpriority renamed to Job#set_priority.
* Job#disable_preview removed, since a working test scenario couldn't be found
for it.
* Collection's constructor arguments have been changed from service, name,
and a dictionary of procedures to perform operations to service, path to the
collection as a list of strings, one per path component, and a class
to use to represent entities in the Collection.
* Entity's constructor has changed from taking service, path, and name to taking
a service, namespace, path to the containing collection as an Array of
String's, one per path component, the entity's name, and an optional initial
state.
* Collection's constructor arguments have changed.
* Entity's constructor arguments have changed.
* SplunkError has been removed, and SplunkHTTPError has been made a direct
subclass of StandardError.
* Deleted SearchResults, since it was superseded by ResultsReader.
* The metaprogramming to allow fetching entries of a Hash via dot notation has
been removed. That is, hash.key is no longer a synonym for hash["key"].
* The urlencode method previously monkeypatched onto Hash has been removed.
* Service#create_collection was removed.
* Version in version.rb set to 0.1.0.

### New features and APIs

Expand All @@ -66,8 +59,10 @@
objects. See the header comments of namespace.rb for a detailed description
of Splunk namespaces and their representation in this SDK.
* All XML handling is shimmed to work with either Nokogiri or REXML. It tries
Nokogiri first, and falls back to REXML, unless the user explicitly calls
require_xml_library. See xml_shim.rb for all this behavior.
Nokogiri first, which can process XML vastly faster, and falls back to REXML,
which will be present in all Ruby installs. The user may all call
require_xml_library to force the SDK to use a Nokogiri or REXML. See
xml_shim.rb for all this behavior.
* Added documentation throughout the SDK.
* The unit testing suite has been completely rewritten and expanded.
* Added a ResultsReader class to parse and iterate over sets of XML results from
Expand All @@ -93,12 +88,12 @@
* Collection#each, when called without a block, now returns an enumerator over
all elements in the collection.
* Added an optional namespace argument to Collection#delete and
Collection#fetch so entities can be specified uniquely even the presence of
name collisions.
Collection#fetch so entities can be specified uniquely even in the presence
of name collisions.
* Added new methods to Collection, mostly designed to recapitulate the
relevant methods of Hash. Synonym sets are separated by slashes,
and names in a set of synonyms that already existed are surrounded by square
brackets:
relevant methods of Hash. In the notation below, synonym sets are separated
by slashes, and names in a set of synonyms that already existed are
surrounded by square brackets:
* [contains?]/has_key?/include?/key?/member?
* [list]/values/to_a
* each_key
Expand All @@ -110,9 +105,9 @@
* length
* resource
* service
* Added methods to Entity. Synonym sets are separated by slashes,
and names in a set of synonyms that already existed are surrounded by square
brackets:
* Added methods to Entity. In the notation below, synonym sets are separated
by slashes, and names in a set of synonyms that already existed are
surrounded by square brackets:
* content
* delete
* fetch/[ [] ]
Expand All @@ -123,12 +118,11 @@
* service
* Entities now cache their state. To update the cache, call the entity's refresh
method.
* Added method roll_hot_buckets to Index.
* Index#clean takes a timeout instead of waiting forever. If no timeout is
specified, a default value will be used.
* Added new methods to Job. Synonym sets are separated by slashes,
and names in a set of synonyms that already existed are surrounded by square
brackets:
* Added new methods to Job. In the notation below, synonym sets are separated
by slashes, and names in a set of synonyms that already existed are
surrounded by square brackets:
* control
* is_done?
* is_ready?
Expand All @@ -137,9 +131,9 @@
entities have the following additional methods beyond Entity:
* dispatch
* history
* Added the following methods to Stanza (was: Conf). Synonym sets are separated
by slashes, and names in a set of synonyms that already existed are surrounded
by square brackets:
* Added the following methods to Stanza (was: Conf). In the notation below, synonym sets are separated
by slashes, and names in a set of synonyms that already existed are
surrounded by square brackets:
* length
* update/[submit]
* Added new custom exceptions:
Expand Down
40 changes: 20 additions & 20 deletions README.md
Expand Up @@ -78,7 +78,26 @@ or install it from Rubygems without fetching it from GitHub at all with

### Requirements

The Splunk Ruby SDK requires Ruby 1.9.2 or greater.
The Splunk Ruby SDK requires Ruby 1.9.2 or greater. It will use the Nokogiri
XML parsing library if it is available. To run code coverage on the unit test
suite you also need to install simplecov.

A word about XML: Ruby ships with the REXML library by default, but for most
real world work, you will want to install and use Nokogiri, which is orders of
magnitude faster. The Splunk Ruby SDK supports both. By default it will try to
use Nokogiri, and fall back to REXML if Nokogiri is not available. The value of
the library in use is kept in the global variable `$splunk_xml_library` (which
will be either `:nokogiri` or `:rexml`).

You can force your program to use a particular library by calling
require_xml_library(_library_) (where, again, _library_ is either `:nokogiri`
or `:rexml`). This method is in `lib/splunk_sdk_ruby/xml_shim.rb`, but will be
included when you include the whole SDK.

If you force your program to use a particular library, the SDK will no longer
try to fall back to REXML, but will issue a LoadError, on the assumption that
if you really wanted Nokogiri that badly, we should probably tell you if you
don't get it.

### Running the Unit Tests

Expand Down Expand Up @@ -155,25 +174,6 @@ The Splunk library included in this SDK consists of two layers of API that
can be used to interact with splunkd - the _binding_ layer and the
_client_ layer.

### A word about XML

Ruby ships with the REXML library by default, but for most real world work,
you will want to use Nokogiri, which is orders of magnitude faster. The Splunk
Ruby SDK supports both. By default it will try to use Nokogiri, and fall back
to REXML if Nokogiri is not available. The value of the library in use is
kept in the global variable `$splunk_xml_library` (which will be either
`:nokogiri` or `:rexml`).

You can force your program to use a particular library by calling
require_xml_library(_library_) (where, again, _library_ is either `:nokogiri`
or `:rexml`). This method is in `lib/splunk_sdk_ruby/xml_shim.rb`, but will be
included when you include the whole SDK.

If you force your program to use a particular library, the SDK will no longer
try to fall back to REXML, but will issue a LoadError, on the assumption that
if you really wanted Nokogiri that badly, we should probably tell you if you
don't get it.

### The Binding Layer
This is the lowest layer of the Splunk Ruby SDK. It is a thin wrapper around
low-level HTTP capabilities, including:
Expand Down
4 changes: 2 additions & 2 deletions Rakefile
Expand Up @@ -7,8 +7,8 @@ require 'date'
spec = Gem::Specification.new do |s|
s.name = "splunk-sdk"
s.version = "0.1.0"
s.author = "Frederick Ross"
s.email = "fross@splunk.com"
s.author = "Splunk"
s.email = "devinfo@splunk.com"
s.homepage = "http://dev.splunk.com"
s.summary = "SDK for easily working with Splunk from Ruby."
s.description = s.summary
Expand Down
2 changes: 1 addition & 1 deletion examples/1_connect.rb
Expand Up @@ -23,7 +23,7 @@
:host => "localhost",
:port => 8089,
:username => "admin",
:password => "admin"
:password => "changeme"
}

# Create a Service logged into Splunk, and print the authentication token
Expand Down
2 changes: 1 addition & 1 deletion examples/2_manage.rb
Expand Up @@ -23,7 +23,7 @@
:host => "localhost",
:port => 8089,
:username => "admin",
:password => "admin"
:password => "changeme"
}

# First we connect to Splunk. We'll use this service for all the work in this
Expand Down
2 changes: 1 addition & 1 deletion examples/3_retrieve_data.rb
Expand Up @@ -23,7 +23,7 @@
:host => "localhost",
:port => 8089,
:username => "admin",
:password => "admin"
:password => "changeme"
}

# First open a connection to Splunk.
Expand Down
6 changes: 3 additions & 3 deletions examples/4_write_data.rb
Expand Up @@ -23,7 +23,7 @@
:host => "localhost",
:port => 8089,
:username => "admin",
:password => "admin"
:password => "changeme"
}

# First open a connection to Splunk.
Expand All @@ -43,7 +43,7 @@
# We can write single events to the index with the Index#submit method.
example_index.submit("This is a test event.")

# And we'll make sure it is actually there.
# And we'll wait until it has probably been indexed.
sleep(1) # Indexing isn't instantaneous.
stream = service.create_oneshot("search index=#{INDEX_NAME}")
results = Splunk::ResultsReader.new(stream)
Expand All @@ -64,7 +64,7 @@
socket.close() # You must make sure the socket gets closed.
end

# Again we'll make sure the events arrived.
# Again we'll wait until it's probably been indexed.
sleep(3) # Indexing isn't instantaneous.
stream = service.create_oneshot("search index=#{INDEX_NAME}")
results = Splunk::ResultsReader.new(stream)
Expand Down
12 changes: 8 additions & 4 deletions lib/splunk-sdk-ruby/collection.rb
Expand Up @@ -151,8 +151,12 @@ def create(name, args={})
response = @service.request(request_args)

if @always_fetch
response = @service.request(:method => :GET,
:resource => @resource + [name])
fetch_args = {:method => :GET,
:resource => @resource + [name]}
if args.has_key?(namespace)
fetch_args[:namespace] = args[:namespace]
end
response = @service.request(fetch_args)
end
feed = AtomFeed.new(response.body)
raise StandardError.new("No entities returned") if feed.entries.empty?
Expand Down Expand Up @@ -182,8 +186,8 @@ def delete(name, namespace=nil)

# We don't want to handle any cases about deleting ambiguously named
# entities.
if !namespace.is_proper?
raise StandardError.new("Must provide a proper namespace to delete an entity.")
if !namespace.is_exact?
raise StandardError.new("Must provide an exact namespace to delete an entity.")
end

@service.request(:method => :DELETE,
Expand Down
1 change: 1 addition & 0 deletions lib/splunk-sdk-ruby/collection/jobs.rb
Expand Up @@ -104,6 +104,7 @@ def create_export(query, args={})
return response.body
end

# Deprecated.
def create_stream(query, args={}) # :nodoc:
warn "[DEPRECATION] Jobs#create_stream is deprecated. Use Jobs#create_export instead."
create_export(query, args)
Expand Down
6 changes: 3 additions & 3 deletions lib/splunk-sdk-ruby/entity.rb
Expand Up @@ -43,8 +43,8 @@ class Entity
def initialize(service, namespace, resource, name, state=nil) # :nodoc:
@service = service
@namespace = namespace
if !@namespace.is_proper?
raise StandardError.new("Must provide a proper namespace to " +
if !@namespace.is_exact?
raise StandardError.new("Must provide an exact namespace to " +
"Entity (found: #{@namespace}")
end
@resource = resource
Expand Down Expand Up @@ -181,7 +181,7 @@ def refresh()
raise EntityNotReady.new((@resource + [name]).join("/"))
end
# We are guaranteed a unique entity, since entities must have
# proper namespaces.
# exact namespaces.
feed = AtomFeed.new(response.body)
@state = feed.entries[0]
self
Expand Down
2 changes: 1 addition & 1 deletion lib/splunk-sdk-ruby/entity/index.rb
Expand Up @@ -70,7 +70,7 @@ def attach(args={})
end

##
# Delete all events in this index. DEPRECATED.
# Delete all events in this index. DEPRECATED: Delete the index instead.
#
# +clean+ will wait until the operation completes, or _timeout_
# seconds have passed. By default, _timeout_ is 100 seconds.
Expand Down
26 changes: 13 additions & 13 deletions lib/splunk-sdk-ruby/namespace.rb
Expand Up @@ -24,9 +24,9 @@
# use for the query.
#
# Some namespaces can contain wildcards or default values filled in by Splunk.
# We call such namespaces improper, since they cannot be the namespace of an
# We call such namespaces wildcard, since they cannot be the namespace of an
# entity, only a query. Namespaces which can be the namespace of an entity we
# call proper.
# call exact.
#
# We distinguish six kinds of namespace, each of which is represented by a
# separate class:
Expand All @@ -41,7 +41,7 @@
# in Splunk.
# * +AppNamespace+, one per application installed in the Splunk instance.
# * +AppReferenceNamespace+, which is the namespace that applications themselves
# live in. It differs from +DefaultNamespace+ only in that it is a proper
# live in. It differs from +DefaultNamespace+ only in that it is a exact
# namespace.
# * The user namespaces, which are defined by a user _and_ an application.
#
Expand Down Expand Up @@ -139,16 +139,16 @@ def self.namespace(args)
##
# A mixin that fills the role of an abstract base class.
#
# Namespaces have two methods: +is_proper?+ and +to_path_fragment+, and
# Namespaces have two methods: +is_exact?+ and +to_path_fragment+, and
# can be compared for equality.
#
module Namespace
##
# Is this a proper namespace?
# Is this a exact namespace?
#
# Returns: +true+ or +false+.
#
def is_proper?() end
def is_exact?() end

##
# Returns the URL prefix corresponding to this namespace.
Expand All @@ -165,14 +165,14 @@ def to_path_fragment() end
class GlobalNamespace # :nodoc:
include Singleton
include Namespace
def is_proper?() true end
def is_exact?() true end
def to_path_fragment() ["servicesNS", "nobody", "system"] end
end

class SystemNamespace # :nodoc:
include Singleton
include Namespace
def is_proper?() true end
def is_exact?() true end
def to_path_fragment() ["servicesNS", "nobody", "system"] end
end

Expand All @@ -181,15 +181,15 @@ class DefaultNamespace # :nodoc:
include Namespace
# A services/ namespace always uses the current user
# and current app, neither of which are wildcards, so this
# namespace is guaranteed to be proper.
def is_proper?() true end
# namespace is guaranteed to be exact.
def is_exact?() true end
def to_path_fragment() ["services"] end
end

class AppReferenceNamespace # :nodoc:
include Singleton
include Namespace
def is_proper?() true end
def is_exact?() true end
def to_path_fragment() ["services"] end
end

Expand All @@ -205,7 +205,7 @@ def ==(other)
other.is_a?(AppNamespace) && @app == other.app
end

def is_proper?()
def is_exact?()
@app != "-"
end

Expand All @@ -228,7 +228,7 @@ def ==(other)
@user == other.user
end

def is_proper?()
def is_exact?()
(@app != "-") && (@user != "-")
end

Expand Down

0 comments on commit 3c7d78e

Please sign in to comment.