Skip to content

Commit 2199b5e

Browse files
Merge pull request #414 from splunk/Release-1.6.18
Release 1.6.18
2 parents 7674157 + ae709be commit 2199b5e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+439
-1193
lines changed

.github/workflows/test.yml

-6
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,6 @@ jobs:
4545
echo password=changed! >> .splunkrc
4646
echo scheme=https >> .splunkrc
4747
echo version=${{ matrix.splunk }} >> .splunkrc
48-
- name: Create build dir for ExamplesTestCase::test_build_dir_exists test case
49-
run: |
50-
cd ~
51-
cd /home/runner/work/splunk-sdk-python/splunk-sdk-python/
52-
python setup.py build
53-
python setup.py dist
5448
- name: Install tox
5549
run: pip install tox
5650
- name: Test Execution

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ MANIFEST
1616
coverage_report
1717
test.log
1818
examples/*/local
19-
examples/*/metadata/local.meta
19+
examples/**/local.meta
20+
examples/**/*.log
2021
tests/searchcommands_data/log/
2122
tests/searchcommands_data/output/
2223
examples/searchcommands_app/searchcommand_app.log
2324
Test Results*.html
2425
tests/searchcommands/data/app/app.log
2526
splunk_sdk.egg-info/
2627
dist/
27-
examples/searchcommands_app/package/default/commands.conf
2828
examples/searchcommands_app/package/lib/splunklib
2929
tests/searchcommands/apps/app_with_logging_configuration/*.log
3030
*.observed

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Splunk Enterprise SDK for Python Changelog
22

3+
## Version 1.6.18
4+
5+
### Bug fixes
6+
* [#405](https://github.com/splunk/splunk-sdk-python/pull/405) Fix searchcommands_app example
7+
* [#406](https://github.com/splunk/splunk-sdk-python/pull/406) Fix mod inputs examples
8+
* [#407](https://github.com/splunk/splunk-sdk-python/pull/407) Fixed issue with Streaming and Generating Custom Search Commands dropping fields that aren't present in the first row of results. More details on how to opt-in to this fix can be found here:
9+
https://github.com/splunk/splunk-sdk-python/blob/develop/README.md#customization [ [issue#401](https://github.com/splunk/splunk-sdk-python/issues/401) ]
10+
11+
### Minor changes
12+
* [#408](https://github.com/splunk/splunk-sdk-python/pull/408) Add search mode example
13+
* [#409](https://github.com/splunk/splunk-sdk-python/pull/409) Add Support for authorization tokens read from .splunkrc [ [issue#388](https://github.com/splunk/splunk-sdk-python/issues/388) ]
14+
* [#413](https://github.com/splunk/splunk-sdk-python/pull/413) Default kvstore owner to nobody [ [issue#231](https://github.com/splunk/splunk-sdk-python/issues/231) ]
15+
316
## Version 1.6.17
417

518
### Bug fixes

Makefile

+1-6
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,11 @@ DATE := `date "+%FT%T%z"`
1818
CONTAINER_NAME := 'splunk'
1919

2020
.PHONY: all
21-
all: build_app test
21+
all: test
2222

2323
init:
2424
@echo "$(ATTN_COLOR)==> init $(NO_COLOR)"
2525

26-
.PHONY: build_app
27-
build_app:
28-
@echo "$(ATTN_COLOR)==> build_app $(NO_COLOR)"
29-
@python setup.py build dist
30-
3126
.PHONY: docs
3227
docs:
3328
@echo "$(ATTN_COLOR)==> docs $(NO_COLOR)"

README.md

+78-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# The Splunk Enterprise Software Development Kit for Python
55

6-
#### Version 1.6.17
6+
#### Version 1.6.18
77

88
The Splunk Enterprise Software Development Kit (SDK) for Python contains library code and examples designed to enable developers to build applications using the Splunk platform.
99

@@ -71,6 +71,26 @@ To run the examples and unit tests, you must put the root of the SDK on your PYT
7171

7272
The SDK command-line examples require a common set of arguments that specify the host, port, and login credentials for Splunk Enterprise. For a full list of command-line arguments, include `--help` as an argument to any of the examples.
7373

74+
### Following are the different ways to connect to Splunk Enterprise
75+
#### Using username/password
76+
```python
77+
import splunklib.client as client
78+
service = client.connect(host=<host_url>, username=<username>, password=<password>, autoLogin=True)
79+
```
80+
81+
#### Using bearer token
82+
```python
83+
import splunklib.client as client
84+
service = client.connect(host=<host_url>, splunkToken=<bearer_token>, autologin=True)
85+
```
86+
87+
#### Using session key
88+
```python
89+
import splunklib.client as client
90+
service = client.connect(host=<host_url>, token=<session_key>, autologin=True)
91+
```
92+
93+
###
7494
#### Create a .splunkrc convenience file
7595

7696
To connect to Splunk Enterprise, many of the SDK examples and unit tests take command-line arguments that specify values for the host, port, and login credentials for Splunk Enterprise. For convenience during development, you can store these arguments as key-value pairs in a text file named **.splunkrc**. Then, the SDK examples and unit tests use the values from the **.splunkrc** file when you don't specify them.
@@ -112,8 +132,18 @@ Save the file as **.splunkrc** in the current user's home directory.
112132

113133
Examples are located in the **/splunk-sdk-python/examples** directory. To run the examples at the command line, use the Python interpreter and include any arguments that are required by the example. In the commands below, replace "examplename" with the name of the specific example in the directory that you want to run:
114134

