Skip to content

Commit

Permalink
released 0.2.0 see changelog for more details
Browse files Browse the repository at this point in the history
  • Loading branch information
ryancurrah committed Jan 3, 2017
1 parent 2846fc2 commit 795a0a5
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 55 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
## [Unreleased]
## 0.2.0 (January, 4, 2017)
### Added

* More test coverage

### Changed

* Splunk class version method is now a property
* Updated README with correct usage and how to install
* Setup.py adds more packaging information

### Fixed

* Bad Splunk logins are now caught and handled for real this time

## 0.1.0 (January, 3, 2017)

* Initial release
143 changes: 97 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,119 @@
[![Build Status](https://travis-ci.org/ryancurrah/searchsplunk.svg?branch=master)](https://travis-ci.org/ryancurrah/searchsplunk)

[![Coverage Status](https://coveralls.io/repos/github/ryancurrah/searchsplunk/badge.svg?branch=master)](https://coveralls.io/github/ryancurrah/searchsplunk?branch=master)
[![Build Status](https://travis-ci.org/ryancurrah/searchsplunk.svg?branch=master)](https://travis-ci.org/ryancurrah/searchsplunk) [![Coverage Status](https://coveralls.io/repos/github/ryancurrah/searchsplunk/badge.svg?branch=master)](https://coveralls.io/github/ryancurrah/searchsplunk?branch=master)


# Search Splunk

Easily create Splunk searches from Python and get the result as a Python object

# Requires
- requests: https://pypi.python.org/pypi/requests

- requests>=2.7.0: https://pypi.python.org/pypi/requests

# Installation instructions

The [searchsplunk](https://pypi.python.org/pypi/searchsplunk) PyPi package can be installed from pip.

```bash
pip install searchsplunk
```

# Usage instructions

```python
import pprint
pp = pprint.PrettyPrinter(indent=2)

from searchsplunk import SearchSplunk
from searchsplunk.searchsplunk import SearchSplunk
s = SearchSplunk('https://splunk.acme.com:8089', 'MYUSER', 'MYPASS', ssl_verify=True)
result = s.search('sourcetype=salt:grains openstack_uid=e0303456c-d5a3-789f-ab68-8f27561ffa0f | dedup openstack_uid')

pp.pprint(result)
{
u'fields': [ { u'name': u'_bkt'},
{ u'name': u'_cd'},
{ u'name': u'_indextime'},
{ u'name': u'_kv'},
{ u'name': u'_raw'},
{ u'name': u'_serial'},
{ u'name': u'_si'},
{ u'name': u'_sourcetype'},
{ u'name': u'_subsecond'},
{ u'name': u'_time'},
{ u'name': u'host'},
{ u'name': u'index'},
{ u'name': u'linecount'},
{ u'name': u'openstack_uid'},
{ u'name': u'source'},
{ u'name': u'sourcetype'},
{ u'name': u'splunk_server'}],
u'init_offset': 0,
u'messages': [],
u'preview': False,
u'results': [ { u'_bkt': u'main~1122~25B521A6-9612-407D-A1BA-F8KJSEBB7628',
u'_cd': u'1122:290410720',
u'_indextime': u'1435071966',
u'_kv': u'1',
u'_raw': u"somefile contents",
u'_serial': u'0',
u'_si': [u'splunkserv', u'main'],
u'_sourcetype': u'salt:grains',
u'_time': u'2015-06-23T11:06:05.000-04:00',
u'host': u'server-7654.acme.com',
u'index': u'main',
u'linecount': u'17',
u'openstack_uid': u'e0303456c-d5a3-789f-ab68-8f27561ffa0f',
u'source': u'/etc/salt/grains',
u'sourcetype': u'salt:grains',
u'splunk_server': u'splunkmaster'}]
import json
print json.dumps(result, sort_keys=True, indent=2)
{
"fields": [
{
"name": "_bkt"
},
{
"name": "_cd"
},
{
"name": "_indextime"
},
{
"name": "_kv"
},
{
"name": "_raw"
},
{
"name": "_serial"
},
{
"name": "_si"
},
{
"name": "_sourcetype"
},
{
"name": "_subsecond"
},
{
"name": "_time"
},
{
"name": "host"
},
{
"name": "index"
},
{
"name": "linecount"
},
{
"name": "openstack_uid"
},
{
"name": "source"
},
{
"name": "sourcetype"
},
{
"name": "splunk_server"
}
],
"init_offset": 0,
"messages": [],
"preview": false,
"results": [
{
"_bkt": "main~1122~25B521A6-9612-407D-A1BA-F8KJSEBB7628",
"_cd": "1122:290410720",
"_indextime": "1435071966",
"_kv": "1",
"_raw": "somefile contents",
"_serial": "0",
"_si": [
"splunkserv",
"main"
],
"_sourcetype": "salt:grains",
"_time": "2015-06-23T11:06:05.000-04:00",
"host": "server-7654.acme.com",
"index": "main",
"linecount": "17",
"openstack_uid": "e0303456c-d5a3-789f-ab68-8f27561ffa0f",
"source": "/etc/salt/grains",
"sourcetype": "salt:grains",
"splunk_server": "splunkmaster"
}
]
}
```

## Author

[Ryan Currah](ryan@currah.ca)

## License

GPL v2

9 changes: 5 additions & 4 deletions searchsplunk/searchsplunk.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import warnings
import requests
from xml.dom import minidom
from xml.parsers.expat import ExpatError
from .exceptions import SplunkInvalidCredentials
from .version import __version__

Expand Down Expand Up @@ -31,8 +32,8 @@ def __init__(self, url, username, password, ssl_verify=True):
self.__login()
return

@staticmethod
def version():
@property
def version(self):
"""
Get the module version
Expand All @@ -58,9 +59,9 @@ def __login(self):
self.session_key = minidom.parseString(
r.text
).getElementsByTagName('sessionKey')[0].childNodes[0].nodeValue
except (IndexError, KeyError):
except (IndexError, KeyError, ExpatError):
raise SplunkInvalidCredentials(
'HTTP status code:\n{0}\nError message:\n{1]'.format(
'HTTP status code:\n{0}\nError message:\n{1}'.format(
r.status_code,
r.text
)
Expand Down
50 changes: 49 additions & 1 deletion searchsplunk/tests/test_searchsplunk.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import re
import httpretty
import pytest
from searchsplunk.searchsplunk import SearchSplunk
from searchsplunk.exceptions import SplunkInvalidCredentials


auth_response = """<response>
<sessionKey>abc123efg456</sessionKey>
</response>
"""

bad_auth_response = """
Invalid login credentials!
"""

search_response = """<?xml version="1.0" encoding="UTF-8"?>
<response>
<sid>1483419124.3</sid>
Expand Down Expand Up @@ -106,6 +112,9 @@

@pytest.mark.httpretty
def test_searchsplunk():
"""
Login and running a search should return a result
"""
httpretty.register_uri(
httpretty.POST,
'http://example.com/services/auth/login',
Expand Down Expand Up @@ -138,5 +147,44 @@ def test_searchsplunk():
'openstack_uid=e0303456c-d5a3-789f-ab68-8f27561ffa0f | '
'dedup openstack_uid'
)

assert len(result['results']) == 1


@pytest.mark.httpretty
def test_version_is_valid():
"""
Getting the module version should work as expected
"""
httpretty.register_uri(
httpretty.POST,
'http://example.com/services/auth/login',
body=auth_response
)

s = SearchSplunk(
'http://example.com/',
'MYUSER',
'MYPASS'
)
print type(s.version)
print s.version
assert bool(re.match(r'^\d+\.\d+\.\d+$', str(s.version))) is True


@pytest.mark.httpretty
def test_bad_login():
"""
Bad login should raise a SplunkInvalidCredentials exception
"""
httpretty.register_uri(
httpretty.POST,
'http://example.com/services/auth/login',
body=bad_auth_response
)

with pytest.raises(SplunkInvalidCredentials):
SearchSplunk(
'http://example.com/',
'MYUSER',
'MYPASS'
)
2 changes: 1 addition & 1 deletion searchsplunk/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
Reports the version of the module
"""
__version__ = '0.1.0'
__version__ = '0.2.0'
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
[metadata]
description = README.md

[bdist_wheel]
universal=1

[aliases]
test=pytest

Expand Down
20 changes: 18 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
#!/usr/bin/env python
from codecs import open
from os import path
from setuptools import setup, find_packages

# Get the long description from the README file
here = path.abspath(path.dirname(__file__))
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()

setup(
name='searchsplunk',
version='0.1.0',
version='0.2.0',
description='Splunk search client',
long_description=long_description,
author='Ryan Currah',
author_email='ryan@currah.ca',
url='https://github.com/ryancurrah/searchsplunk',
license='GPLv2',
keywords=['splunk', 'search'],
classifiers=['License :: OSI Approved :: GNU General Public License version 2'],
classifiers=[
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5'
],
packages=find_packages(),
install_requires=[
'requests>=2.7.0'
Expand Down

0 comments on commit 795a0a5

Please sign in to comment.