From 5b6aa1c34c2c293da2593d49fd841eb52cede155 Mon Sep 17 00:00:00 2001 From: srv-rr-github-token <94607705+srv-rr-github-token@users.noreply.github.com> Date: Wed, 26 Jun 2024 09:51:11 +0000 Subject: [PATCH 01/10] chore(release): 5.1.0 # [5.1.0](https://github.com/splunk/addonfactory-solutions-library-python/compare/v5.0.0...v5.1.0) (2024-06-26) ### Features * add bulletin_rest_client module to manage global Splunk messages ([#369](https://github.com/splunk/addonfactory-solutions-library-python/issues/369)) ([829d1cb](https://github.com/splunk/addonfactory-solutions-library-python/commit/829d1cb224c4547cf1855ffe3b931e1012817b9e)) * **mtls:** implement of mutual TLS communication for fetching server info ([#372](https://github.com/splunk/addonfactory-solutions-library-python/issues/372)) ([278505a](https://github.com/splunk/addonfactory-solutions-library-python/commit/278505aff3f9ede199bc9c57d72f2f2886bb5850)) [ci skip] --- pyproject.toml | 2 +- solnlib/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2d61b050..1e98b031 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ [tool.poetry] name = "solnlib" -version = "5.1.0-beta.2" +version = "5.1.0" description = "The Splunk Software Development Kit for Splunk Solutions" authors = ["Splunk "] license = "Apache-2.0" diff --git a/solnlib/__init__.py b/solnlib/__init__.py index 32a94f26..0fa8a8e6 100644 --- a/solnlib/__init__.py +++ b/solnlib/__init__.py @@ -56,4 +56,4 @@ "utils", ] -__version__ = "5.1.0-beta.2" +__version__ = "5.1.0" From 364146a8abbb3df3dca1d7a2343e6f657c0c6b0e Mon Sep 17 00:00:00 2001 From: sgoral Date: Wed, 26 Jun 2024 12:08:27 +0200 Subject: [PATCH 02/10] chore: remove skip ci from releaserc --- .releaserc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.releaserc b/.releaserc index e936f184..dce467f0 100644 --- a/.releaserc +++ b/.releaserc @@ -55,7 +55,7 @@ "@semantic-release/git", { "assets": ["NOTICE", "pyproject.toml", "solnlib/__init__.py"], - "message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes} [ci skip]", + "message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}", }, ], ["@semantic-release/github", { "assets": ["NOTICE", "pyproject.toml"] }], From e204a3d9f47302229af56777204172520fd91e80 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:46:05 +0200 Subject: [PATCH 03/10] chore(deps): lock file maintenance (#377) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/splunk/addonfactory-solutions-library-python). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- poetry.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 06025615..fa163dcf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -881,12 +881,12 @@ files = [ [[package]] name = "splunk-sdk" -version = "2.0.1" +version = "2.0.2" description = "The Splunk Software Development Kit for Python." optional = false python-versions = "*" files = [ - {file = "splunk-sdk-2.0.1.tar.gz", hash = "sha256:a1cc9b24e0c9c79ef8e2845fedcca066638219eef0018163f97795dbfa367c67"}, + {file = "splunk-sdk-2.0.2.tar.gz", hash = "sha256:d5ccf6e1b96e493b1399e071ef10f8337e0a39ac2b2acc73fdd375b87b4104cb"}, ] [package.dependencies] From 89cb2b02b760d23f43b384435ef23230dbd20d2d Mon Sep 17 00:00:00 2001 From: hetangmodi-crest Date: Tue, 2 Jul 2024 18:25:54 +0530 Subject: [PATCH 04/10] fix(server_info): handle splunk not present imports --- solnlib/server_info.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/solnlib/server_info.py b/solnlib/server_info.py index 01643067..c61b5e67 100644 --- a/solnlib/server_info.py +++ b/solnlib/server_info.py @@ -20,7 +20,17 @@ import json from typing import Any, Dict, Optional -from splunk.rest import getWebCertFile, getWebKeyFile +try: + from splunk.rest import getWebCertFile, getWebKeyFile +except (ModuleNotFoundError, ImportError): + + def getWebCertFile(): + return None + + def getWebKeyFile(): + return None + + from splunklib import binding from solnlib import splunk_rest_client as rest_client from solnlib import utils From 687b82f1e12c53cc7ccebd28f47536fe22351f04 Mon Sep 17 00:00:00 2001 From: hetangmodi-crest Date: Fri, 5 Jul 2024 14:58:49 +0530 Subject: [PATCH 05/10] test(unit): add test when splunk isn't imported --- tests/unit/conftest.py | 6 ------ tests/unit/test_server_info.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) delete mode 100644 tests/unit/conftest.py diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py deleted file mode 100644 index 1dbefb3d..00000000 --- a/tests/unit/conftest.py +++ /dev/null @@ -1,6 +0,0 @@ -import sys -from unittest.mock import MagicMock - -# mock modules of 'splunk' library added 'splunk_rest_client' -sys.modules["splunk"] = MagicMock() -sys.modules["splunk.rest"] = MagicMock() diff --git a/tests/unit/test_server_info.py b/tests/unit/test_server_info.py index f7f6e5a6..41fd0f98 100644 --- a/tests/unit/test_server_info.py +++ b/tests/unit/test_server_info.py @@ -161,3 +161,32 @@ def test_server_info_object_with_key_file( assert kwargs.get("cert_file") is None assert kwargs.get("key_file") is None assert kwargs.get("verify") is None + + @patch("solnlib.server_info.os.environ", autospec=True, return_value="$SPLUNK_HOME") + @patch( + "solnlib.server_info.get_splunkd_access_info", + autospec=True, + return_value=("https", "127.0.0.1", "8089"), + ) + @patch("solnlib.server_info.rest_client", autospec=True) + def test_server_info_object_with_no_splunk_import( + self, + mock_rest_client, + mock_splunkd, + mock_os_env, + ): + mock_rest_client.SplunkRestClient = MagicMock() + + # we want to raise 'ModuleNotFoundError' when importing the required functions + with patch.dict("sys.modules", {"splunk": ModuleNotFoundError}): + server_info.ServerInfo(common.SESSION_KEY) + + for call_arg in mock_rest_client.SplunkRestClient.call_args_list: + _, kwargs = call_arg + assert ( + kwargs.get("cert_file") is None + ) # comes from the empty function in except + assert ( + kwargs.get("key_file") is None + ) # comes from the empty function in except + assert kwargs.get("verify") is None From ffd66a92ce32198ce9bae25d4a049dad16db9e70 Mon Sep 17 00:00:00 2001 From: srv-rr-github-token <94607705+srv-rr-github-token@users.noreply.github.com> Date: Fri, 5 Jul 2024 10:25:41 +0000 Subject: [PATCH 06/10] chore(release): 5.1.1 ## [5.1.1](https://github.com/splunk/addonfactory-solutions-library-python/compare/v5.1.0...v5.1.1) (2024-07-05) ### Bug Fixes * **server_info:** handle splunk not present imports ([89cb2b0](https://github.com/splunk/addonfactory-solutions-library-python/commit/89cb2b02b760d23f43b384435ef23230dbd20d2d)) * **server_info:** handle splunk not present imports ([#378](https://github.com/splunk/addonfactory-solutions-library-python/issues/378)) ([46bc899](https://github.com/splunk/addonfactory-solutions-library-python/commit/46bc899712ef0a40b2a4463c94ca7363a13ce00b)) --- pyproject.toml | 2 +- solnlib/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1e98b031..819db470 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ [tool.poetry] name = "solnlib" -version = "5.1.0" +version = "5.1.1" description = "The Splunk Software Development Kit for Splunk Solutions" authors = ["Splunk "] license = "Apache-2.0" diff --git a/solnlib/__init__.py b/solnlib/__init__.py index 0fa8a8e6..cf68aa9c 100644 --- a/solnlib/__init__.py +++ b/solnlib/__init__.py @@ -56,4 +56,4 @@ "utils", ] -__version__ = "5.1.0" +__version__ = "5.1.1" From 5c0daafa862e96a9761f8c4bfaf3cfbad103ec02 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 6 Jul 2024 09:46:56 +0200 Subject: [PATCH 07/10] chore(deps): lock file maintenance (#379) --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index fa163dcf..b628d61d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -30,13 +30,13 @@ files = [ [[package]] name = "certifi" -version = "2024.6.2" +version = "2024.7.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, - {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, ] [[package]] From bdc78c82becf40af9b4183222ad4be16969f0b9b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 13 Jul 2024 12:17:16 +0200 Subject: [PATCH 08/10] chore(deps): lock file maintenance (#381) --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index b628d61d..d83a13dd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -191,13 +191,13 @@ packaging = "*" [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] From 4e961b2cf17b569f78b875f3273210dadd599db3 Mon Sep 17 00:00:00 2001 From: Florian Zug <85840077+zugf@users.noreply.github.com> Date: Mon, 22 Jul 2024 10:34:21 +0200 Subject: [PATCH 09/10] fix: standalone HEC Event writer (#380) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When create_from_token() is invoked, it triggers the HECEventWriter constructor with scheme, host, and port set to None. This leads to a get_splunkd_access_info() call, which throws an exception if the HEC URI doesn’t reference the local machine. As this call is unnecessary in such cases, its invocation has been relocated within the if-statement --- solnlib/modular_input/event_writer.py | 5 +- tests/unit/test_modular_input_event_writer.py | 176 +++++++++++------- 2 files changed, 114 insertions(+), 67 deletions(-) diff --git a/solnlib/modular_input/event_writer.py b/solnlib/modular_input/event_writer.py index 3d14a4c3..b6653784 100644 --- a/solnlib/modular_input/event_writer.py +++ b/solnlib/modular_input/event_writer.py @@ -229,12 +229,11 @@ def __init__( else: self.logger = logging - if not all([scheme, host, port]): - scheme, host, port = get_splunkd_access_info() - if hec_uri and hec_token: scheme, host, hec_port = utils.extract_http_scheme_host_port(hec_uri) else: + if not all([scheme, host, port]): + scheme, host, port = get_splunkd_access_info() hec_port, hec_token = self._get_hec_config( hec_input_name, session_key, scheme, host, port, **context ) diff --git a/tests/unit/test_modular_input_event_writer.py b/tests/unit/test_modular_input_event_writer.py index 5eddbae8..dd9902e7 100644 --- a/tests/unit/test_modular_input_event_writer.py +++ b/tests/unit/test_modular_input_event_writer.py @@ -18,6 +18,7 @@ import sys import common +import pytest from splunklib import binding from solnlib.modular_input import ClassicEventWriter, HECEventWriter @@ -85,7 +86,54 @@ def flush(self): assert mock_stdout.write_count == 1 -def test_hec_event_writer(monkeypatch): +def create_hec_event_writer__create_from_input(hec=False): + return HECEventWriter.create_from_input( + "HECTestInput", + "https://localhost:8089", + common.SESSION_KEY, + global_settings_schema=hec, + ) + + +def create_hec_event_writer__create_from_token_with_session_key(hec=False): + return HECEventWriter.create_from_token_with_session_key( + "https://localhost:8089", + common.SESSION_KEY, + "https://localhost:8090", + "test_token", + global_settings_schema=hec, + ) + + +def create_hec_event_writer__create_from_token(hec=False): + return HECEventWriter.create_from_token( + "https://localhost:8090", "test_token", global_settings_schema=hec + ) + + +def create_hec_event_writer__create_from_token__external_host(hec=False): + return HECEventWriter.create_from_token( + "https://external:8090", "test_token", global_settings_schema=hec + ) + + +def create_hec_event_writer__constructor(hec=False): + return HECEventWriter( + "HECTestInput", common.SESSION_KEY, global_settings_schema=hec + ) + + +@pytest.mark.parametrize( + "create_hec_event_writer, has_splunk_home", + [ + (create_hec_event_writer__constructor, True), + (create_hec_event_writer__create_from_input, True), + (create_hec_event_writer__create_from_token_with_session_key, True), + (create_hec_event_writer__create_from_token, True), + (create_hec_event_writer__create_from_token__external_host, False), + ], +) +def test_hec_event_writer(monkeypatch, create_hec_event_writer, has_splunk_home): def mock_get(self, path_segment, owner=None, app=None, sharing=None, **query): if path_segment.endswith("/http"): return common.make_response_record( @@ -120,42 +168,46 @@ def mock_get_hec_config( ): return "8088", "87de04d1-0823-11e6-9c94-a45e60e" - common.mock_splunkhome(monkeypatch) + if has_splunk_home: + common.mock_splunkhome(monkeypatch) + else: + # simulate an environment that has no splunk installation + monkeypatch.delenv("SPLUNK_HOME", raising=False) + monkeypatch.delenv("SPLUNK_ETC", raising=False) monkeypatch.setattr(binding.Context, "get", mock_get) monkeypatch.setattr(binding.Context, "post", mock_post) monkeypatch.setattr(HECEventWriter, "_get_hec_config", mock_get_hec_config) - for i in range(4): - ew = create_hec_event_writer(i) - - events = [] - events.append( - ew.create_event( - data="This is a test data1.", - time=1372274622.493, - index="main", - host="localhost", - source="Splunk", - sourcetype="misc", - stanza="test_scheme://test", - unbroken=True, - done=False, - ) + ew = create_hec_event_writer(hec=False) + + events = [] + events.append( + ew.create_event( + data="This is a test data1.", + time=1372274622.493, + index="main", + host="localhost", + source="Splunk", + sourcetype="misc", + stanza="test_scheme://test", + unbroken=True, + done=False, ) - events.append( - ew.create_event( - data="This is a test data2.", - time=1372274622.493, - index="main", - host="localhost", - source="Splunk", - sourcetype="misc", - stanza="test_scheme://test", - unbroken=True, - done=True, - ) + ) + events.append( + ew.create_event( + data="This is a test data2.", + time=1372274622.493, + index="main", + host="localhost", + source="Splunk", + sourcetype="misc", + stanza="test_scheme://test", + unbroken=True, + done=True, ) - ew.write_events(events) + ) + ew.write_events(events) # length of this list will indicate how many times post was called times_post_called = [] @@ -170,7 +222,7 @@ def mock_post_2( # test that there are 2 event batches created for write_event and post is called 2 times # max batch size is 1,000,000. If the max size is exceeded then a new batch is created. assert len(times_post_called) == 0 - ew = create_hec_event_writer(1) + events = [] # each event length will be ~500 characters, 3000 events length will equal ~1,500,000 characters @@ -207,35 +259,31 @@ def mock_post_2( # test that post is called 2 times assert len(times_post_called) == 2 - for i in range(4): - ev = create_hec_event_writer(i) - assert ev._rest_client.scheme == "https" - for i in range(4): - ev = create_hec_event_writer(i, hec=True) - assert ev._rest_client.scheme == "http" - - -def create_hec_event_writer(i, hec=False): - if i == 1: - return HECEventWriter.create_from_input( - "HECTestInput", - "https://localhost:8089", - common.SESSION_KEY, - global_settings_schema=hec, - ) - elif i == 2: - return HECEventWriter.create_from_token_with_session_key( - "https://localhost:8089", - common.SESSION_KEY, - "https://localhost:8090", - "test_token", - global_settings_schema=hec, - ) - elif i == 3: - return HECEventWriter.create_from_token( - "https://localhost:8090", "test_token", global_settings_schema=hec - ) - else: - return HECEventWriter( - "HECTestInput", common.SESSION_KEY, global_settings_schema=hec - ) + +@pytest.mark.parametrize( + "create_hec_event_writer, hec, expected_scheme", + [ + (create_hec_event_writer__constructor, True, "http"), + (create_hec_event_writer__constructor, False, "https"), + (create_hec_event_writer__create_from_input, True, "http"), + (create_hec_event_writer__create_from_input, False, "https"), + (create_hec_event_writer__create_from_token_with_session_key, True, "http"), + (create_hec_event_writer__create_from_token_with_session_key, False, "https"), + (create_hec_event_writer__create_from_token, True, "http"), + (create_hec_event_writer__create_from_token, False, "https"), + ], +) +def test_hec_event_writer_gets_scheme_from_global_settings_if_requested( + monkeypatch, create_hec_event_writer, hec, expected_scheme +): + common.mock_splunkhome(monkeypatch) + + def mock_get_hec_config( + self, hec_input_name, session_key, scheme, host, port, **context + ): + return "8088", "87de04d1-0823-11e6-9c94-a45e60e" + + monkeypatch.setattr(HECEventWriter, "_get_hec_config", mock_get_hec_config) + + ev = create_hec_event_writer(hec) + assert ev._rest_client.scheme == expected_scheme From 0eee07c1a7ee88a1cc07ff6709a4ac9719ce5ab4 Mon Sep 17 00:00:00 2001 From: srv-rr-github-token <94607705+srv-rr-github-token@users.noreply.github.com> Date: Mon, 22 Jul 2024 08:39:12 +0000 Subject: [PATCH 10/10] chore(release): 5.1.2 ## [5.1.2](https://github.com/splunk/addonfactory-solutions-library-python/compare/v5.1.1...v5.1.2) (2024-07-22) ### Bug Fixes * standalone HEC Event writer ([#380](https://github.com/splunk/addonfactory-solutions-library-python/issues/380)) ([4e961b2](https://github.com/splunk/addonfactory-solutions-library-python/commit/4e961b2cf17b569f78b875f3273210dadd599db3)) --- pyproject.toml | 2 +- solnlib/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 819db470..92307a7c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ [tool.poetry] name = "solnlib" -version = "5.1.1" +version = "5.1.2" description = "The Splunk Software Development Kit for Splunk Solutions" authors = ["Splunk "] license = "Apache-2.0" diff --git a/solnlib/__init__.py b/solnlib/__init__.py index cf68aa9c..50ae5eb9 100644 --- a/solnlib/__init__.py +++ b/solnlib/__init__.py @@ -56,4 +56,4 @@ "utils", ] -__version__ = "5.1.1" +__version__ = "5.1.2"