135+
Using username and Password
136+
115137
python examplename.py --username="admin" --password="changeme"
116138

139+
Using Bearer token
140+
141+
python examplename.py --bearerToken=<value>
142+
143+
Using Session key
144+
145+
python examplename.py --sessionKey="<value>"
146+
117147
If you saved your login credentials in the **.splunkrc** file, you can omit those arguments:
118148

119149
python examplename.py
@@ -150,6 +180,53 @@ The test suite uses Python's standard library, the built-in `unittest` library,
150180
|/tests | Source for unit tests |
151181
|/utils | Source for utilities shared by the examples and unit tests |
152182

183+
### Customization
184+
* When working with custom search commands such as Custom Streaming Commands or Custom Generating Commands, We may need to add new fields to the records based on certain conditions.
185+
* Structural changes like this may not be preserved.
186+
* Make sure to use ``add_field(record, fieldname, value)`` method from SearchCommand to add a new field and value to the record.
187+
* ___Note:__ Usage of ``add_field`` method is completely optional, if you are not facing any issues with field retention._
188+
189+
Do
190+
```python
191+
class CustomStreamingCommand(StreamingCommand):
192+
def stream(self, records):
193+
for index, record in enumerate(records):
194+
if index % 1 == 0:
195+
self.add_field(record, "odd_record", "true")
196+
yield record
197+
```
198+
199+
Don't
200+
```python
201+
class CustomStreamingCommand(StreamingCommand):
202+
def stream(self, records):
203+
for index, record in enumerate(records):
204+
if index % 1 == 0:
205+
record["odd_record"] = "true"
206+
yield record
207+
```
208+
### Customization for Generating Custom Search Command
209+
* Generating Custom Search Command is used to generate events using SDK code.
210+
* Make sure to use ``gen_record()`` method from SearchCommand to add a new record and pass event data as a key=value pair separated by , (mentioned in below example).
211+
212+
Do
213+
```python
214+
@Configuration()
215+
class GeneratorTest(GeneratingCommand):
216+
def generate(self):
217+
yield self.gen_record(_time=time.time(), one=1)
218+
yield self.gen_record(_time=time.time(), two=2)
219+
```
220+
221+
Don't
222+
```python
223+
@Configuration()
224+
class GeneratorTest(GeneratingCommand):
225+
def generate(self):
226+
yield {'_time': time.time(), 'one': 1}
227+
yield {'_time': time.time(), 'two': 2}
228+
```
229+
153230
### Changelog
154231

