Coverage for tests/test_kubernetes.py: 100%
15 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-18 22:03 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-18 22:03 +0000
1import types
2import typing
4import pytest
6from archdocs.main import SettingsForArchdocs
7from tests import diagram_rendering
10_FIXTURE_ANNOTATIONS: typing.Final = "replicas 3, HPA 2-10, target CPU 70%, cpu 100m-500m, RAM 128Mi-512Mi, GPU 1"
11_STATEFULSET_ANNOTATIONS: typing.Final = "StatefulSet, replicas 2, HPA 2-6, target CPU 80%, cpu 250m-1, RAM 256Mi-1Gi"
12_ALL_MANIFEST_CASES: typing.Final = types.MappingProxyType(
13 {
14 "chart of the project": (
15 SettingsForArchdocs(
16 root_dir=diagram_rendering.TESTS_ROOT / "kubernetes_fixtures", service_name="kubernetes-svc"
17 ),
18 (
19 f'kubernetes_svc{{"kubernetes-svc ({_FIXTURE_ANNOTATIONS})"}}',
20 'external_client --> |"HTTPS api.example.com"| kubernetes_svc',
21 ),
22 (),
23 ),
24 "manifests and code on one node": (
25 SettingsForArchdocs(
26 root_dir=diagram_rendering.LITESTAR_ROOT,
27 service_name="merged-svc",
28 kubernetes_dir=diagram_rendering.TESTS_ROOT / "kubernetes_fixtures" / "chart",
29 ),
30 (
31 f'merged_svc{{"merged-svc ({_FIXTURE_ANNOTATIONS})"}}',
32 'external_client --> |"HTTPS api.example.com"| merged_svc',
33 'ConfigMap_app_config --> |"env"| merged_svc',
34 'Secret_app_secrets --> |"env"| merged_svc',
35 'ConfigMap_app_tuning --> |"volume"| merged_svc',
36 'merged_svc --> |"volume 10Gi"| PersistentVolume',
37 'redisdb["redis"]',
38 ),
39 (),
40 ),
41 "disabled toggles": (
42 SettingsForArchdocs(
43 root_dir=diagram_rendering.FASTAPI_ROOT,
44 service_name="disabled-svc",
45 kubernetes_dir=diagram_rendering.KUBERNETES_VARIANTS_ROOT / "disabled",
46 ),
47 ('disabled_svc{"disabled-svc (replicas 2)"}',),
48 ("never.example.com", "Ingress", "HPA", "PersistentVolume"),
49 ),
50 # The second host spells its own name with quotes: a label carrying one closes the edge
51 # early and takes the whole diagram down with it, so the quote may not reach the page.
52 "ingress without its own tls": (
53 SettingsForArchdocs(
54 root_dir=diagram_rendering.FASTAPI_ROOT,
55 service_name="plain-svc",
56 kubernetes_dir=diagram_rendering.KUBERNETES_VARIANTS_ROOT / "plain_ingress",
57 ),
58 (
59 'plain_svc{"plain-svc (replicas 1, cpu 50m)"}',
60 'external_client --> |"HTTP plain.example.com"| plain_svc',
61 'external_client --> |"HTTP quoted.example.com"| plain_svc',
62 ),
63 ("HTTPS", '"example"'),
64 ),
65 "load balancer entrypoint": (
66 SettingsForArchdocs(
67 root_dir=diagram_rendering.FASTAPI_ROOT,
68 service_name="entry-svc",
69 kubernetes_dir=diagram_rendering.KUBERNETES_VARIANTS_ROOT / "loadbalancer",
70 ),
71 ('external_client --> |"LoadBalancer, port 8080"| entry_svc',),
72 (),
73 ),
74 "node port entrypoint": (
75 SettingsForArchdocs(
76 root_dir=diagram_rendering.FASTAPI_ROOT,
77 service_name="entry-svc",
78 kubernetes_dir=diagram_rendering.KUBERNETES_VARIANTS_ROOT / "nodeport",
79 ),
80 (
81 'entry_svc{"entry-svc (RAM up to 512Mi)"}',
82 'external_client --> |"NodePort"| entry_svc',
83 'entry_svc --> |"volume 5Gi"| PersistentVolume',
84 ),
85 (),
86 ),
87 "ingress entrypoint": (
88 SettingsForArchdocs(
89 root_dir=diagram_rendering.FASTAPI_ROOT,
90 service_name="entry-svc",
91 kubernetes_dir=diagram_rendering.KUBERNETES_VARIANTS_ROOT / "bare_ingress",
92 ),
93 ('external_client --> |"Ingress"| entry_svc',),
94 (),
95 ),
96 "plain manifests without a chart": (
97 SettingsForArchdocs(
98 root_dir=diagram_rendering.FASTAPI_ROOT,
99 service_name="stateful-svc",
100 kubernetes_dir=diagram_rendering.KUBERNETES_VARIANTS_ROOT / "statefulset",
101 ),
102 (
103 f'stateful_svc{{"stateful-svc ({_STATEFULSET_ANNOTATIONS})"}}',
104 'external_client --> |"NodePort, port 8080"| stateful_svc',
105 'Secret_stateful_secrets --> |"env"| stateful_svc',
106 'stateful_svc --> |"volume 20Gi"| PersistentVolume',
107 ),
108 (),
109 ),
110 },
111)
114@pytest.mark.parametrize(
115 ("arch_settings", "expected_parts", "forbidden_parts"),
116 _ALL_MANIFEST_CASES.values(),
117 ids=_ALL_MANIFEST_CASES,
118)
119def test_manifests_reach_the_diagram(
120 arch_settings: SettingsForArchdocs,
121 expected_parts: tuple[str, ...],
122 forbidden_parts: tuple[str, ...],
123) -> None:
124 rendered_diagram: typing.Final = diagram_rendering.render_example_diagram(arch_settings)
126 for one_expected_part in expected_parts:
127 assert one_expected_part in rendered_diagram, one_expected_part
128 for one_forbidden_part in forbidden_parts:
129 assert one_forbidden_part not in rendered_diagram, one_forbidden_part