Skip to content

Commit 65b4862

Browse files
authored
add tests for controller (kopf) (#9)
Signed-off-by: Luiz Oliveira <ziuloliveira@gmail.com>
1 parent 8d7f14a commit 65b4862

File tree

3 files changed

+104
-2
lines changed

3 files changed

+104
-2
lines changed

.github/workflows/tests.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ jobs:
2121
name: Linting
2222
- name: Bandit
2323
uses: PyCQA/bandit-action@v1
24+
with:
25+
exclude: "tests,charts"
26+
skips: B101
2427
- name: Pytest
2528
run: |
2629
pip install poetry

controller.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def configure(memo: kopf.Memo, **_):
1414
async def cleanup_fn(logger, **kwargs):
1515
logger.info("Cleaning up resources...")
1616

17-
@kopf.on.event('v1', 'services',
17+
@kopf.on.event('v1', 'services',
1818
annotations={os.environ.get('SWAGGER_OPERATOR_PATH_KEY', 'swagger-operator-path'):kopf.PRESENT},
1919
)
2020
def service_event(event, memo: kopf.Memo, logger, **kwargs):
@@ -34,7 +34,7 @@ def service_event(event, memo: kopf.Memo, logger, **kwargs):
3434
if not application_url.netloc:
3535
if not application_url.path.startswith('/'):
3636
application_url = urlparse(f"/{application_url.path}")
37-
application_url = urlparse(f"http://{service_name}.{namespace}.svc.cluster.local:{application_port}{application_path}")
37+
application_url = urlparse(f"http://{service_name}.{namespace}.svc.cluster.local:{application_port}{application_url.path}")
3838

3939

4040

tests/test_controller.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from unittest.mock import MagicMock, patch
2+
3+
import pytest
4+
from controller import service_event
5+
6+
@pytest.fixture
7+
def fake_memo():
8+
class Memo:
9+
apps = {}
10+
return Memo()
11+
12+
def make_event(path):
13+
return {
14+
'type': 'ADDED',
15+
'object': {
16+
'metadata': {
17+
'name': 'my-service',
18+
'namespace': 'default',
19+
'annotations': {
20+
'swagger-operator-path': path,
21+
'swagger-operator-name': 'my-app',
22+
'swagger-operator-port': '8080',
23+
'swagger-operator-header': 'X-API-KEY'
24+
}
25+
}
26+
}
27+
}
28+
29+
def test_path_without_slash(fake_memo):
30+
# Path without leading slash
31+
event = make_event("openapi.json")
32+
logger = MagicMock()
33+
with patch("builtins.open"), patch("json.dump"):
34+
service_event(event, fake_memo, logger)
35+
key = "default/my-app"
36+
assert key in fake_memo.apps
37+
# The final path should contain the original path
38+
assert fake_memo.apps[key]['url'].endswith("/openapi.json")
39+
40+
def test_path_with_slash(fake_memo):
41+
# Path with leading slash
42+
event = make_event("/openapi.json")
43+
logger = MagicMock()
44+
with patch("builtins.open"), patch("json.dump"):
45+
service_event(event, fake_memo, logger)
46+
key = "default/my-app"
47+
assert key in fake_memo.apps
48+
assert fake_memo.apps[key]['url'].endswith("/openapi.json")
49+
50+
def test_path_with_host(fake_memo):
51+
# Path with host
52+
event = make_event("http://myhost/openapi.json")
53+
logger = MagicMock()
54+
with patch("builtins.open"), patch("json.dump"):
55+
service_event(event, fake_memo, logger)
56+
key = "default/my-app"
57+
assert key in fake_memo.apps
58+
# The host should be preserved
59+
assert fake_memo.apps[key]['url'].startswith("http://myhost")
60+
61+
def test_missing_annotation(fake_memo):
62+
# Missing annotation
63+
event = make_event("/openapi.json")
64+
del event['object']['metadata']['annotations']['swagger-operator-path']
65+
logger = MagicMock()
66+
with patch("builtins.open"), patch("json.dump"):
67+
try:
68+
service_event(event, fake_memo, logger)
69+
assert False, "Should raise KeyError"
70+
except KeyError:
71+
pass
72+
73+
def test_service_event_deleted(fake_memo):
74+
# Pre-add an app to memo
75+
fake_memo.apps["default/my-app"] = {
76+
"url": "http://dummy",
77+
"name": "my-app",
78+
"header": "X-API-KEY"
79+
}
80+
event = {
81+
'type': 'DELETED',
82+
'object': {
83+
'metadata': {
84+
'name': 'my-service',
85+
'namespace': 'default',
86+
'annotations': {
87+
'swagger-operator-path': '/openapi.json',
88+
'swagger-operator-name': 'my-app',
89+
'swagger-operator-port': '8080',
90+
'swagger-operator-header': 'X-API-KEY'
91+
}
92+
}
93+
}
94+
}
95+
logger = MagicMock()
96+
with patch("builtins.open"), patch("json.dump"):
97+
service_event(event, fake_memo, logger)
98+
# Should remove the app from memo
99+
assert "default/my-app" not in fake_memo.apps

0 commit comments

Comments
 (0)