Skip to content

Commit c789da4

Browse files
author
Shakeel Mohamed
committed
Updated docstrings, moved *_testlib to /tests/modularinput/, general code cleanup
1 parent 0abf611 commit c789da4

File tree

11 files changed

+240
-152
lines changed

11 files changed

+240
-152
lines changed

splunklib/modularinput/argument.py

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,52 +17,69 @@
1717
except ImportError:
1818
import xml.etree.cElementTree as ET
1919

20-
#TODO: extend docs
21-
2220
class Argument(object):
23-
"""Class representing an argument to a modular input kind."""
24-
def __init__(self, name):
25-
"""
26-
:param name: string identifier for this argument in Splunk
27-
"""
28-
self.name = name
29-
self.description = None
30-
self.validation = None
21+
"""Class representing an argument to a modular input kind.
22+
Argument is meant to be used with Scheme to generate an XML definition of the modular input
23+
kind that Splunk understands."""
24+
25+
# Constant values, do not change
26+
dataTypeBoolean = "BOOLEAN"
27+
dataTypeNumber = "NUMBER"
28+
dataTypeString = "STRING"
29+
30+
def __init__(self, name, description=None, validation=None, \
31+
dataType=dataTypeString, requiredOnEdit=False, requiredOnCreate=False):
32+
"""name is the only required parameter for the constructor
3133
32-
# Constant values, do not change
33-
self.dataTypeBoolean = "BOOLEAN"
34-
self.dataTypeNumber = "NUMBER"
35-
self.dataTypeString = "STRING"
34+
Example with least parameters:
3635
37-
self.dataType = self.dataTypeString
36+
arg1 = Argument(name="arg1")
3837
39-
self.requiredOnEdit = False
40-
self.requiredOnCreate = False
38+
Example with all parameters:
4139
42-
def addToDocument(self, parent):
40+
arg2 = Argument(
41+
name="arg2",
42+
description="This is an argument with lots of parameters",
43+
validation="is_pos_int('some_name')",
44+
dataType=Argument.dataTypeNumber,
45+
requiredOnEdit=True,
46+
requiredOnCreate=True
47+
)
48+
49+
:param name: string, identifier for this argument in Splunk
50+
:param description: string, human readable description of the argument
51+
:param validation: string, specifying how the argument should be validated, if using internal validation. If using
52+
external validation, this will be ignored.
53+
:param dataType: string, data type of this field; use the class constants
54+
dataTypeBoolean, dataTypeNumber, or dataTypeString
55+
:param requiredOnEdit: boolean, is this arg required when editing an existing modular input of this kind?
56+
:param requiredOnCreate: boolean, is this arg required when creating a modular input of this kind?
57+
"""
58+
self.name = name
59+
self.description = description
60+
self.validation = validation
61+
self.dataType = dataType
62+
self.requiredOnEdit = requiredOnEdit
63+
self.requiredOnCreate = requiredOnCreate
64+
65+
def add_to_document(self, parent):
4366
"""Adds an <arg> SubElement to the Parent Element, typically <args>
67+
and setup its subelements with their respective text
4468
4569
:param parent: an ET.Element to be the parent of a new <arg> SubElement
4670
:return: an ET.Element object representing this argument #TODO: might not need to return here..
4771
"""
4872
arg = ET.SubElement(parent, "arg")
4973
arg.set("name", self.name)
5074

51-
if self.description:
52-
description = ET.SubElement(arg, "description")
53-
description.text = self.description
75+
if self.description is not None:
76+
ET.SubElement(arg, "description").text = self.description
5477

5578
if self.validation:
56-
validation = ET.SubElement(arg, "validation")
57-
validation.text = self.validation
58-
59-
data_type = ET.SubElement(arg, "data_type")
60-
data_type.text = self.dataType.lower()
61-
62-
required_on_edit = ET.SubElement(arg, "required_on_edit")
63-
required_on_edit.text = str(self.requiredOnEdit).lower()
79+
ET.SubElement(arg, "validation").text = self.validation
6480

65-
required_on_create = ET.SubElement(arg, "required_on_create")
66-
required_on_create.text = str(self.requiredOnCreate).lower()
81+
ET.SubElement(arg, "data_type").text = self.dataType.lower()
82+
ET.SubElement(arg, "required_on_edit").text = str(self.requiredOnEdit).lower()
83+
ET.SubElement(arg, "required_on_create").text = str(self.requiredOnCreate).lower()
6784

6885
return arg

splunklib/modularinput/event.py

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,52 +17,90 @@
1717
except ImportError as ie:
1818
import xml.etree.ElementTree as ET
1919

