Skip to content

Commit 6abd3b5

Browse files
committed
refactor: use conf-parser in eventgen.conf parser
1 parent 400e62c commit 6abd3b5

File tree

12 files changed

+237
-290
lines changed

12 files changed

+237
-290
lines changed

pytest_splunk_addon/standard_lib/index_tests/test_generator.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ def generate_tests(self, store_events, app_path, config_path, test_type):
4949
store_sample = sample_generator.get_samples(store_events)
5050
tokenized_events = store_sample.get("tokenized_events")
5151
if not store_sample.get("conf_name") == "psa-data-gen":
52-
LOGGER.warning(
53-
"Index Time tests cannot be executed using eventgen.conf, pytest-splunk-addon-data.conf is required."
52+
msg = (
53+
"Index time tests cannot be executed without "
54+
"pytest-splunk-addon-data.conf"
5455
)
55-
return " Index Time tests cannot be executed using eventgen.conf,\
56-
pytest-splunk-addon-data.conf is required."
56+
LOGGER.warning(msg)
57+
return msg
5758

5859
if test_type == "line_breaker":
5960
LOGGER.info("Generating line breaker test")

pytest_splunk_addon/standard_lib/sample_generation/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from .sample_event import SampleEvent
1717
from .rule import Rule, raise_warning
1818
from .sample_stanza import SampleStanza
19-
from .eventgen_parser import EventgenParser
19+
from .pytest_splunk_addon_data_parser import PytestSplunkAddonDataParser
2020
from .sample_event import SampleEvent
2121
from .sample_generator import SampleGenerator
2222
from .sample_xdist_generator import SampleXdistGenerator

pytest_splunk_addon/standard_lib/sample_generation/eventgen_parser.py renamed to pytest_splunk_addon/standard_lib/sample_generation/pytest_splunk_addon_data_parser.py

Lines changed: 44 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,31 @@
1616
import os
1717
import re
1818
import logging
19-
from splunk_appinspect import App
20-
from .rule import Rule, raise_warning
19+
from .rule import raise_warning
2120
from . import SampleStanza
2221

22+
import addonfactory_splunk_conf_parser_lib as conf_parser
23+
2324
LOGGER = logging.getLogger("pytest-splunk-addon")
24-
import warnings
2525

2626

27-
class EventgenParser:
27+
PSA_DATA_CONFIG_FILE = "pytest-splunk-addon-data.conf"
28+
29+
30+
class PytestSplunkAddonDataParser:
2831
"""
29-
This class represents the entire eventgen.conf file and handles parsing mechanism of eventgen and the rules.
32+
This class parses pytest-splunk-addon-data.conf file.
3033
3134
Args:
32-
addon_path (str): Path to the Splunk App
35+
addon_path: Path to the Splunk App
3336
"""
3437

3538
conf_name = " "
3639

37-
def __init__(self, addon_path, config_path=None):
38-
self._app = App(addon_path, python_analyzer_enable=False)
40+
def __init__(self, addon_path: str, config_path: str):
41+
self._conf_parser = conf_parser.TABConfigParser()
3942
self.config_path = config_path
40-
self._eventgen = None
43+
self._psa_data = None
4144
self.addon_path = addon_path
4245
self.match_stanzas = set()
4346

@@ -71,64 +74,36 @@ def path_to_samples(self):
7174
return os.path.join(self.addon_path, "samples")
7275

7376
@property
74-
def eventgen(self):
75-
try:
76-
relative_path = os.path.relpath(self.config_path, self.addon_path)
77-
if os.path.exists(
78-
os.path.join(self.config_path, "pytest-splunk-addon-data.conf")
79-
):
80-
self._eventgen = self._app.get_config(
81-
"pytest-splunk-addon-data.conf", dir=relative_path
82-
)
83-
self.conf_name = "psa-data-gen"
84-
path = self._app.get_filename(
85-
relative_path, "pytest-splunk-addon-data.conf"
86-
)
87-
88-
elif os.path.exists(os.path.join(self.config_path, "eventgen.conf")):
89-
90-
self._eventgen = self._app.get_config(
91-
"eventgen.conf", dir=relative_path
92-
)
93-
self.conf_name = "eventgen"
94-
path = self._app.get_filename(relative_path, "eventgen.conf")
95-
96-
else:
97-
self._eventgen = self._app.get_config("eventgen.conf")
98-
self.conf_name = "eventgen"
99-
path = self._app.get_filename("default", "eventgen.conf")
100-
LOGGER.info(
101-
"Using Eventgen path: {e}\nUsing Conf file name: {c}".format(
102-
e=path, c=self.conf_name
103-
)
104-
)
105-
return self._eventgen
106-
107-
except OSError:
108-
LOGGER.warning("pytest-splunk-addon-data.conf/eventgen.conf not Found")
109-
raise FileNotFoundError(
110-
"pytest-splunk-addon-data.conf/eventgen.conf not Found"
111-
)
77+
def psa_data(self):
78+
path = os.path.join(self.config_path, PSA_DATA_CONFIG_FILE)
79+
if os.path.exists(path):
80+
self._conf_parser.read(path)
81+
self.conf_name = "psa-data-gen"
82+
self._psa_data = self._conf_parser.item_dict()
83+
return self._psa_data
84+
else:
85+
LOGGER.warning(f"{PSA_DATA_CONFIG_FILE} not found")
86+
raise FileNotFoundError(f"{PSA_DATA_CONFIG_FILE} not found")
11287

11388
def get_sample_stanzas(self):
11489
"""
115-
Converts a stanza in eventgen.conf to an object of SampleStanza.
90+
Converts a stanza in pytest-splunk-addon-data.conf to an object of SampleStanza.
11691
11792
Yields:
11893
SampleStanza Object
11994
"""
120-
eventgen_dict = self.get_eventgen_stanzas()
95+
_psa_data = self.get_psa_data_stanzas()
12196
self.check_samples()
122-
for sample_name, stanza_params in sorted(eventgen_dict.items()):
97+
for sample_name, stanza_params in sorted(_psa_data.items()):
12398
sample_path = os.path.join(self.path_to_samples, sample_name)
12499
yield SampleStanza(
125100
sample_path,
126101
stanza_params,
127102
)
128103

129-
def get_eventgen_stanzas(self):
104+
def get_psa_data_stanzas(self):
130105
"""
131-
Parses the eventgen.conf file and converts it into a dictionary.
106+
Parses the pytest-splunk-addon-data.conf file and converts it into a dictionary.
132107
133108
Format::
134109
@@ -149,44 +124,39 @@ def get_eventgen_stanzas(self):
149124
}
150125
151126
Return:
152-
Dictionary representing eventgen.conf in the above format.
127+
Dictionary representing pytest-splunk-addon-data.conf in the above format.
153128
"""
154-
eventgen_dict = {}
129+
psa_data_dict = {}
155130
if os.path.exists(self.path_to_samples):
156131
for sample_file in os.listdir(self.path_to_samples):
157-
for stanza in sorted(self.eventgen.sects):
132+
for stanza, fields in sorted(self.psa_data.items()):
158133
stanza_match_obj = re.search(stanza, sample_file)
159134
if stanza_match_obj and stanza_match_obj.group(0) == sample_file:
160135
self.match_stanzas.add(stanza)
161-
eventgen_sections = self.eventgen.sects[stanza]
162-
eventgen_dict.setdefault((sample_file), {"tokens": {}})
163-
for stanza_param in eventgen_sections.options:
164-
eventgen_property = eventgen_sections.options[stanza_param]
165-
if eventgen_property.name.startswith("token"):
166-
_, token_id, token_param = eventgen_property.name.split(
167-
"."
168-
)
169-
token_key = "{}_{}".format(stanza, token_id)
136+
psa_data_dict.setdefault(sample_file, {"tokens": {}})
137+
for key, value in fields.items():
138+
if key.startswith("token"):
139+
_, token_id, token_param = key.split(".")
140+
token_key = f"{stanza}_{token_id}"
170141
if (
171142
not token_key
172-
in eventgen_dict[sample_file]["tokens"].keys()
143+
in psa_data_dict[sample_file]["tokens"].keys()
173144
):
174-
eventgen_dict[sample_file]["tokens"][token_key] = {}
175-
eventgen_dict[sample_file]["tokens"][token_key][
145+
psa_data_dict[sample_file]["tokens"][token_key] = {}
146+
psa_data_dict[sample_file]["tokens"][token_key][
176147
token_param
177-
] = eventgen_property.value
148+
] = value
178149
else:
179-
eventgen_dict[sample_file][
180-
eventgen_property.name
181-
] = eventgen_property.value
182-
return eventgen_dict
150+
psa_data_dict[sample_file][key] = value
151+
return psa_data_dict
183152

184153
def check_samples(self):
185154
"""
186-
Gives a user warning when sample file is not found for the stanza peresent in the configuration file.
155+
Gives a user warning when sample file is not found for the stanza
156+
present in the configuration file.
187157
"""
188158
if os.path.exists(self.path_to_samples):
189-
for stanza in self.eventgen.sects:
159+
for stanza in self.psa_data.keys():
190160
if stanza not in self.match_stanzas:
191161
raise_warning("No sample file found for stanza : {}".format(stanza))
192162
LOGGER.info("Sample file found for stanza : {}".format(stanza))

pytest_splunk_addon/standard_lib/sample_generation/sample_generator.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
#
16-
import time
17-
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
16+
from concurrent.futures import ThreadPoolExecutor
1817

19-
from . import EventgenParser
18+
from . import PytestSplunkAddonDataParser
2019
from . import SampleStanza
2120
from itertools import cycle
2221

@@ -47,14 +46,13 @@ def get_samples(self):
4746
Generate SampleEvent object
4847
"""
4948
if not SampleGenerator.sample_stanzas:
50-
eventgen_parser = EventgenParser(
49+
eventgen_parser = PytestSplunkAddonDataParser(
5150
self.addon_path, config_path=self.config_path
5251
)
5352
sample_stanzas = list(eventgen_parser.get_sample_stanzas())
5453
SampleGenerator.conf_name = eventgen_parser.conf_name
5554
with ThreadPoolExecutor(min(20, max(len(sample_stanzas), 1))) as t:
5655
t.map(SampleStanza.get_raw_events, sample_stanzas)
57-
# with ProcessPoolExecutor(self.process_count) as p:
5856
_ = list(
5957
map(
6058
SampleStanza.tokenize,

tests/unit/tests_standard_lib/test_index_tests/test_test_generator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def test_generate_tests_without_conf_file(mock_object, caplog):
2626
)
2727
)
2828
assert caplog.messages == [
29-
"Index Time tests cannot be executed using eventgen.conf, pytest-splunk-addon-data.conf is required."
29+
"Index time tests cannot be executed without pytest-splunk-addon-data.conf"
3030
]
3131

3232

tests/unit/tests_standard_lib/test_utilities/test_create_new_eventgen.py

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import pytest
22
from unittest.mock import MagicMock, patch, PropertyMock, call
3-
from collections import namedtuple
43
from pytest_splunk_addon.standard_lib.utilities.create_new_eventgen import (
54
UpdateEventgen,
6-
main,
75
)
86

97
output_to_build = {
@@ -58,16 +56,6 @@ def os_listdir_mock(monkeypatch):
5856
return listdir
5957

6058

61-
@pytest.fixture()
62-
def update_eventgen_mock(monkeypatch):
63-
ue = MagicMock()
64-
monkeypatch.setattr(
65-
"pytest_splunk_addon.standard_lib.utilities.create_new_eventgen.UpdateEventgen",
66-
ue,
67-
)
68-
return ue
69-
70-
7159
def test_update_eventgen_instantiation(app_mock):
7260
app_mock.return_value = "APP_RETURN_VALUE"
7361
event = UpdateEventgen("fake_path")
@@ -345,22 +333,3 @@ def test_create_new_eventgen(
345333
call.__exit__(None, None, None),
346334
]
347335
)
348-
349-
350-
def test_main(argparse_mock, update_eventgen_mock):
351-
update_eventgen_mock.return_value = update_eventgen_mock
352-
update_eventgen_mock.get_eventgen_stanzas.return_value = {"fake": "init"}
353-
update_eventgen_mock.update_eventgen_stanzas.return_value = {"fake": "updated"}
354-
args = namedtuple("Namespace", ["addon_path", "new_conf_path"])
355-
argparse_mock.parse_args.return_value = args(
356-
"fake_addon_path", "fake_new_conf_path"
357-
)
358-
main()
359-
update_eventgen_mock.assert_has_calls(
360-
[
361-
call("fake_addon_path"),
362-
call.get_eventgen_stanzas(),
363-
call.update_eventgen_stanzas({"fake": "init"}),
364-
call.create_new_eventgen({"fake": "updated"}, "fake_new_conf_path"),
365-
]
366-
)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[test1.samples]
2+
sourcetype = test:sourcetype
3+
source = source://test
4+
input_type = modinput
5+
host_type = plugin
6+
sourcetype_to_search = test:sourcetype
7+
timestamp_type = event
8+
sample_count = 1
9+
10+
token.0.token = ##Timestamp##
11+
token.0.replacementType = timestamp
12+
token.0.replacement = %Y-%m-%dT%H:%M:%S
13+
token.0.field = _time
14+
15+
token.1.token = ##user##
16+
token.1.replacementType = random
17+
token.1.replacement = list["[email protected]","[email protected]"]
18+
19+
token.2.token = ##ip##
20+
token.2.replacementType = random
21+
token.2.replacement = src["ipv4"]
22+
token.2.field = src
23+
24+
token.3.token = ##number##
25+
token.3.replacementType = random
26+
token.3.replacement = integer[100000000000000000000:999999999999999999999]
27+
28+
[test2.samples]
29+
sourcetype = test:sourcetype
30+
source = source://test:text
31+
input_type = modinput
32+
host_type = plugin
33+
sourcetype_to_search = test:sourcetype
34+
timestamp_type = event
35+
sample_count = 1
36+
37+
token.1.token = ##user##
38+
token.1.replacementType = random
39+
token.1.replacement = list["[email protected]","[email protected]"]
40+
41+
token.2.token = ##ip##
42+
token.2.replacementType = random
43+
token.2.replacement = src["ipv4"]
44+
token.2.field = src
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"number": "##number##", "ip": "##ip##", "user": "##user##", "time": "##Timestamp##"}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Src ip address ##ip## for user ##user##
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[test1.samples]
2+
sourcetype = test:sourcetype
3+
source = source://test
4+
input_type = modinput
5+
host_type = plugin
6+
sourcetype_to_search = test:sourcetype
7+
timestamp_type = event
8+
sample_count = 1
9+
10+
token.0.token = ##Timestamp##
11+
token.0.replacementType = timestamp
12+
token.0.replacement = %Y-%m-%dT%H:%M:%S
13+
token.0.field = _time
14+
15+
token.1.token = ##user##
16+
token.1.replacementType = random
17+
token.1.replacement = list["[email protected]","[email protected]"]
18+
19+
token.2.token = ##ip##
20+
token.2.replacementType = random
21+
token.2.replacement = src["ipv4"]
22+
token.2.field = src
23+
24+
token.3.token = ##number##
25+
token.3.replacementType = random
26+
token.3.replacement = integer[100000000000000000000:999999999999999999999]
27+
28+
[test2.samples]
29+
sourcetype = test:sourcetype
30+
source = source://test:text
31+
input_type = modinput
32+
host_type = plugin
33+
sourcetype_to_search = test:sourcetype
34+
timestamp_type = event
35+
sample_count = 1
36+
37+
token.1.token = ##user##
38+
token.1.replacementType = random
39+
token.1.replacement = list["[email protected]","[email protected]"]
40+
41+
token.2.token = ##ip##
42+
token.2.replacementType = random
43+
token.2.replacement = src["ipv4"]
44+
token.2.field = src

0 commit comments

Comments
 (0)