diff --git a/CHANGELOG.md b/CHANGELOG.md index e36b326c..1ceda287 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Splunk Enterprise SDK for Python Changelog +## Version 1.7.2 + +### Minor changes +* [#482](https://github.com/splunk/splunk-sdk-python/pull/482) Special handling related to the semantic versioning of specific Search APIs functional in Splunk Enterprise 9.0.2 and (Splunk Cloud 9.0.2209). These SDK changes will enable seamless transition between the APIs based on the version of the Splunk Enterprise in use + ## Version 1.7.1 ### Bug fixes diff --git a/README.md b/README.md index eb7ad8bd..29b75704 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # The Splunk Enterprise Software Development Kit for Python -#### Version 1.7.1 +#### Version 1.7.2 The Splunk Enterprise Software Development Kit (SDK) for Python contains library code designed to enable developers to build applications using the Splunk platform. diff --git a/splunklib/__init__.py b/splunklib/__init__.py index b370003e..774cb757 100644 --- a/splunklib/__init__.py +++ b/splunklib/__init__.py @@ -31,5 +31,5 @@ def setup_logging(level, log_format=DEFAULT_LOG_FORMAT, date_format=DEFAULT_DATE format=log_format, datefmt=date_format) -__version_info__ = (1, 7, 1) +__version_info__ = (1, 7, 2) __version__ = ".".join(map(str, __version_info__)) diff --git a/splunklib/binding.py b/splunklib/binding.py index 7806bee4..17b5783c 100644 --- a/splunklib/binding.py +++ b/splunklib/binding.py @@ -1434,7 +1434,7 @@ def request(url, message, **kwargs): head = { "Content-Length": str(len(body)), "Host": host, - "User-Agent": "splunk-sdk-python/1.7.1", + "User-Agent": "splunk-sdk-python/1.7.2", "Accept": "*/*", "Connection": "Close", } # defaults diff --git a/splunklib/client.py b/splunklib/client.py index 85c559d0..cde39e95 100644 --- a/splunklib/client.py +++ b/splunklib/client.py @@ -421,6 +421,7 @@ def __init__(self, **kwargs): super(Service, self).__init__(**kwargs) self._splunk_version = None self._kvstore_owner = None + self._instance_type = None @property def apps(self): @@ -572,7 +573,7 @@ def parse(self, query, **kwargs): :type kwargs: ``dict`` :return: A semantic map of the parsed search query. """ - if self.splunk_version >= (9,): + if not self.disable_v2_api: return self.post("search/v2/parser", q=query, **kwargs) return self.get("search/parser", q=query, **kwargs) @@ -695,6 +696,22 @@ def splunk_version(self): self._splunk_version = tuple([int(p) for p in self.info['version'].split('.')]) return self._splunk_version + @property + def splunk_instance(self): + if self._instance_type is None : + splunk_info = self.info; + if hasattr(splunk_info, 'instance_type') : + self._instance_type = splunk_info['instance_type'] + else: + self._instance_type = '' + return self._instance_type + + @property + def disable_v2_api(self): + if self.splunk_instance.lower() == 'cloud': + return self.splunk_version < (9,0,2209) + return self.splunk_version < (9,0,2) + @property def kvstore_owner(self): """Returns the KVStore owner for this instance of Splunk. @@ -2722,7 +2739,7 @@ def __init__(self, service, sid, **kwargs): # Default to v2 in Splunk Version 9+ path = "{path}{sid}" # Formatting path based on the Splunk Version - if service.splunk_version < (9,): + if service.disable_v2_api: path = path.format(path=PATH_JOBS, sid=sid) else: path = path.format(path=PATH_JOBS_V2, sid=sid) @@ -2782,7 +2799,7 @@ def events(self, **kwargs): kwargs['segmentation'] = kwargs.get('segmentation', 'none') # Search API v1(GET) and v2(POST) - if self.service.splunk_version < (9,): + if self.service.disable_v2_api: return self.get("events", **kwargs).body return self.post("events", **kwargs).body @@ -2874,7 +2891,7 @@ def results(self, **query_params): query_params['segmentation'] = query_params.get('segmentation', 'none') # Search API v1(GET) and v2(POST) - if self.service.splunk_version < (9,): + if self.service.disable_v2_api: return self.get("results", **query_params).body return self.post("results", **query_params).body @@ -2919,7 +2936,7 @@ def preview(self, **query_params): query_params['segmentation'] = query_params.get('segmentation', 'none') # Search API v1(GET) and v2(POST) - if self.service.splunk_version < (9,): + if self.service.disable_v2_api: return self.get("results_preview", **query_params).body return self.post("results_preview", **query_params).body @@ -3011,7 +3028,7 @@ class Jobs(Collection): collection using :meth:`Service.jobs`.""" def __init__(self, service): # Splunk 9 introduces the v2 endpoint - if service.splunk_version >= (9,): + if not service.disable_v2_api: path = PATH_JOBS_V2 else: path = PATH_JOBS diff --git a/tests/test_job.py b/tests/test_job.py index e514c83c..18f3189a 100755 --- a/tests/test_job.py +++ b/tests/test_job.py @@ -399,10 +399,10 @@ def test_v1_job_fallback(self): n_events = len([x for x in events_r if isinstance(x, dict)]) n_preview = len([x for x in preview_r if isinstance(x, dict)]) n_results = len([x for x in results_r if isinstance(x, dict)]) - - # Fallback test for Splunk Version 9+ - if self.service.splunk_version[0] >= 9: - self.assertGreaterEqual(9, self.service.splunk_version[0]) + + # Fallback test for Splunk Version 9.0.2+ + if not self.service.disable_v2_api: + self.assertTrue(client.PATH_JOBS_V2 in self.job.path) self.assertEqual(n_events, n_preview, n_results) diff --git a/tests/test_service.py b/tests/test_service.py index e3ffef68..34afef2c 100755 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -102,11 +102,6 @@ def test_parse(self): # objectified form of the results, but for now there's # nothing to test but a good response code. response = self.service.parse('search * abc="def" | dedup abc') - - # Splunk Version 9+ using API v2: search/v2/parser - if self.service.splunk_version[0] >= 9: - self.assertGreaterEqual(9, self.service.splunk_version[0]) - self.assertEqual(response.status, 200) def test_parse_fail(self):