Skip to content

Commit aba10c7

Browse files
author
Sergey Vasilyev
committed
Test k8s-event posting in the background task
1 parent 751c42c commit aba10c7

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

kopf/engines/posting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def exception(obj, *, reason='', message='', exc=None):
5757
if exc is None:
5858
_, exc, _ = sys.exc_info()
5959
reason = reason if reason else type(exc).__name__
60-
message = f'{message} {exc}' if message else f'{exc}'
60+
message = f'{message} {exc}' if message and exc else f'{exc}' if exc else f'{message}'
6161
event(obj, type='Error', reason=reason, message=message)
6262

6363

tests/posting/test_poster.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import asyncio
2+
3+
import pytest
4+
from asynctest import call
5+
6+
from kopf import event, info, warn, exception
7+
from kopf.engines.posting import poster, K8sEvent, event_queue_var
8+
9+
OBJ1 = {'apiVersion': 'group1/version1', 'kind': 'Kind1',
10+
'metadata': {'uid': 'uid1', 'name': 'name1', 'namespace': 'ns1'}}
11+
REF1 = {'apiVersion': 'group1/version1', 'kind': 'Kind1',
12+
'uid': 'uid1', 'name': 'name1', 'namespace': 'ns1'}
13+
OBJ2 = {'apiVersion': 'group2/version2', 'kind': 'Kind2',
14+
'metadata': {'uid': 'uid2', 'name': 'name2', 'namespace': 'ns2'}}
15+
REF2 = {'apiVersion': 'group2/version2', 'kind': 'Kind2',
16+
'uid': 'uid2', 'name': 'name2', 'namespace': 'ns2'}
17+
18+
19+
async def test_poster_polls_and_posts(mocker):
20+
event1 = K8sEvent(type='type1', reason='reason1', message='message1', ref=REF1)
21+
event2 = K8sEvent(type='type2', reason='reason2', message='message2', ref=REF2)
22+
event_queue = asyncio.Queue()
23+
event_queue.put_nowait(event1)
24+
event_queue.put_nowait(event2)
25+
26+
# A way to cancel `while True` cycle when we need it (ASAP).
27+
def _cancel(*args, **kwargs):
28+
if post_event.call_count >= 2:
29+
raise asyncio.CancelledError()
30+
post_event = mocker.patch('kopf.clients.events.post_event', side_effect=_cancel)
31+
32+
# A way to cancel `whole True` cycle by timing, event if routines are not called.
33+
with pytest.raises(asyncio.CancelledError):
34+
await asyncio.wait_for(
35+
poster(event_queue=event_queue), timeout=0.5)
36+
37+
assert post_event.call_count == 2
38+
assert post_event.await_count == 2
39+
assert post_event.called_with(
40+
call(ref=REF1, type='type1', reason='reason1', message='message1'),
41+
call(ref=REF2, type='type2', reason='reason2', message='message2'),
42+
)
43+
44+
45+
def test_queueing_fails_with_no_queue(mocker):
46+
# Prerequisite: the context-var should not be set by anything in advance.
47+
sentinel = object()
48+
assert event_queue_var.get(sentinel) is sentinel
49+
50+
with pytest.raises(LookupError):
51+
event(OBJ1, type='type1', reason='reason1', message='message1')
52+
53+
54+
def test_via_event_function(mocker):
55+
post_event = mocker.patch('kopf.clients.events.post_event')
56+
57+
event_queue = asyncio.Queue()
58+
event_queue_var.set(event_queue)
59+
event(OBJ1, type='type1', reason='reason1', message='message1')
60+
61+
assert not post_event.called
62+
assert event_queue.qsize() == 1
63+
event1 = event_queue.get_nowait()
64+
65+
assert isinstance(event1, K8sEvent)
66+
assert event1.ref == REF1
67+
assert event1.type == 'type1'
68+
assert event1.reason == 'reason1'
69+
assert event1.message == 'message1'
70+
71+
72+
@pytest.mark.parametrize('event_fn, event_type', [
73+
pytest.param(info, "Normal", id='info'),
74+
pytest.param(warn, "Warning", id='warn'),
75+
pytest.param(exception, "Error", id='exception'),
76+
])
77+
def test_via_shortcut(mocker, event_fn, event_type):
78+
post_event = mocker.patch('kopf.clients.events.post_event')
79+
80+
event_queue = asyncio.Queue()
81+
event_queue_var.set(event_queue)
82+
event_fn(OBJ1, reason='reason1', message='message1')
83+
84+
assert not post_event.called
85+
assert event_queue.qsize() == 1
86+
event1 = event_queue.get_nowait()
87+
88+
assert isinstance(event1, K8sEvent)
89+
assert event1.ref == REF1
90+
assert event1.type == event_type
91+
assert event1.reason == 'reason1'
92+
assert event1.message == 'message1'

0 commit comments

Comments
 (0)