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

1import types 

2import typing 

3 

4import pytest 

5 

6from archdocs.main import SettingsForArchdocs 

7from tests import diagram_rendering 

8 

9 

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) 

112 

113 

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) 

125 

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