Skip to content

Commit 4e961b2

Browse files
authored
fix: standalone HEC Event writer (#380)
When create_from_token() is invoked, it triggers the HECEventWriter constructor with scheme, host, and port set to None. This leads to a get_splunkd_access_info() call, which throws an exception if the HEC URI doesn’t reference the local machine. As this call is unnecessary in such cases, its invocation has been relocated within the if-statement
1 parent bdc78c8 commit 4e961b2

File tree

2 files changed

+114
-67
lines changed

2 files changed

+114
-67
lines changed

solnlib/modular_input/event_writer.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,11 @@ def __init__(
229229
else:
230230
self.logger = logging
231231

232-
if not all([scheme, host, port]):
233-
scheme, host, port = get_splunkd_access_info()
234-
235232
if hec_uri and hec_token:
236233
scheme, host, hec_port = utils.extract_http_scheme_host_port(hec_uri)
237234
else:
235+
if not all([scheme, host, port]):
236+
scheme, host, port = get_splunkd_access_info()
238237
hec_port, hec_token = self._get_hec_config(
239238
hec_input_name, session_key, scheme, host, port, **context
240239
)

tests/unit/test_modular_input_event_writer.py

Lines changed: 112 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import sys
1919

2020
import common
21+
import pytest
2122
from splunklib import binding
2223

2324
from solnlib.modular_input import ClassicEventWriter, HECEventWriter
@@ -85,7 +86,54 @@ def flush(self):
8586
assert mock_stdout.write_count == 1
8687

8788

88-
def test_hec_event_writer(monkeypatch):
89+
def create_hec_event_writer__create_from_input(hec=False):
90+
return HECEventWriter.create_from_input(
91+
"HECTestInput",
92+
"https://localhost:8089",
93+
common.SESSION_KEY,
94+
global_settings_schema=hec,
95+
)
96+
97+
98+
def create_hec_event_writer__create_from_token_with_session_key(hec=False):
99+
return HECEventWriter.create_from_token_with_session_key(
100+
"https://localhost:8089",
101+
common.SESSION_KEY,
102+
"https://localhost:8090",
103+
"test_token",
104+
global_settings_schema=hec,
105+
)
106+
107+
108+
def create_hec_event_writer__create_from_token(hec=False):
109+
return HECEventWriter.create_from_token(
110+
"https://localhost:8090", "test_token", global_settings_schema=hec
111+
)
112+
113+
114+
def create_hec_event_writer__create_from_token__external_host(hec=False):
115+
return HECEventWriter.create_from_token(
116+
"https://external:8090", "test_token", global_settings_schema=hec
117+
)
118+
119+
120+
def create_hec_event_writer__constructor(hec=False):
121+
return HECEventWriter(
122+
"HECTestInput", common.SESSION_KEY, global_settings_schema=hec
123+
)
124+
125+
126+
@pytest.mark.parametrize(
127+
"create_hec_event_writer, has_splunk_home",
128+
[
129+
(create_hec_event_writer__constructor, True),
130+
(create_hec_event_writer__create_from_input, True),
131+
(create_hec_event_writer__create_from_token_with_session_key, True),
132+
(create_hec_event_writer__create_from_token, True),
133+
(create_hec_event_writer__create_from_token__external_host, False),
134+
],
135+
)
136+
def test_hec_event_writer(monkeypatch, create_hec_event_writer, has_splunk_home):
89137
def mock_get(self, path_segment, owner=None, app=None, sharing=None, **query):
90138
if path_segment.endswith("/http"):
91139
return common.make_response_record(
@@ -120,42 +168,46 @@ def mock_get_hec_config(
120168
):
121169
return "8088", "87de04d1-0823-11e6-9c94-a45e60e"
122170

123-
common.mock_splunkhome(monkeypatch)
171+
if has_splunk_home:
172+
common.mock_splunkhome(monkeypatch)
173+
else:
174+
# simulate an environment that has no splunk installation
175+
monkeypatch.delenv("SPLUNK_HOME", raising=False)
176+
monkeypatch.delenv("SPLUNK_ETC", raising=False)
124177
monkeypatch.setattr(binding.Context, "get", mock_get)
125178
monkeypatch.setattr(binding.Context, "post", mock_post)
126179
monkeypatch.setattr(HECEventWriter, "_get_hec_config", mock_get_hec_config)
127180

128-
for i in range(4):
129-
ew = create_hec_event_writer(i)
130-
131-
events = []
132-
events.append(
133-
ew.create_event(
134-
data="This is a test data1.",
135-
time=1372274622.493,
136-
index="main",
137-
host="localhost",
138-
source="Splunk",
139-
sourcetype="misc",
140-
stanza="test_scheme://test",
141-
unbroken=True,
142-
done=False,
143-
)
181+
ew = create_hec_event_writer(hec=False)
182+
183+
events = []
184+
events.append(
185+
ew.create_event(
186+
data="This is a test data1.",
187+
time=1372274622.493,
188+
index="main",
189+
host="localhost",
190+
source="Splunk",
191+
sourcetype="misc",
192+
stanza="test_scheme://test",
193+
unbroken=True,
194+
done=False,
144195
)
145-
events.append(
146-
ew.create_event(
147-
data="This is a test data2.",
148-
time=1372274622.493,
149-
index="main",
150-
host="localhost",
151-
source="Splunk",
152-
sourcetype="misc",
153-
stanza="test_scheme://test",
154-
unbroken=True,
155-
done=True,
156-
)
196+
)
197+
events.append(
198+
ew.create_event(
199+
data="This is a test data2.",
200+
time=1372274622.493,
201+
index="main",
202+
host="localhost",
203+
source="Splunk",
204+
sourcetype="misc",
205+
stanza="test_scheme://test",
206+
unbroken=True,
207+
done=True,
157208
)
158-
ew.write_events(events)
209+
)
210+
ew.write_events(events)
159211

160212
# length of this list will indicate how many times post was called
161213
times_post_called = []
@@ -170,7 +222,7 @@ def mock_post_2(
170222
# test that there are 2 event batches created for write_event and post is called 2 times
171223
# max batch size is 1,000,000. If the max size is exceeded then a new batch is created.
172224
assert len(times_post_called) == 0
173-
ew = create_hec_event_writer(1)
225+
174226
events = []
175227

176228
# each event length will be ~500 characters, 3000 events length will equal ~1,500,000 characters
@@ -207,35 +259,31 @@ def mock_post_2(
207259
# test that post is called 2 times
208260
assert len(times_post_called) == 2
209261

210-
for i in range(4):
211-
ev = create_hec_event_writer(i)
212-
assert ev._rest_client.scheme == "https"
213-
for i in range(4):
214-
ev = create_hec_event_writer(i, hec=True)
215-
assert ev._rest_client.scheme == "http"
216-
217-
218-
def create_hec_event_writer(i, hec=False):
219-
if i == 1:
220-
return HECEventWriter.create_from_input(
221-
"HECTestInput",
222-
"https://localhost:8089",
223-
common.SESSION_KEY,
224-
global_settings_schema=hec,
225-
)
226-
elif i == 2:
227-
return HECEventWriter.create_from_token_with_session_key(
228-
"https://localhost:8089",
229-
common.SESSION_KEY,
230-
"https://localhost:8090",
231-
"test_token",
232-
global_settings_schema=hec,
233-
)
234-
elif i == 3:
235-
return HECEventWriter.create_from_token(
236-
"https://localhost:8090", "test_token", global_settings_schema=hec
237-
)
238-
else:
239-
return HECEventWriter(
240-
"HECTestInput", common.SESSION_KEY, global_settings_schema=hec
241-
)
262+
263+
@pytest.mark.parametrize(
264+
"create_hec_event_writer, hec, expected_scheme",
265+
[
266+
(create_hec_event_writer__constructor, True, "http"),
267+
(create_hec_event_writer__constructor, False, "https"),
268+
(create_hec_event_writer__create_from_input, True, "http"),
269+
(create_hec_event_writer__create_from_input, False, "https"),
270+
(create_hec_event_writer__create_from_token_with_session_key, True, "http"),
271+
(create_hec_event_writer__create_from_token_with_session_key, False, "https"),
272+
(create_hec_event_writer__create_from_token, True, "http"),
273+
(create_hec_event_writer__create_from_token, False, "https"),
274+
],
275+
)
276+
def test_hec_event_writer_gets_scheme_from_global_settings_if_requested(
277+
monkeypatch, create_hec_event_writer, hec, expected_scheme
278+
):
279+
common.mock_splunkhome(monkeypatch)
280+
281+
def mock_get_hec_config(
282+
self, hec_input_name, session_key, scheme, host, port, **context
283+
):
284+
return "8088", "87de04d1-0823-11e6-9c94-a45e60e"
285+
286+
monkeypatch.setattr(HECEventWriter, "_get_hec_config", mock_get_hec_config)
287+
288+
ev = create_hec_event_writer(hec)
289+
assert ev._rest_client.scheme == expected_scheme

0 commit comments

Comments
 (0)