Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/2.1.0 #595

Merged
merged 35 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ca3d9eb
Add exception logging in Script
kkedziak-splunk Feb 22, 2024
d9492f5
Merge branch 'master' into feature/improve_logging
kkedziak-splunk Apr 5, 2024
2869237
Revert CHANGELOG.md
kkedziak-splunk Apr 5, 2024
e5f7af0
Revert README.md
kkedziak-splunk Apr 5, 2024
3dab0b5
Update __init__.py
kkedziak-splunk Apr 5, 2024
be7dfe0
Refactor comment
kkedziak-splunk May 8, 2024
40e7b2a
DVPL-0: don't use latest splunk version because of HEC token issue
maszyk99 May 16, 2024
75806e6
Merge pull request #576 from splunk/DVPL-0/change-splunk-versions
maszyk99 May 17, 2024
e4a07be
Merge branch 'refs/heads/develop' into feature/improve_logging
kkedziak-splunk May 20, 2024
3ef0519
Change
kkedziak-splunk May 21, 2024
8d74bd5
Merge pull request #559 from kkedziak-splunk/feature/improve_logging
maszyk99 May 23, 2024
1a2d17f
Add python2/3 utils file back
maszyk99 Jun 25, 2024
ba04e1b
Merge pull request #578 from splunk/DVPL-0/add-six-py-back
maszyk99 Jun 27, 2024
a02b2ce
update pipelines so they would be testing python3.13
szymonjas Oct 15, 2024
a4085e0
DVPL-0: enable manual workflow trigger
maszyk99 Oct 16, 2024
6b55844
DVPL-0: fix test pipeline
maszyk99 Oct 20, 2024
eeb1ecf
Merge pull request #587 from splunk/DVPL-0/enable-manual-workflow-tri…
maszyk99 Oct 20, 2024
93f51c4
Add Service.macros
Synse Feb 13, 2023
6de12b1
Add tests for macros
Synse Feb 13, 2023
e7ba1c1
Merge pull request #589 from splunk/test-macros-pr
maszyk99 Oct 21, 2024
6ec2559
remove commands used to run test directly from setup.py
szymonjas Oct 24, 2024
1b44135
modify tox ini not to use deprecated libraries for unittests and add …
szymonjas Oct 24, 2024
97e1b60
Merge remote-tracking branch 'origin/develop' into DVPL-11087-Python3.13
szymonjas Oct 24, 2024
2f2e174
modify testing traceback so it would filter out additions to tracback…
szymonjas Oct 24, 2024
e3f3968
Revert "DVPL-0: don't use latest splunk version because of HEC token …
maszyk99 Oct 25, 2024
0c9469d
Merge pull request #593 from splunk/DVPL-0/update-splunk-image
szymonjas Oct 28, 2024
a8948f8
resolve conflicts
szymonjas Oct 29, 2024
41e8948
Merge remote-tracking branch 'origin/develop' into VULN-17383
szymonjas Oct 29, 2024
2a8931e
Merge pull request #590 from splunk/VULN-17383
szymonjas Oct 29, 2024
2b90307
Merge pull request #592 from splunk/DVPL-11087-Python3.13
szymonjas Oct 29, 2024
daf1bcd
Merge remote-tracking branch 'origin/master' into develop
szymonjas Oct 29, 2024
f637ade
use SSL DEFAULT CONTEX, use tls version min 1.2, allow for usage of S…
szymonjas Sep 25, 2024
180cdd2
Add changelog
szymonjas Oct 29, 2024
25c44e9
update changelog
szymonjas Oct 29, 2024
d36db5e
update ReadMe
szymonjas Oct 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Python CI

on:
[ push, pull_request ]
[ push, pull_request, workflow_dispatch ]

jobs:
build:
Expand All @@ -11,7 +11,7 @@ jobs:
matrix:
os:
- ubuntu-latest
python: [ 3.7, 3.9]
python: [ 3.7, 3.9, 3.13]
splunk-version:
- "8.1"
- "8.2"
Expand All @@ -22,8 +22,8 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3

- name: Run docker-compose
run: SPLUNK_VERSION=${{matrix.splunk-version}} docker-compose up -d
- name: Run docker compose
run: SPLUNK_VERSION=${{matrix.splunk-version}} docker compose up -d

- name: Setup Python
uses: actions/setup-python@v4
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Splunk Enterprise SDK for Python Changelog

## Version 2.1.0