20-
#todo: extend the docs. What would you want to know about this class if you were faced with it for the first time and had to use it?
21-
2220
class Event(object):
23-
"""Represents an event or fragment of an event to be written by this modular input to Splunk."""
24-
def __init__(self):
25-
self.data = None
26-
self.done = True
27-
self.host = None
28-
self.index = None
29-
self.source = None
30-
self.sourceType = None
31-
self.stanza = None
32-
self.time = None
33-
self.unbroken = True
21+
"""Represents an event or fragment of an event to be written by this modular input to Splunk.
22+
23+
To write an input to a stream, call the write_to function, passing in a stream.
24+
"""
25+
def __init__(self, data=None, stanza=None, time=None, host=None, index=None, source=None,\
26+
sourceType=None, done=True, unbroken=True):
27+
"""There are no required parameters for constructing an Event
28+
29+
Example with minimal configuration:
30+
31+
my_event = Event(
32+
data="This is a test of my new event.",
33+
stanza="myStanzaName",
34+
time="%.3f" % 1372187084.000
35+
)
36+
37+
Example with full configuration:
38+
39+
excellent_event = Event(
40+
data="This is a test of my excellent event.",
41+
stanza="excellenceOnly",
42+
time="%.3f" % 1372274622.493,
43+
host="localhost",
44+
index="main",
45+
source="Splunk",
46+
sourceType="misc",
47+
done=True,
48+
unbroken=True
49+
)
50+
51+
:param data: string, the event's text
52+
:param stanza: string, name of the input this event should be sent to
53+
:param time: float, time in seconds, including up to 3 decimal places to represent milliseconds
54+
:param host: string, the event's host, ex: localhost
55+
:param index: string, the index this event is specified to write to, or None if default index
56+
:param source: string, the source of this event, or None to have Splunk guess
57+
:param sourceType: string, source type currently set on this event, or None to have Splunk guess
58+
:param done: boolean, is this a complete Event? False if an Event fragment
59+
:param unbroken: boolean, Is this event completely encapsulated in this Event object?
60+
"""
61+
self.data = data
62+
self.done = done
63+
self.host = host
64+
self.index = index
65+
self.source = source
66+
self.sourceType = sourceType
67+
self.stanza = stanza
68+
self.time = time
69+
self.unbroken = unbroken
3470

3571
def write_to(self, stream):
36-
"""Write an XML representation of self, an Event, to the given stream
72+
"""Write an XML representation of self, an Event object, to the given stream
73+
74+
The Event object will only be written if its data field is defined
3775
3876
:param stream: stream to write XML to
3977
"""
40-
if not self.data:
78+
if self.data is None:
4179
raise ValueError("Events must have at least the data field set to be written to XML.")
4280

4381
event = ET.Element("event")
44-
if self.stanza:
82+
if self.stanza is not None:
4583
event.set("stanza", self.stanza)
4684
event.set("unbroken", str(int(self.unbroken)))
4785

4886
# if a time isn't set, let Splunk guess by not creating a <time> element
49-
if self.time:
87+
if self.time is not None:
5088
ET.SubElement(event, "time").text = str(self.time)
5189

52-
# add all other subelements to this event
53-
subElements = [
90+
# add all other subelements to this event, represented by (tag, text)
91+
subelements = [
5492
("source", self.source),
5593
("sourceType", self.sourceType),
5694
("index", self.index),
5795
("host", self.host),
5896
("data", self.data)
5997
]
60-
for node, value in subElements:
98+
for node, value in subelements:
6199
if value:
62100
ET.SubElement(event, node).text = value
63101

64102
if self.done:
65-
done = ET.SubElement(event, "done")
103+
ET.SubElement(event, "done")
66104

67105
stream.write(ET.tostring(event))
68106
stream.flush()

splunklib/modularinput/event_writer.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,26 @@
2020
except ImportError:
2121
from StringIO import StringIO
2222

23-
#todo: extend the docs. What would you want to know about this class if you were faced with it for the first time and had to use it?
24-
2523
class EventWriter(object):
26-
"""EventWriter writes events and error messages to Splunk from a modular input."""
24+
"""EventWriter writes events and error messages to Splunk from a modular input.
25+
26+
Its two important methods are writeEvent, which takes an Event object,
27+
and log, which takes a severity and an error message.
28+
"""
29+
30+
# Severities that Splunk understands for log messages from modular inputs.
31+
# Do not change these
32+
DEBUG = "DEBUG"
33+
INFO = "INFO"
34+
WARN = "WARN"
35+
ERROR = "ERROR"
36+
FATAL = "FATAL"
37+
2738
def __init__(self, output = sys.stdout, error = sys.stderr):
2839
"""
2940
:param output: where to write the output, defaults to sys.stdout
30-
:param error:
41+
:param error: where to write any errors, defaults to sys.stderr
3142
"""
32-
# The severities that Splunk understands for log messages from modular inputs.
33-
self.DEBUG = "DEBUG"
34-
self.INFO = "INFO"
35-
self.WARN = "WARN"
36-
self.ERROR = "ERROR"
37-
self.FATAL = "FATAL"
38-
3943
self._out = output
4044
self._err = error
4145

@@ -44,6 +48,9 @@ def __init__(self, output = sys.stdout, error = sys.stderr):
4448

4549
def write_event(self, event):
4650
"""Write an Event object to Splunk.
51+
If the opening <stream> tag hasn't been written,
52+
write it & set header_written to True
53+
Then, write the event.
4754
4855
:param event: an Event object
4956
"""
@@ -55,18 +62,19 @@ def write_event(self, event):
5562
event.write_to(self._out)
5663

5764
def log(self, severity, message):
58-
"""Log messages about the state of this modular input to Splunk. These messages will show up in Splunk's
59-
internal logs
65+
"""Log messages about the state of this modular input to Splunk.
66+
These messages will show up in Splunk's internal logs
6067
61-
:param severity: string, severity of message, see severites in __init__
68+
:param severity: string, severity of message, see severites defined as class constants
6269
:param message: message to log
6370
"""
6471