155232
The [CHANGELOG](CHANGELOG.md) contains a description of changes for each version of the SDK. For the latest version, see the [CHANGELOG.md](https://github.com/splunk/splunk-sdk-python/blob/master/CHANGELOG.md) on GitHub.

docker-compose.yml

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ services:
99
- SPLUNK_HEC_TOKEN=11111111-1111-1111-1111-1111111111113
1010
- SPLUNK_PASSWORD=changed!
1111
- SPLUNK_APPS_URL=https://github.com/splunk/sdk-app-collection/releases/download/v1.1.0/sdkappcollection.tgz
12+
volumes:
13+
- ./examples/github_forks:/opt/splunk/etc/apps/github_forks
14+
- ./splunklib:/opt/splunk/etc/apps/github_forks/lib/splunklib
15+
- ./examples/random_numbers:/opt/splunk/etc/apps/random_numbers
16+
- ./splunklib:/opt/splunk/etc/apps/random_numbers/lib/splunklib
17+
- ./examples/searchcommands_app/package:/opt/splunk/etc/apps/searchcommands_app
18+
- ./splunklib:/opt/splunk/etc/apps/searchcommands_app/lib/splunklib
19+
- ./examples/twitted/twitted:/opt/splunk/etc/apps/twitted
1220
ports:
1321
- 8000:8000
1422
- 8088:8088

examples/github_forks/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
splunk-sdk-python github_forks example
2+
========================================
3+
4+
This app provides an example of a modular input that generates the number of repository forks according to the Github API based on the owner and repo_name provided by the user during setup of the input.
5+
6+
To run this example locally run `SPLUNK_VERSION=latest docker compose up -d` from the root of this repository which will mount this example alongside the latest version of splunklib within `/opt/splunk/etc/apps/github_forks` and `/opt/splunk/etc/apps/github_forks/lib/splunklib` within the `splunk` container.
7+
8+
Once the docker container is up and healthy log into the Splunk UI and setup a new `Github Repository Forks` input by visiting this page: http://localhost:8000/en-US/manager/github_forks/datainputstats and selecting the "Add new..." button next to the Local Inputs > Random Inputs. Enter values for a Github Repository owner and repo_name, for example owner = `splunk` repo_name = `splunk-sdk-python`.
9+
10+
NOTE: If no Github Repository Forks input appears then the script is likely not running properly, see https://docs.splunk.com/Documentation/SplunkCloud/latest/AdvancedDev/ModInputsDevTools for more details on debugging the modular input using the command line and relevant logs.
11+
12+
Once the input is created you should be able to see an event when running the following search: `source="github_forks://*"` the event should contain fields for `owner` and `repository` matching the values you input during setup and then a `fork_count` field corresponding to the number of forks the repo has according to the Github API.

examples/github_forks/github_forks.py renamed to examples/github_forks/bin/github_forks.py

+27-8
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,18 @@
1515
# under the License.
1616

1717
from __future__ import absolute_import
18-
import sys, urllib2, json
18+
import os
19+
import sys
20+
import json
21+
# NOTE: splunklib must exist within github_forks/lib/splunklib for this
22+
# example to run! To run this locally use `SPLUNK_VERSION=latest docker compose up -d`
23+
# from the root of this repo which mounts this example and the latest splunklib
24+
# code together at /opt/splunk/etc/apps/github_forks
25+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
1926

2027
from splunklib.modularinput import *
2128
from splunklib import six
29+
from six.moves import http_client
2230

2331
class MyScript(Script):
2432
"""All modular inputs should inherit from the abstract base class Script
@@ -87,11 +95,9 @@ def validate_input(self, validation_definition):
8795
# Get the values of the parameters, and construct a URL for the Github API
8896
owner = validation_definition.parameters["owner"]
8997
repo_name = validation_definition.parameters["repo_name"]
90-
repo_url = "https://api.github.com/repos/%s/%s" % (owner, repo_name)
9198

92-
# Read the response from the Github API, then parse the JSON data into an object
93-
response = urllib2.urlopen(repo_url).read()
94-
jsondata = json.loads(response)
99+
# Call Github to retrieve repo information
100+
jsondata = _get_github_repos(owner, repo_name)
95101

96102
# If there is only 1 field in the jsondata object,some kind or error occurred
97103
# with the Github API.
@@ -125,9 +131,7 @@ def stream_events(self, inputs, ew):
125131
repo_name = input_item["repo_name"]
126132

127133
# Get the fork count from the Github API
128-
repo_url = "https://api.github.com/repos/%s/%s" % (owner, repo_name)
129-
response = urllib2.urlopen(repo_url).read()
130-
jsondata = json.loads(response)
134+
jsondata = _get_github_repos(owner, repo_name)
131135
fork_count = jsondata["forks_count"]
132136

133137
# Create an Event object, and set its fields
@@ -139,5 +143,20 @@ def stream_events(self, inputs, ew):
139143
# Tell the EventWriter to write this event
140144
ew.write_event(event)
141145

146+
147+
def _get_github_repos(owner, repo_name):
148+
# Read the response from the Github API, then parse the JSON data into an object
149+
repo_path = "/repos/%s/%s" % (owner, repo_name)
150+
connection = http_client.HTTPSConnection('api.github.com')
151+
headers = {
152+
'Content-type': 'application/json',
153+
'User-Agent': 'splunk-sdk-python',
154+
}
155+
connection.request('GET', repo_path, headers=headers)
156+
response = connection.getresponse()
157+
body = response.read().decode()
158+
return json.loads(body)
159+
160+
142161
if __name__ == "__main__":
143162
sys.exit(MyScript().run(sys.argv))

examples/random_numbers/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
splunk-sdk-python random_numbers example
2+
========================================
3+
4+
This app provides an example of a modular input that generates a random number between the min and max values provided by the user during setup of the input.
5+
6+
To run this example locally run `SPLUNK_VERSION=latest docker compose up -d` from the root of this repository which will mount this example alongside the latest version of splunklib within `/opt/splunk/etc/apps/random_numbers` and `/opt/splunk/etc/apps/random_numbers/lib/splunklib` within the `splunk` container.
7+
8+
Once the docker container is up and healthy log into the Splunk UI and setup a new `Random Numbers` input by visiting this page: http://localhost:8000/en-US/manager/random_numbers/datainputstats and selecting the "Add new..." button next to the Local Inputs > Random Inputs. Enter values for the `min` and `max` values which the random number should be generated between.
9+
10+
NOTE: If no Random Numbers input appears then the script is likely not running properly, see https://docs.splunk.com/Documentation/SplunkCloud/latest/AdvancedDev/ModInputsDevTools for more details on debugging the modular input using the command line and relevant logs.
11+
12+
Once the input is created you should be able to see an event when running the following search: `source="random_numbers://*"` the event should contain a `number` field with a float between the min and max specified when the input was created.

examples/random_numbers/random_numbers.py renamed to examples/random_numbers/bin/random_numbers.py

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
from __future__ import absolute_import
1818
import random, sys
1919
import os
20+
# NOTE: splunklib must exist within random_numbers/lib/splunklib for this
21+
# example to run! To run this locally use `SPLUNK_VERSION=latest docker compose up -d`
22+
# from the root of this repo which mounts this example and the latest splunklib
23+
# code together at /opt/splunk/etc/apps/random_numbers
2024
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
2125

2226
from splunklib.modularinput import *

examples/search_modes.py

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import sys
2+
import os
3+
# import from utils/__init__.py
4+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
5+
from utils import *
6+
import time
7+
from splunklib.client import connect
8+
from splunklib import results
9+
from splunklib import six
10+
11+
def cmdline(argv, flags, **kwargs):
12+
"""A cmdopts wrapper that takes a list of flags and builds the
13+
corresponding cmdopts rules to match those flags."""
14+
rules = dict([(flag, {'flags': ["--%s" % flag]}) for flag in flags])
15+
return parse(argv, rules, ".splunkrc", **kwargs)
16+
17+
def modes(argv):
18+
opts = cmdline(argv, [])
19+
kwargs_splunk = dslice(opts.kwargs, FLAGS_SPLUNK)
20+
service = connect(**kwargs_splunk)
21+
22+
# By default the job will run in 'smart' mode which will omit events for transforming commands
23+
job = service.jobs.create('search index=_internal | head 10 | top host')
24+
while not job.is_ready():
25+
time.sleep(0.5)
26+
pass
27+
reader = results.ResultsReader(job.events())
28+
# Events found: 0
29+
print('Events found with adhoc_search_level="smart": %s' % len([e for e in reader]))
30+
31+
# Now set the adhoc_search_level to 'verbose' to see the events
32+
job = service.jobs.create('search index=_internal | head 10 | top host', adhoc_search_level='verbose')
33+
while not job.is_ready():
34+
time.sleep(0.5)
35+
pass
36+
reader = results.ResultsReader(job.events())
37+
# Events found: 10
38+
print('Events found with adhoc_search_level="verbose": %s' % len([e for e in reader]))
39+
40+
if __name__ == "__main__":
41+
modes(sys.argv[1:])

examples/searchcommands_app/Build-App

-31
This file was deleted.

0 commit comments

Comments
 (0)