Skip to content

Commit ade8146

Browse files
chore: merge develop into main (#1853)
2 parents 0cc805f + 0174ce2 commit ade8146

File tree

55 files changed

+518
-412
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+518
-412
lines changed

docs/inputs/helper.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,20 @@ def stream_events(inputs: smi.InputDefinition, event_writer: smi.EventWriter):
5454
```
5555

5656
The two methods' bodies should be filled by the developer.
57+
58+
Alternatively, if you want to have access to the instance of the input script class,
59+
you can also add the `self` parameter to the methods:
60+
61+
```python
62+
from splunklib import modularinput as smi
63+
64+
65+
def validate_input(self, definition: smi.ValidationDefinition):
66+
...
67+
68+
69+
def stream_events(self, inputs: smi.InputDefinition, event_writer: smi.EventWriter):
70+
...
71+
```
72+
73+
Instead of `self`, you can also use any other name, but it must be the first parameter.

splunk_add_on_ucc_framework/commands/build.py

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
#
16+
import ast
1617
import glob
1718
import json
1819
import logging
1920
import os
2021
import shutil
2122
import sys
22-
from typing import Optional, List, Any
23+
from pathlib import Path
24+
from typing import Optional, List, Any, Union
2325
import subprocess
2426
import colorama as c
2527
import fnmatch
@@ -114,7 +116,10 @@ def _modify_and_replace_token_for_oauth_templates(
114116

115117

116118
def _add_modular_input(
117-
ta_name: str, global_config: global_config_lib.GlobalConfig, outputdir: str
119+
ta_name: str,
120+
global_config: global_config_lib.GlobalConfig,
121+
outputdir: str,
122+
gc_path: str,
118123
) -> None:
119124
for service in global_config.inputs:
120125
input_name = service.get("name")
@@ -132,6 +137,39 @@ def _add_modular_input(
132137

133138
input_helper_module = service.get("inputHelperModule")
134139

140+
len_of_args = {"stream_events": 2, "validate_input": 1}
141+
include_self = {"stream_events": False, "validate_input": False}
142+
143+
if input_helper_module:
144+
addon_root_path = os.path.dirname(gc_path)
145+
bin_path = os.path.join(addon_root_path, "package", "bin")
146+
helper_path = os.path.join(bin_path, f"{input_helper_module}.py")
147+
148+
for func in len_of_args:
149+
try:
150+
result = _get_num_of_args(func, helper_path)
151+
152+
if result is None:
153+
logger.error(
154+
f"Cannot find function definition 'def {func}(...)' in module '{input_helper_module}'."
155+
)
156+
exit(1)
157+
158+
if result == len_of_args[func]:
159+
# change nothing
160+
include_self[func] = False
161+
elif result == len_of_args[func] + 1:
162+
# add self to the function
163+
include_self[func] = True
164+
else:
165+
logger.error(
166+
f"Unexpected number of arguments in helper module. "
167+
f"Function '{func}' in '{input_helper_module}' has {result} arguments."
168+
)
169+
except FileNotFoundError:
170+
# If no module, that was specified in globalConfig, default one will be created without 'self'
171+
pass
172+
135173
content = (
136174
utils.get_j2_env()
137175
.get_template(template)
@@ -141,6 +179,8 @@ def _add_modular_input(
141179
description=description,
142180
entity=entity,
143181
input_helper_module=input_helper_module,
182+
stream_events_self=include_self["stream_events"],
183+
validate_input_self=include_self["validate_input"],
144184
)
145185
)
146186
input_file_name = os.path.join(outputdir, ta_name, "bin", input_name + ".py")
@@ -164,6 +204,27 @@ def _add_modular_input(
164204
helper_file.write(content)
165205

166206

207+
def _get_num_of_args(
208+
function_name: str,
209+
module_path: Union[str, Path],
210+
) -> Optional[int]:
211+
module_path = Path(module_path)
212+
213+
if not module_path.is_file():
214+
raise FileNotFoundError(
215+
f"Module path '{module_path}' does not point to a valid file."
216+
)
217+
218+
module_content = ast.parse(module_path.read_text(encoding="utf-8"))
219+
220+
for node in module_content.body:
221+
if isinstance(node, ast.FunctionDef) and node.name == function_name:
222+
# Return the number of arguments defined in the function
223+
return len(node.args.args)
224+
225+
return None
226+
227+
167228
def _get_ignore_list(
168229
addon_name: str, ucc_ignore_path: str, output_directory: str
169230
) -> List[str]:
@@ -231,14 +292,14 @@ def _get_addon_version(addon_version: Optional[str]) -> str:
231292
"repository?). Use `--ta-version` to specify the version you "
232293
"want."
233294
)
234-
exit(1)
295+
sys.exit(1)
235296
except exceptions.CouldNotVersionFromGitException:
236297
logger.error(
237298
"Could not find the proper version from git tags. "
238299
"Check out "
239300
"https://github.com/splunk/addonfactory-ucc-generator/issues/404"
240301
)
241-
exit(1)
302+
sys.exit(1)
242303
return addon_version.strip()
243304

244305

@@ -546,7 +607,7 @@ def generate(
546607
)
547608
if global_config.has_inputs():
548609
logger.info("Generating inputs code")
549-
_add_modular_input(ta_name, global_config, output_directory)
610+
_add_modular_input(ta_name, global_config, output_directory, gc_path)
550611
if global_config.has_alerts():
551612
logger.info("Generating alerts code")
552613
alert_builder.generate_alerts(global_config, ta_name, output_directory)

splunk_add_on_ucc_framework/commands/package.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# limitations under the License.
1515
#
1616
import logging
17+
import sys
1718
import os
1819
import tarfile
1920
from typing import Optional
@@ -47,7 +48,7 @@ def package(path_to_built_addon: str, output_directory: Optional[str] = None) ->
4748
f"Cannot package an add-on without a manifest file. "
4849
f"Please check the --path provided."
4950
)
50-
exit(1)
51+
sys.exit(1)
5152
with open(app_manifest_path) as _f:
5253
app_manifest_content = _f.read()
5354
app_manifest = app_manifest_lib.AppManifest(app_manifest_content)

splunk_add_on_ucc_framework/generators/conf_files/create_account_conf.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from typing import Tuple, List, Dict, Optional
1717

1818
from splunk_add_on_ucc_framework.generators.file_generator import FileGenerator
19+
from splunk_add_on_ucc_framework.global_config import GlobalConfig
1920

2021

2122
class AccountConf(FileGenerator):
@@ -24,13 +25,14 @@ class AccountConf(FileGenerator):
2425
"file for the configuration mentioned in globalConfig"
2526
)
2627

27-
def _set_attributes(self) -> None:
28+
def __init__(
29+
self, global_config: GlobalConfig, input_dir: str, output_dir: str
30+
) -> None:
31+
super().__init__(global_config, input_dir, output_dir)
2832
self.account_fields: List[Tuple[str, List[str]]] = []
29-
if self._global_config.has_configuration():
30-
self.conf_spec_file = (
31-
self._global_config.namespace.lower() + "_account.conf.spec"
32-
)
33-
for account in self._global_config.configs:
33+
if global_config.has_configuration():
34+
self.conf_spec_file = global_config.namespace.lower() + "_account.conf.spec"
35+
for account in global_config.configs:
3436
# If the endpoint is oauth, which is for getting access_token, conf file entries
3537
# should not get created (compatibility to previous versions)
3638
if account["name"] == "oauth":

splunk_add_on_ucc_framework/generators/conf_files/create_alert_actions_conf.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from splunk_add_on_ucc_framework.commands.modular_alert_builder import normalize
2222
from splunk_add_on_ucc_framework.generators.file_generator import FileGenerator
23+
from splunk_add_on_ucc_framework.global_config import GlobalConfig
2324

2425

2526
class AlertActionsConf(FileGenerator):
@@ -28,15 +29,18 @@ class AlertActionsConf(FileGenerator):
2829
"for the custom alert actions defined in globalConfig"
2930
)
3031

31-
def _set_attributes(self) -> None:
32+
def __init__(
33+
self, global_config: GlobalConfig, input_dir: str, output_dir: str
34+
) -> None:
35+
super().__init__(global_config, input_dir, output_dir)
3236
self.conf_file = "alert_actions.conf"
3337
self.conf_spec_file = f"{self.conf_file}.spec"
34-
if self._global_config is None:
38+
if global_config is None:
3539
return
3640

3741
envs = normalize.normalize(
38-
self._global_config.alerts,
39-
self._global_config.namespace,
42+
global_config.alerts,
43+
global_config.namespace,
4044
)
4145
schema_content = envs["schema.content"]
4246
self._alert_settings = schema_content["modular_alerts"]

splunk_add_on_ucc_framework/generators/conf_files/create_app_conf.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,11 @@ class AppConf(FileGenerator):
2727
)
2828

2929
def __init__(self, global_config: GlobalConfig, input_dir: str, output_dir: str):
30+
super().__init__(global_config, input_dir, output_dir)
3031
app_manifest = get_app_manifest(input_dir)
3132
self.description = app_manifest.get_description()
3233
self.title = app_manifest.get_title()
3334
self.author = app_manifest.get_authors()[0]["name"]
34-
super().__init__(global_config, input_dir, output_dir)
35-
36-
def _set_attributes(self) -> None:
3735
self.conf_file = "app.conf"
3836
self.check_for_updates = "true"
3937
self.custom_conf = []
@@ -45,16 +43,14 @@ def _set_attributes(self) -> None:
4543
self.custom_conf.extend(list(self._gc_schema.configs_conf_file_names))
4644
self.custom_conf.extend(list(self._gc_schema.oauth_conf_file_names))
4745

48-
if self._global_config.meta.get("checkForUpdates") is False:
46+
if global_config.meta.get("checkForUpdates") is False:
4947
self.check_for_updates = "false"
50-
if self._global_config.meta.get("supportedThemes") is not None:
51-
self.supported_themes = ", ".join(
52-
self._global_config.meta["supportedThemes"]
53-
)
48+
if global_config.meta.get("supportedThemes") is not None:
49+
self.supported_themes = ", ".join(global_config.meta["supportedThemes"])
5450

55-
self.addon_version = self._global_config.version
51+
self.addon_version = global_config.version
5652
self.is_visible = str(
57-
self._global_config.meta.get("isVisible", self._global_config.has_pages())
53+
global_config.meta.get("isVisible", global_config.has_pages())
5854
).lower()
5955
self.build = str(int(time()))
6056

splunk_add_on_ucc_framework/generators/conf_files/create_commands_conf.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,22 @@
1616
from typing import Dict, List, Optional
1717

1818
from splunk_add_on_ucc_framework.generators.file_generator import FileGenerator
19+
from splunk_add_on_ucc_framework.global_config import GlobalConfig
1920

2021

2122
class CommandsConf(FileGenerator):
2223
__description__ = (
2324
"Generates `commands.conf` for custom commands provided in the globalConfig."
2425
)
2526

26-
def _set_attributes(self) -> None:
27+
def __init__(
28+
self, global_config: GlobalConfig, input_dir: str, output_dir: str
29+
) -> None:
30+
super().__init__(global_config, input_dir, output_dir)
2731
self.conf_file = "commands.conf"
28-
if self._global_config.has_custom_search_commands():
32+
if global_config.has_custom_search_commands():
2933
self.command_names = []
30-
for command in self._global_config.custom_search_commands:
34+
for command in global_config.custom_search_commands:
3135
self.command_names.append(command["commandName"])
3236

3337
def generate(self) -> Optional[List[Dict[str, str]]]:

splunk_add_on_ucc_framework/generators/conf_files/create_eventtypes_conf.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from splunk_add_on_ucc_framework.commands.modular_alert_builder import normalize
1919
from splunk_add_on_ucc_framework.generators.file_generator import FileGenerator
20+
from splunk_add_on_ucc_framework.global_config import GlobalConfig
2021

2122

2223
class EventtypesConf(FileGenerator):
@@ -25,12 +26,15 @@ class EventtypesConf(FileGenerator):
2526
" in Adaptive Response of custom alert action in globalConfig"
2627
)
2728

28-
def _set_attributes(self) -> None:
29+
def __init__(
30+
self, global_config: GlobalConfig, input_dir: str, output_dir: str
31+
) -> None:
32+
super().__init__(global_config, input_dir, output_dir)
2933
self.conf_file = "eventtypes.conf"
3034
self.alert_settings: Dict[str, List[Dict[str, Any]]] = {}
3135
envs = normalize.normalize(
32-
self._global_config.alerts,
33-
self._global_config.namespace,
36+
global_config.alerts,
37+
global_config.namespace,
3438
)
3539
schema_content = envs["schema.content"]
3640
self.alert_settings = schema_content["modular_alerts"]

splunk_add_on_ucc_framework/generators/conf_files/create_inputs_conf.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from typing import Any, Dict, List, Optional
1818

1919
from splunk_add_on_ucc_framework.generators.file_generator import FileGenerator
20+
from splunk_add_on_ucc_framework.global_config import GlobalConfig
2021

2122

2223
class InputsConf(FileGenerator):
@@ -25,13 +26,10 @@ class InputsConf(FileGenerator):
2526
"file for the services mentioned in globalConfig"
2627
)
2728

28-
def _conf_file_name(self, conf_name: str) -> str:
29-
return f"{conf_name}.conf"
30-
31-
def _spec_file_name(self, conf_name: str) -> str:
32-
return f"{self._conf_file_name(conf_name)}.spec"
33-
34-
def _set_attributes(self) -> None:
29+
def __init__(
30+
self, global_config: GlobalConfig, input_dir: str, output_dir: str
31+
) -> None:
32+
super().__init__(global_config, input_dir, output_dir)
3533
self.conf_file = self._conf_file_name("inputs")
3634

3735
# A list of service names from globalConfig that will be in inputs.conf
@@ -47,10 +45,10 @@ def _set_attributes(self) -> None:
4745
# (i.e. dict key is the spec file name)
4846
self.other_spec_files: Dict[str, List[str]] = defaultdict(list)
4947

50-
if not self._global_config.has_inputs():
48+
if not global_config.has_inputs():
5149
return
5250

53-
for service in self._global_config.inputs:
51+
for service in global_config.inputs:
5452
default_values = None
5553

5654
# If the service has a conf property, it will be in a separate spec file
@@ -99,6 +97,12 @@ def _set_attributes(self) -> None:
9997
prop = f"{field_name} = {field_value}".rstrip()
10098
spec_properties.append(prop)
10199

100+
def _conf_file_name(self, conf_name: str) -> str:
101+
return f"{conf_name}.conf"
102+
103+
def _spec_file_name(self, conf_name: str) -> str:
104+
return f"{self._conf_file_name(conf_name)}.spec"
105+
102106
def generate(self) -> Optional[List[Dict[str, str]]]:
103107
conf_files: List[Dict[str, str]] = []
104108
conf = self.generate_conf()

0 commit comments

Comments
 (0)