6572
self._err.write("%s %s\n" % (severity, message))
6673
self._err.flush()
6774

6875
def write_xml_document(self, document):
69-
"""Write an ElementTree to the output stream
76+
"""Write a string representation of an
77+
ElementTree object to the output stream
7078
7179
:param document: an ElementTree object
7280
"""

splunklib/modularinput/input_definition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import xml.etree.cElementTree as ET
1515
except ImportError as ie:
1616
import xml.etree.ElementTree as ET
17-
from splunklib.modularinput.modularinput_testlib import parse_xml_data
17+
from tests.modularinput.modularinput_testlib import parse_xml_data
1818

1919
class InputDefinition:
2020
"""InputDefinition encodes the XML defining inputs that Splunk passes to

splunklib/modularinput/scheme.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,24 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15-
from splunklib.modularinput.argument import Argument
16-
1715
try:
1816
import xml.etree.cElementTree as ET
1917
except ImportError:
2018
import xml.etree.ElementTree as ET
2119

22-
#TODO: extend docs
23-
2420
class Scheme(object):
25-
"""Class representing the metadata for a modular input kind."""
21+
"""Class representing the metadata for a modular input kind.
22+
23+
A Scheme specifies a title, description, several options of how Splunk should run modular inputs of this
24+
kind, and a set of arguments which define a particular modular input's properties.
25+
26+
The primary use of Scheme is to abstract away the construction of XML to feed to Splunk.
27+
"""
28+
29+
# Constant values, do not change
30+
streamingModeSimple = "SIMPLE"
31+
streamingModeXML = "XML"
32+
2633
def __init__(self, title):
2734
"""
2835
:param title: string identifier for this Scheme in Splunk
@@ -31,25 +38,20 @@ def __init__(self, title):
3138
self.description = None
3239
self.useExternalValidation = True
3340
self.useSingleInstance = False
41+
self.streamingMode = Scheme.streamingModeXML
3442

35-
# Constant values, do not change
36-
self.streamingModeSimple = "SIMPLE"
37-
self.streamingModeXML = "XML"
38-
39-
self.streamingMode = self.streamingModeXML
40-
41-
#List of Argument objects
43+
# list of Argument objects, each to be represented by an <arg> tag
4244
self.arguments = []
4345

44-
def addArgument(self, arg):
45-
"""Add the provided argument, arg, to self.arguments
46+
def add_argument(self, arg):
47+
"""Add the provided argument, arg, to the self.arguments list
4648
4749
:param arg: an Argument object to add to self.arguments
4850
"""
4951
self.arguments.append(arg)
5052

51-
def toXML(self):
52-
"""Creates an ET.Element representing this scheme, then returns it
53+
def to_XML(self):
54+
"""Creates an ET.Element representing self, then returns it
5355
5456
:return root, an ET.Element representing this scheme
5557
"""
@@ -58,10 +60,12 @@ def toXML(self):
5860
title = ET.SubElement(root, "title")
5961
title.text = self.title
6062

61-
if self.description:
63+
# add a description subelement if it's defined
64+
if self.description is not None:
6265
description = ET.SubElement(root, "description")
6366
description.text = self.description
6467

68+
# add other subelements
6569
use_external_validation = ET.SubElement(root, "use_external_validation")
6670
use_external_validation.text = str(self.useExternalValidation).lower()
6771

@@ -75,7 +79,8 @@ def toXML(self):
7579

7680
args = ET.SubElement(endpoint, "args")
7781

82+
# add arguments as subelements to the <args> element
7883
for arg in self.arguments:
79-
arg.addToDocument(args)
84+
arg.add_to_document(args)
8085

8186
return root

splunklib/modularinput/validation_definition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import xml.etree.cElementTree as ET
1818
except ImportError as ie:
1919
import xml.etree.ElementTree as ET
20-
from splunklib.modularinput.modularinput_testlib import parse_xml_data
20+
from tests.modularinput.modularinput_testlib import parse_xml_data
2121

2222
class ValidationDefinition(object):
2323
"""This class represents the XML sent by Splunk for external validation of a new modular input.

0 commit comments

Comments
 (0)