Skip to content

Commit 52d1363

Browse files
author
Shakeel Mohamed
committed
Merge branch 'feature/modInputs' into develop
2 parents d68a895 + 6308a25 commit 52d1363

39 files changed

+1854
-6
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ proxy.log
1313
MANIFEST
1414
coverage_report
1515
test.log
16+
examples/*/local
17+
examples/*/metadata
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[github_forks://<name>]
2+
*Streams events giving the number of forks of a GitHub repository
3+
4+
owner = <value>
5+
repo_name = <value>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[install]
2+
is_configured = 0
3+
4+
[ui]
5+
is_visible = 1
6+
label = Github Repository Forks
7+
8+
[launcher]
9+
author=Splunk
10+
description=Streams events giving the number of forks of a GitHub repository
11+
version = 1.0

examples/github_forks/github_forks.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#!/usr/bin/env python
2+
#
3+
# Copyright 2013 Splunk, Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"): you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
import sys, urllib2, json
18+
19+
from splunklib.modularinput import *
20+
21+
try:
22+
import xml.etree.cElementTree as ET
23+
except ImportError:
24+
import xml.etree.ElementTree as ET
25+
26+
class MyScript(Script):
27+
"""All modular inputs should inherit from the abstract base class Script
28+
from splunklib.modularinput.script.
29+
They must override the get_scheme and stream_events functions, and,
30+
if the scheme returned by get_scheme has Scheme.use_external_validation
31+
set to True, the validate_input function.
32+
"""
33+
def get_scheme(self):
34+
"""When Splunk starts, it looks for all the modular inputs defined by
35+
its configuration, and tries to run them with the argument --scheme.
36+
Splunkd expects the modular inputs to print a description of the
37+
input in XML on stdout. The modular input framework takes care of all
38+
the details of formatting XML and printing it. The user need only
39+
override get_scheme and return a new Scheme object.
40+
41+
:return: scheme, a Scheme object
42+
"""
43+
# Splunk will display "Github Repository Forks" to users for this input
44+
scheme = Scheme("Github Repository Forks")
45+
46+
scheme.description = "Streams events giving the number of forks of a GitHub repository."
47+
# If you set external validation to True, without overriding validate_input,
48+
# the script will accept anything as valid. Generally you only need external
49+
# validation if there are relationships you must maintain among the
50+
# parameters, such as requiring min to be less than max in this example,
51+
# or you need to check that some resource is reachable or valid.
52+
# Otherwise, Splunk lets you specify a validation string for each argument
53+
# and will run validation internally using that string.
54+
scheme.use_external_validation = True
55+
scheme.use_single_instance = True
56+
57+
owner_argument = Argument("owner")
58+
owner_argument.data_type = Argument.data_type_string
59+
owner_argument.description = "Github user or organization that created the repository."
60+
owner_argument.required_on_create = True
61+
# If you are not using external validation, you would add something like:
62+
#
63+
# scheme.validation = "owner==splunk"
64+
scheme.add_argument(owner_argument)
65+
66+
repo_name_argument = Argument("repo_name")
67+
repo_name_argument.data_type = Argument.data_type_string
68+
repo_name_argument.description = "Name of the Github repository."
69+
repo_name_argument.required_on_create = True
70+
scheme.add_argument(repo_name_argument)
71+
72+
return scheme
73+
74+
def validate_input(self, validation_definition):
75+
"""In this example we are using external validation to verify that the Github
76+
repository exists. If validate_input does not raise an Exception, the input
77+
is assumed to be valid. Otherwise it prints the exception as an error message
78+
when telling splunkd that the configuration is invalid.
79+
80+
When using external validation, after splunkd calls the modular input with
81+
--scheme to get a scheme, it calls it again with --validate-arguments for
82+
each instance of the modular input in its configuration files, feeding XML
83+
on stdin to the modular input to do validation. It is called the same way
84+
whenever a modular input's configuration is edited.
85+
86+
:param validation_definition: a ValidationDefinition object
87+
"""
88+
# Get the values of the parameters, and construct a URL for the Github API
89+
owner = validation_definition.parameters["owner"]
90+
repo_name = validation_definition.parameters["repo_name"]
91+
repo_url = "https://api.github.com/repos/%s/%s" % (owner, repo_name)
92+
93+
# Read the response from the Github API, then parse the JSON data into an object
94+
response = urllib2.urlopen(repo_url).read()
95+
jsondata = json.loads(response)
96+
97+
# If there is only 1 field in the jsondata object,some kind or error occurred
98+
# with the Github API.
99+
# Typically, this will happen with an invalid repository.
100+
if len(jsondata) == 1:
101+
raise ValueError("The Github repository was not found.")
102+
103+
# If the API response seems normal, validate the fork count
104+
# If there's something wrong with getting fork_count, raise a ValueError
105+
try:
106+
fork_count = int(jsondata["forks_count"])
107+
except ValueError as ve:
108+
raise ValueError("Invalid fork count: %s", ve.message)
109+
110+
def stream_events(self, inputs, ew):
111+
"""This function handles all the action: splunk calls this modular input
112+
without arguments, streams XML describing the inputs to stdin, and waits
113+
for XML on stout describing events.
114+
115+
If you set use_single_instance to True on the scheme in get_scheme, it
116+
will pass all the instances of this input to a single instance of this
117+
script.
118+
119+
:param inputs: an InputDefinition object
120+
:param ew: an EventWriter object
121+
"""
122+
# Go through each input for this modular input
123+
for input_name, input_item in inputs.inputs.iteritems():
124+
# Get fields from the InputDefinition object
125+
owner = input_item["owner"]
126+
repo_name = input_item["repo_name"]
127+
128+
# Get the fork count from the Github API
129+
repo_url = "https://api.github.com/repos/%s/%s" % (owner, repo_name)
130+
response = urllib2.urlopen(repo_url).read()
131+
jsondata = json.loads(response)
132+
fork_count = jsondata["forks_count"]
133+
134+
# Create an Event object, and set its fields
135+
event = Event()
136+
event.stanza = input_name
137+
event.data = 'owner="%s" repository="%s" fork_count=%s' % \
138+
(owner.replace('"', '\\"'), repo_name.replace('"', '\\"'), fork_count)
139+
140+
# Tell the EventWriter to write this event
141+
ew.write_event(event)
142+
143+
if __name__ == "__main__":
144+
sys.exit(MyScript().run(sys.argv))
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[random_numbers://<name>]
2+
*Generates events containing a random floating point number.
3+
4+
min = <value>
5+
max = <value>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[install]
2+
is_configured = 0
3+
4+
[ui]
5+
is_visible = 1
6+
label = Random Numbers
7+
8+
[launcher]
9+
author=Splunk
10+
description=Streams events containing a random number
11+
version = 1.0
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/usr/bin/env python
2+
#
3+
# Copyright 2013 Splunk, Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"): you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
import random, sys
18+
19+
from splunklib.modularinput import *
20+
21+
try:
22+
import xml.etree.cElementTree as ET
23+
except ImportError:
24+
import xml.etree.ElementTree as ET
25+
26+
class MyScript(Script):
27+
"""All modular inputs should inherit from the abstract base class Script
28+
from splunklib.modularinput.script.
29+
They must override the get_scheme and stream_events functions, and,
30+
if the scheme returned by get_scheme has Scheme.use_external_validation
31+
set to True, the validate_input function.
32+
"""
33+
def get_scheme(self):
34+
"""When Splunk starts, it looks for all the modular inputs defined by
35+
its configuration, and tries to run them with the argument --scheme.
36+
Splunkd expects the modular inputs to print a description of the
37+
input in XML on stdout. The modular input framework takes care of all
38+
the details of formatting XML and printing it. The user need only
39+
override get_scheme and return a new Scheme object.
40+
41+
:return: scheme, a Scheme object
42+
"""
43+
# "random_numbers" is the name Splunk will display to users for this input.
44+
scheme = Scheme("Random Numbers")
45+
46+
scheme.description = "Streams events containing a random number."
47+
# If you set external validation to True, without overriding validate_input,
48+
# the script will accept anything as valid. Generally you only need external
49+
# validation if there are relationships you must maintain among the
50+
# parameters, such as requiring min to be less than max in this example,
51+
# or you need to check that some resource is reachable or valid.
52+
# Otherwise, Splunk lets you specify a validation string for each argument
53+
# and will run validation internally using that string.
54+
scheme.use_external_validation = True
55+
scheme.use_single_instance = True
56+
57+
min_argument = Argument("min")
58+
min_argument.data_type = Argument.data_type_number
59+
min_argument.description = "Minimum random number to be produced by this input."
60+
min_argument.required_on_create = True
61+
# If you are not using external validation, you would add something like:
62+
#
63+
# setValidation("min > 0");
64+
scheme.add_argument(min_argument)
65+
66+
max_argument = Argument("max")
67+
max_argument.data_type = Argument.data_type_number
68+
max_argument.description = "Maximum random number to be produced by this input."
69+
max_argument.required_on_create = True
70+
scheme.add_argument(max_argument)
71+
72+
return scheme
73+
74+
def validate_input(self, validation_definition):
75+
"""In this example we are using external validation to verify that min is
76+
less than max. If validate_input does not raise an Exception, the input is
77+
assumed to be valid. Otherwise it prints the exception as an error message
78+
when telling splunkd that the configuration is invalid.
79+
80+
When using external validation, after splunkd calls the modular input with
81+
--scheme to get a scheme, it calls it again with --validate-arguments for
82+
each instance of the modular input in its configuration files, feeding XML
83+
on stdin to the modular input to do validation. It is called the same way
84+
whenever a modular input's configuration is edited.
85+
86+
:param validation_definition: a ValidationDefinition object
87+
"""
88+
# Get the parameters from the ValidationDefinition object,
89+
# then typecast the values as floats
90+
minimum = float(validation_definition.parameters["min"])
91+
maximum = float(validation_definition.parameters["max"])
92+
93+
if minimum >= maximum:
94+
raise ValueError("min must be less than max; found min=%f, max=%f" % minimum, maximum)
95+
96+
def stream_events(self, inputs, ew):
97+
"""This function handles all the action: splunk calls this modular input
98+
without arguments, streams XML describing the inputs to stdin, and waits
99+
for XML on stout describing events.
100+
101+
If you set use_single_instance to True on the scheme in get_scheme, it
102+
will pass all the instances of this input to a single instance of this
103+
script.
104+
105+
:param inputs: an InputDefinition object
106+
:param ew: an EventWriter object
107+
"""
108+
# Go through each input for this modular input
109+
for input_name, input_item in inputs.inputs.iteritems():
110+
# Get the values, cast them as floats
111+
minimum = float(input_item["min"])
112+
maximum = float(input_item["max"])
113+
114+
# Create an Event object, and set its data fields
115+
event = Event()
116+
event.stanza = input_name
117+
event.data = "number=\"%s\"" % str(random.uniform(minimum, maximum))
118+
119+
# Tell the EventWriter to write this event
120+
ew.write_event(event)
121+
122+
if __name__ == "__main__":
123+
sys.exit(MyScript().run(sys.argv))

0 commit comments

Comments
 (0)