diff --git a/README.md b/README.md index 6a2b8a43b..51c7086d9 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ class GeneratorTest(GeneratingCommand): #### Accessing instance metadata in scripts -- The `service` metadata object is created from the `splunkd` URI and session key passed to the command invocation on the modular input stream respectively, and is available as soon as the `.stream_events()` method is called. +- The `service` metadata object is created from the `splunkd` URI and session key passed to the command invocation on the modular input stream respectively, and is available as soon as the `.stream_events()` or `.validate_input()` method is called. ```python from splunklib.modularinput import Script diff --git a/splunklib/modularinput/script.py b/splunklib/modularinput/script.py index 89a08edc2..2192eb721 100644 --- a/splunklib/modularinput/script.py +++ b/splunklib/modularinput/script.py @@ -35,7 +35,8 @@ class Script(metaclass=ABCMeta): """ def __init__(self): - self._input_definition = None + self._server_uri = None + self._session_key = None self._service = None def run(self, args): @@ -63,8 +64,10 @@ def run_script(self, args, event_writer, input_stream): # This script is running as an input. Input definitions will be # passed on stdin as XML, and the script will write events on # stdout and log entries on stderr. - self._input_definition = InputDefinition.parse(input_stream) - self.stream_events(self._input_definition, event_writer) + input_definition = InputDefinition.parse(input_stream) + self._server_uri = input_definition.metadata["server_uri"] + self._session_key = input_definition.metadata["session_key"] + self.stream_events(input_definition, event_writer) event_writer.close() return 0 @@ -83,6 +86,8 @@ def run_script(self, args, event_writer, input_stream): if args[1].lower() == "--validate-arguments": validation_definition = ValidationDefinition.parse(input_stream) + self._server_uri = validation_definition.metadata["server_uri"] + self._session_key = validation_definition.metadata["session_key"] try: self.validate_input(validation_definition) return 0 @@ -119,19 +124,16 @@ def service(self): if self._service is not None: return self._service - if self._input_definition is None: + if self._server_uri is None and self._session_key is None: return None - splunkd_uri = self._input_definition.metadata["server_uri"] - session_key = self._input_definition.metadata["session_key"] - - splunkd = urlsplit(splunkd_uri, allow_fragments=False) + splunkd = urlsplit(self._server_uri, allow_fragments=False) self._service = Service( scheme=splunkd.scheme, host=splunkd.hostname, port=splunkd.port, - token=session_key, + token=self._session_key, ) return self._service diff --git a/tests/system/test_apps/modularinput_app/bin/modularinput.py b/tests/system/test_apps/modularinput_app/bin/modularinput.py index ee525faf2..0b12660d4 100755 --- a/tests/system/test_apps/modularinput_app/bin/modularinput.py +++ b/tests/system/test_apps/modularinput_app/bin/modularinput.py @@ -22,7 +22,7 @@ class ModularInput(Script): """ - This app provides an example of a modular input that + This app provides an example of a modular input that can be used in Settings => Data inputs => Local inputs => modularinput """ @@ -44,18 +44,29 @@ def get_scheme(self): return scheme def validate_input(self, definition): + self.check_service_access() + url = definition.parameters[self.endpoint_arg] parsed = parse.urlparse(url) if parsed.scheme != "https": raise ValueError(f"non-supported scheme {parsed.scheme}") def stream_events(self, inputs, ew): + self.check_service_access() + for input_name, input_item in list(inputs.inputs.items()): event = Event() event.stanza = input_name event.data = "example message" ew.write_event(event) + def check_service_access(self): + # Both validate_input and stream_events should have access to the Splunk + # instance that executed the modular input. + if self.service is None: + raise Exception("self.Service == None") + self.service.info # make sure that we are properly authenticated and self.service works + if __name__ == "__main__": sys.exit(ModularInput().run(sys.argv)) diff --git a/tests/unit/modularinput/test_script.py b/tests/unit/modularinput/test_script.py index 9469048a8..06ae4a5ae 100644 --- a/tests/unit/modularinput/test_script.py +++ b/tests/unit/modularinput/test_script.py @@ -258,7 +258,7 @@ def stream_events(self, inputs, ew): "ERROR Some error - " "Traceback (most recent call last): " ' File "...", line 123, in run_script ' - " self.stream_events(self._input_definition, event_writer) " + " self.stream_events(input_definition, event_writer) " ' File "...", line 123, in stream_events ' ' raise RuntimeError("Some error") ' "RuntimeError: Some error "