### Changes
* [#516](https://github.com/splunk/splunk-sdk-python/pull/516) Added support for macros
* Remove deprecated `wrap_socket` in `Contex` class.
* Added explicit support for self signed certificates in https
* Enforce minimal required tls version in https connection
* Add support for python 3.13
* [#559](https://github.com/splunk/splunk-sdk-python/pull/559/) Add exception logging

## Version 2.0.2

### Minor changes
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# The Splunk Enterprise Software Development Kit for Python

#### Version 2.0.2
#### Version 2.1.0

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

Expand All @@ -25,9 +25,9 @@ The Splunk Enterprise SDK for Python contains library code, and its examples are

Here's what you need to get going with the Splunk Enterprise SDK for Python.

* Python 3.7 or Python 3.9
* Python 3.7, Python 3.9 and Python 3.13

The Splunk Enterprise SDK for Python is compatible with python3 and has been tested with Python v3.7 and v3.9.
The Splunk Enterprise SDK for Python is compatible with python3 and has been tested with Python v3.7, v3.9 and v3.13.

* Splunk Enterprise 9.2 or 8.2

Expand Down
111 changes: 1 addition & 110 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,124 +14,15 @@
# License for the specific language governing permissions and limitations
# under the License.

from setuptools import setup, Command

import os
import sys
from setuptools import setup

import splunklib

failed = False

def run_test_suite():
import unittest

def mark_failed():
global failed
failed = True

class _TrackingTextTestResult(unittest._TextTestResult):
def addError(self, test, err):
unittest._TextTestResult.addError(self, test, err)
mark_failed()

def addFailure(self, test, err):
unittest._TextTestResult.addFailure(self, test, err)
mark_failed()

class TrackingTextTestRunner(unittest.TextTestRunner):
def _makeResult(self):
return _TrackingTextTestResult(
self.stream, self.descriptions, self.verbosity)

original_cwd = os.path.abspath(os.getcwd())
os.chdir('tests')
suite = unittest.defaultTestLoader.discover('.')
runner = TrackingTextTestRunner(verbosity=2)
runner.run(suite)
os.chdir(original_cwd)

return failed


def run_test_suite_with_junit_output():
try:
import unittest2 as unittest
except ImportError:
import unittest
import xmlrunner
original_cwd = os.path.abspath(os.getcwd())
os.chdir('tests')
suite = unittest.defaultTestLoader.discover('.')
xmlrunner.XMLTestRunner(output='../test-reports').run(suite)
os.chdir(original_cwd)


class CoverageCommand(Command):
"""setup.py command to run code coverage of the test suite."""
description = "Create an HTML coverage report from running the full test suite."
user_options = []

def initialize_options(self):
pass

def finalize_options(self):
pass

def run(self):
try:
import coverage
except ImportError:
print("Could not import coverage. Please install it and try again.")
exit(1)
cov = coverage.coverage(source=['splunklib'])
cov.start()
run_test_suite()
cov.stop()
cov.html_report(directory='coverage_report')


class TestCommand(Command):
"""setup.py command to run the whole test suite."""
description = "Run test full test suite."
user_options = []

def initialize_options(self):
pass

def finalize_options(self):
pass

def run(self):
failed = run_test_suite()
if failed:
sys.exit(1)


class JunitXmlTestCommand(Command):
"""setup.py command to run the whole test suite."""
description = "Run test full test suite with JUnit-formatted output."
user_options = []

def initialize_options(self):
pass

def finalize_options(self):
pass

def run(self):
run_test_suite_with_junit_output()


setup(
author="Splunk, Inc.",

author_email="[email protected]",

cmdclass={'coverage': CoverageCommand,
'test': TestCommand,
'testjunit': JunitXmlTestCommand},

description="The Splunk Software Development Kit for Python.",

license="http://www.apache.org/licenses/LICENSE-2.0",
Expand Down
2 changes: 1 addition & 1 deletion splunklib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ def setup_logging(level, log_format=DEFAULT_LOG_FORMAT, date_format=DEFAULT_DATE
datefmt=date_format)


__version_info__ = (2, 0, 2)
__version_info__ = (2, 1, 0)
__version__ = ".".join(map(str, __version_info__))
9 changes: 8 additions & 1 deletion splunklib/binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ class Context:
:type scheme: "https" or "http"
:param verify: Enable (True) or disable (False) SSL verification for https connections.
:type verify: ``Boolean``
:param self_signed_certificate: Specifies if self signed certificate is used
:type self_signed_certificate: ``Boolean``
:param sharing: The sharing mode for the namespace (the default is "user").
:type sharing: "global", "system", "app", or "user"
:param owner: The owner context of the namespace (optional, the default is "None").
Expand Down Expand Up @@ -526,6 +528,7 @@ def __init__(self, handler=None, **kwargs):
self.bearerToken = kwargs.get("splunkToken", "")
self.autologin = kwargs.get("autologin", False)
self.additional_headers = kwargs.get("headers", [])
self._self_signed_certificate = kwargs.get("self_signed_certificate", True)

# Store any cookies in the self.http._cookies dict
if "cookie" in kwargs and kwargs['cookie'] not in [None, _NoAuthenticationToken]:
Expand Down Expand Up @@ -604,7 +607,11 @@ def connect(self):
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if self.scheme == "https":
sock = ssl.wrap_socket(sock)
context = ssl.create_default_context()
context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
context.check_hostname = not self._self_signed_certificate
context.verify_mode = ssl.CERT_NONE if self._self_signed_certificate else ssl.CERT_REQUIRED
sock = context.wrap_socket(sock, server_hostname=self.host)
sock.connect((socket.gethostbyname(self.host), self.port))
return sock

Expand Down
96 changes: 95 additions & 1 deletion splunklib/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
PATH_JOBS = "search/jobs/"
PATH_JOBS_V2 = "search/v2/jobs/"
PATH_LOGGER = "/services/server/logger/"
PATH_MACROS = "configs/conf-macros/"
PATH_MESSAGES = "messages/"
PATH_MODULAR_INPUTS = "data/modular-inputs"
PATH_ROLES = "authorization/roles/"
Expand Down Expand Up @@ -667,6 +668,15 @@ def saved_searches(self):
"""
return SavedSearches(self)

@property
def macros(self):
"""Returns the collection of macros.

:return: A :class:`Macros` collection of :class:`Macro`
entities.
"""
return Macros(self)

@property
def settings(self):
"""Returns the configuration settings for this instance of Splunk.
Expand Down Expand Up @@ -3440,6 +3450,90 @@ def create(self, name, search, **kwargs):
return Collection.create(self, name, search=search, **kwargs)


class Macro(Entity):
"""This class represents a search macro."""
def __init__(self, service, path, **kwargs):
Entity.__init__(self, service, path, **kwargs)

@property
def args(self):
"""Returns the macro arguments.
:return: The macro arguments.
:rtype: ``string``
"""
return self._state.content.get('args', '')

@property
def definition(self):
"""Returns the macro definition.
:return: The macro definition.
:rtype: ``string``
"""
return self._state.content.get('definition', '')

@property
def errormsg(self):
"""Returns the validation error message for the macro.
:return: The validation error message for the macro.
:rtype: ``string``
"""
return self._state.content.get('errormsg', '')

@property
def iseval(self):
"""Returns the eval-based definition status of the macro.
:return: The iseval value for the macro.
:rtype: ``string``
"""
return self._state.content.get('iseval', '0')

def update(self, definition=None, **kwargs):
"""Updates the server with any changes you've made to the current macro
along with any additional arguments you specify.
:param `definition`: The macro definition (optional).
:type definition: ``string``
:param `kwargs`: Additional arguments (optional). Available parameters are:
'disabled', 'iseval', 'validation', and 'errormsg'.
:type kwargs: ``dict``
:return: The :class:`Macro`.
"""
# Updates to a macro *require* that the definition be
# passed, so we pass the current definition if a value wasn't
# provided by the caller.
if definition is None: definition = self.content.definition
Entity.update(self, definition=definition, **kwargs)
return self

@property
def validation(self):
"""Returns the validation expression for the macro.
:return: The validation expression for the macro.
:rtype: ``string``
"""
return self._state.content.get('validation', '')


class Macros(Collection):
"""This class represents a collection of macros. Retrieve this
collection using :meth:`Service.macros`."""
def __init__(self, service):
Collection.__init__(
self, service, PATH_MACROS, item=Macro)

def create(self, name, definition, **kwargs):
""" Creates a macro.
:param name: The name for the macro.
:type name: ``string``
:param definition: The macro definition.
:type definition: ``string``
:param kwargs: Additional arguments (optional). Available parameters are:
'disabled', 'iseval', 'validation', and 'errormsg'.
:type kwargs: ``dict``
:return: The :class:`Macros` collection.
"""
return Collection.create(self, name, definition=definition, **kwargs)


class Settings(Entity):
"""This class represents configuration settings for a Splunk service.
Retrieve this collection using :meth:`Service.settings`."""
Expand Down Expand Up @@ -3905,4 +3999,4 @@ def batch_save(self, *documents):
data = json.dumps(documents)

return json.loads(
self._post('batch_save', headers=KVStoreCollectionData.JSON_HEADER, body=data).body.read().decode('utf-8'))
self._post('batch_save', headers=KVStoreCollectionData.JSON_HEADER, body=data).body.read().decode('utf-8'))
20 changes: 20 additions & 0 deletions splunklib/modularinput/event_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# under the License.

import sys
import traceback

from splunklib.utils import ensure_str
from .event import ET
Expand Down Expand Up @@ -66,6 +67,25 @@ def log(self, severity, message):
self._err.write(f"{severity} {message}\n")
self._err.flush()

def log_exception(self, message, exception=None, severity=None):
"""Logs messages about the exception thrown by this modular input to Splunk.
These messages will show up in Splunk's internal logs.

:param message: ``string``, message to log.
:param exception: ``Exception``, exception thrown by this modular input; if none, sys.exc_info() is used
:param severity: ``string``, severity of message, see severities defined as class constants. Default severity: ERROR
"""
if exception is not None:
tb_str = traceback.format_exception(type(exception), exception, exception.__traceback__)
else:
tb_str = traceback.format_exc()

if severity is None:
severity = EventWriter.ERROR

self._err.write(("%s %s - %s" % (severity, message, tb_str)).replace("\n", " "))
self._err.flush()

def write_xml_document(self, document):
"""Writes a string representation of an
``ElementTree`` object to the output stream.
Expand Down
Loading
Loading