diff --git a/splunklib/client.py b/splunklib/client.py index 038980ea4..4cec5b573 100644 --- a/splunklib/client.py +++ b/splunklib/client.py @@ -64,6 +64,7 @@ import socket from datetime import datetime, timedelta from time import sleep +from typing import Any from urllib import parse try: @@ -124,6 +125,7 @@ def deprecated(message): # pyright: ignore[reportUnknownParameterType] PATH_RECEIVERS_STREAM = "/services/receivers/stream" PATH_RECEIVERS_SIMPLE = "/services/receivers/simple" PATH_STORAGE_PASSWORDS = "storage/passwords" +PATH_LOOKUP_TABLE_FILES = "data/lookup-table-files/" XNAMEF_ATOM = "{http://www.w3.org/2005/Atom}%s" XNAME_ENTRY = XNAMEF_ATOM % "entry" @@ -554,6 +556,14 @@ def loggers(self): """ return Loggers(self) + @property + def lookup_table_files(self): + """Returns the collection of lookup table files. + + :return: A :class:`LookupTableFiles` collection of :class:`LookupTableFile` entities. + """ + return LookupTableFiles(self) + @property def messages(self): """Returns the collection of service messages. @@ -3881,6 +3891,36 @@ def delete(self, name): return Collection.delete(self, name.lower()) +class LookupTableFile(Entity): + """Represents a lookup table CSV file.""" + + def __init__(self, service: "Service", path: str, **kwargs: Any) -> None: + Entity.__init__(self, service, path, **kwargs) + + def download(self) -> Any: + """Downloads the lookup file contents via ``| inputlookup``. + + Runs a oneshot search to retrieve the CSV data for this lookup. + + :return: A streaming response handle with the CSV content. + :rtype: ``InputStream`` + """ + return self.service.jobs.oneshot( # pyright: ignore[reportUnknownVariableType] + f"| inputlookup {self.name}", + output_mode="csv", + ) + + +class LookupTableFiles(Collection): + """Provides access to the collection of lookup table files. + + Retrieve this collection using :meth:`Service.lookup_table_files`. + """ + + def __init__(self, service: "Service") -> None: + Collection.__init__(self, service, PATH_LOOKUP_TABLE_FILES, item=LookupTableFile) + + class Application(Entity): """Represents a locally-installed Splunk app.""" diff --git a/tests/unit/test_lookup_table_file.py b/tests/unit/test_lookup_table_file.py new file mode 100644 index 000000000..533dd186f --- /dev/null +++ b/tests/unit/test_lookup_table_file.py @@ -0,0 +1,34 @@ +# Copyright © 2011-2026 Splunk, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"): you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from splunklib.client import ( + PATH_LOOKUP_TABLE_FILES, + Collection, + Entity, + LookupTableFile, + LookupTableFiles, +) + + +class TestLookupTableFile: + def test_is_entity_subclass(self) -> None: + assert issubclass(LookupTableFile, Entity) + + def test_path_constant(self) -> None: + assert PATH_LOOKUP_TABLE_FILES == "data/lookup-table-files/" + + +class TestLookupTableFiles: + def test_is_collection_subclass(self) -> None: + assert issubclass(LookupTableFiles, Collection)