kstlib 0.0.1a0__py3-none-any.whl → 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. kstlib/__init__.py +266 -1
  2. kstlib/__main__.py +16 -0
  3. kstlib/alerts/__init__.py +110 -0
  4. kstlib/alerts/channels/__init__.py +36 -0
  5. kstlib/alerts/channels/base.py +197 -0
  6. kstlib/alerts/channels/email.py +227 -0
  7. kstlib/alerts/channels/slack.py +389 -0
  8. kstlib/alerts/exceptions.py +72 -0
  9. kstlib/alerts/manager.py +651 -0
  10. kstlib/alerts/models.py +142 -0
  11. kstlib/alerts/throttle.py +263 -0
  12. kstlib/auth/__init__.py +139 -0
  13. kstlib/auth/callback.py +399 -0
  14. kstlib/auth/config.py +502 -0
  15. kstlib/auth/errors.py +127 -0
  16. kstlib/auth/models.py +316 -0
  17. kstlib/auth/providers/__init__.py +14 -0
  18. kstlib/auth/providers/base.py +393 -0
  19. kstlib/auth/providers/oauth2.py +645 -0
  20. kstlib/auth/providers/oidc.py +821 -0
  21. kstlib/auth/session.py +338 -0
  22. kstlib/auth/token.py +482 -0
  23. kstlib/cache/__init__.py +50 -0
  24. kstlib/cache/decorator.py +261 -0
  25. kstlib/cache/strategies.py +516 -0
  26. kstlib/cli/__init__.py +8 -0
  27. kstlib/cli/app.py +195 -0
  28. kstlib/cli/commands/__init__.py +5 -0
  29. kstlib/cli/commands/auth/__init__.py +39 -0
  30. kstlib/cli/commands/auth/common.py +122 -0
  31. kstlib/cli/commands/auth/login.py +325 -0
  32. kstlib/cli/commands/auth/logout.py +74 -0
  33. kstlib/cli/commands/auth/providers.py +57 -0
  34. kstlib/cli/commands/auth/status.py +291 -0
  35. kstlib/cli/commands/auth/token.py +199 -0
  36. kstlib/cli/commands/auth/whoami.py +106 -0
  37. kstlib/cli/commands/config.py +89 -0
  38. kstlib/cli/commands/ops/__init__.py +39 -0
  39. kstlib/cli/commands/ops/attach.py +49 -0
  40. kstlib/cli/commands/ops/common.py +269 -0
  41. kstlib/cli/commands/ops/list_sessions.py +252 -0
  42. kstlib/cli/commands/ops/logs.py +49 -0
  43. kstlib/cli/commands/ops/start.py +98 -0
  44. kstlib/cli/commands/ops/status.py +138 -0
  45. kstlib/cli/commands/ops/stop.py +60 -0
  46. kstlib/cli/commands/rapi/__init__.py +60 -0
  47. kstlib/cli/commands/rapi/call.py +341 -0
  48. kstlib/cli/commands/rapi/list.py +99 -0
  49. kstlib/cli/commands/rapi/show.py +206 -0
  50. kstlib/cli/commands/secrets/__init__.py +35 -0
  51. kstlib/cli/commands/secrets/common.py +425 -0
  52. kstlib/cli/commands/secrets/decrypt.py +88 -0
  53. kstlib/cli/commands/secrets/doctor.py +743 -0
  54. kstlib/cli/commands/secrets/encrypt.py +242 -0
  55. kstlib/cli/commands/secrets/shred.py +96 -0
  56. kstlib/cli/common.py +86 -0
  57. kstlib/config/__init__.py +76 -0
  58. kstlib/config/exceptions.py +110 -0
  59. kstlib/config/export.py +225 -0
  60. kstlib/config/loader.py +963 -0
  61. kstlib/config/sops.py +287 -0
  62. kstlib/db/__init__.py +54 -0
  63. kstlib/db/aiosqlcipher.py +137 -0
  64. kstlib/db/cipher.py +112 -0
  65. kstlib/db/database.py +367 -0
  66. kstlib/db/exceptions.py +25 -0
  67. kstlib/db/pool.py +302 -0
  68. kstlib/helpers/__init__.py +35 -0
  69. kstlib/helpers/exceptions.py +11 -0
  70. kstlib/helpers/time_trigger.py +396 -0
  71. kstlib/kstlib.conf.yml +890 -0
  72. kstlib/limits.py +963 -0
  73. kstlib/logging/__init__.py +108 -0
  74. kstlib/logging/manager.py +633 -0
  75. kstlib/mail/__init__.py +42 -0
  76. kstlib/mail/builder.py +626 -0
  77. kstlib/mail/exceptions.py +27 -0
  78. kstlib/mail/filesystem.py +248 -0
  79. kstlib/mail/transport.py +224 -0
  80. kstlib/mail/transports/__init__.py +19 -0
  81. kstlib/mail/transports/gmail.py +268 -0
  82. kstlib/mail/transports/resend.py +324 -0
  83. kstlib/mail/transports/smtp.py +326 -0
  84. kstlib/meta.py +72 -0
  85. kstlib/metrics/__init__.py +88 -0
  86. kstlib/metrics/decorators.py +1090 -0
  87. kstlib/metrics/exceptions.py +14 -0
  88. kstlib/monitoring/__init__.py +116 -0
  89. kstlib/monitoring/_styles.py +163 -0
  90. kstlib/monitoring/cell.py +57 -0
  91. kstlib/monitoring/config.py +424 -0
  92. kstlib/monitoring/delivery.py +579 -0
  93. kstlib/monitoring/exceptions.py +63 -0
  94. kstlib/monitoring/image.py +220 -0
  95. kstlib/monitoring/kv.py +79 -0
  96. kstlib/monitoring/list.py +69 -0
  97. kstlib/monitoring/metric.py +88 -0
  98. kstlib/monitoring/monitoring.py +341 -0
  99. kstlib/monitoring/renderer.py +139 -0
  100. kstlib/monitoring/service.py +392 -0
  101. kstlib/monitoring/table.py +129 -0
  102. kstlib/monitoring/types.py +56 -0
  103. kstlib/ops/__init__.py +86 -0
  104. kstlib/ops/base.py +148 -0
  105. kstlib/ops/container.py +577 -0
  106. kstlib/ops/exceptions.py +209 -0
  107. kstlib/ops/manager.py +407 -0
  108. kstlib/ops/models.py +176 -0
  109. kstlib/ops/tmux.py +372 -0
  110. kstlib/ops/validators.py +287 -0
  111. kstlib/py.typed +0 -0
  112. kstlib/rapi/__init__.py +118 -0
  113. kstlib/rapi/client.py +875 -0
  114. kstlib/rapi/config.py +861 -0
  115. kstlib/rapi/credentials.py +887 -0
  116. kstlib/rapi/exceptions.py +213 -0
  117. kstlib/resilience/__init__.py +101 -0
  118. kstlib/resilience/circuit_breaker.py +440 -0
  119. kstlib/resilience/exceptions.py +95 -0
  120. kstlib/resilience/heartbeat.py +491 -0
  121. kstlib/resilience/rate_limiter.py +506 -0
  122. kstlib/resilience/shutdown.py +417 -0
  123. kstlib/resilience/watchdog.py +637 -0
  124. kstlib/secrets/__init__.py +29 -0
  125. kstlib/secrets/exceptions.py +19 -0
  126. kstlib/secrets/models.py +62 -0
  127. kstlib/secrets/providers/__init__.py +79 -0
  128. kstlib/secrets/providers/base.py +58 -0
  129. kstlib/secrets/providers/environment.py +66 -0
  130. kstlib/secrets/providers/keyring.py +107 -0
  131. kstlib/secrets/providers/kms.py +223 -0
  132. kstlib/secrets/providers/kwargs.py +101 -0
  133. kstlib/secrets/providers/sops.py +209 -0
  134. kstlib/secrets/resolver.py +221 -0
  135. kstlib/secrets/sensitive.py +130 -0
  136. kstlib/secure/__init__.py +23 -0
  137. kstlib/secure/fs.py +194 -0
  138. kstlib/secure/permissions.py +70 -0
  139. kstlib/ssl.py +347 -0
  140. kstlib/ui/__init__.py +23 -0
  141. kstlib/ui/exceptions.py +26 -0
  142. kstlib/ui/panels.py +484 -0
  143. kstlib/ui/spinner.py +864 -0
  144. kstlib/ui/tables.py +382 -0
  145. kstlib/utils/__init__.py +48 -0
  146. kstlib/utils/dict.py +36 -0
  147. kstlib/utils/formatting.py +338 -0
  148. kstlib/utils/http_trace.py +237 -0
  149. kstlib/utils/lazy.py +49 -0
  150. kstlib/utils/secure_delete.py +205 -0
  151. kstlib/utils/serialization.py +247 -0
  152. kstlib/utils/text.py +56 -0
  153. kstlib/utils/validators.py +124 -0
  154. kstlib/websocket/__init__.py +97 -0
  155. kstlib/websocket/exceptions.py +214 -0
  156. kstlib/websocket/manager.py +1102 -0
  157. kstlib/websocket/models.py +361 -0
  158. kstlib-1.0.0.dist-info/METADATA +201 -0
  159. kstlib-1.0.0.dist-info/RECORD +163 -0
  160. {kstlib-0.0.1a0.dist-info → kstlib-1.0.0.dist-info}/WHEEL +1 -1
  161. kstlib-1.0.0.dist-info/entry_points.txt +2 -0
  162. kstlib-1.0.0.dist-info/licenses/LICENSE.md +9 -0
  163. kstlib-0.0.1a0.dist-info/METADATA +0 -29
  164. kstlib-0.0.1a0.dist-info/RECORD +0 -6
  165. kstlib-0.0.1a0.dist-info/licenses/LICENSE.md +0 -5
  166. {kstlib-0.0.1a0.dist-info → kstlib-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,14 @@
1
+ """Exceptions for the metrics module."""
2
+
3
+ __all__ = ["MetricsError"]
4
+
5
+
6
+ class MetricsError(Exception):
7
+ """Base exception for metrics-related errors.
8
+
9
+ Examples:
10
+ >>> raise MetricsError("Something went wrong")
11
+ Traceback (most recent call last):
12
+ ...
13
+ kstlib.metrics.exceptions.MetricsError: Something went wrong
14
+ """
@@ -0,0 +1,116 @@
1
+ """HTML monitoring render types for dashboards and email reports.
2
+
3
+ This module provides five render types that produce HTML output suitable
4
+ for both browser dashboards (CSS classes) and email reports (inline CSS).
5
+
6
+ Render types:
7
+
8
+ - **StatusCell**: Colored ``<span>`` badge for UP/DOWN/DEGRADED indicators.
9
+ - **MonitorTable**: Striped ``<table>`` with typed headers and row validation.
10
+ - **MonitorKV**: Two-column ``<dl>`` grid for key-value stat panels.
11
+ - **MonitorList**: ``<ul>``/``<ol>`` for event logs and alert lists.
12
+ - **MonitorMetric**: Hero-number ``<div>`` for KPI display (P&L, uptime).
13
+ - **MonitorImage**: Base64 ``<img>`` for embedded logos and icons.
14
+
15
+ All render types implement ``render(*, inline_css: bool = False) -> str``:
16
+
17
+ - ``inline_css=False``: CSS class references (``.status-ok``, ``.monitor-table``).
18
+ - ``inline_css=True``: Inline ``style`` attributes for email compatibility.
19
+
20
+ Examples:
21
+ Basic status badge:
22
+
23
+ >>> from kstlib.monitoring import StatusCell, StatusLevel
24
+ >>> cell = StatusCell("UP", StatusLevel.OK)
25
+ >>> cell.render()
26
+ '<span class="status-ok">UP</span>'
27
+
28
+ Table with status cells:
29
+
30
+ >>> from kstlib.monitoring import MonitorTable
31
+ >>> t = MonitorTable(headers=["Service", "Status"])
32
+ >>> t.add_row(["API", StatusCell("OK", StatusLevel.OK)])
33
+ >>> "<table" in t.render()
34
+ True
35
+ """
36
+
37
+ from __future__ import annotations
38
+
39
+ from kstlib.monitoring._styles import get_css_classes
40
+ from kstlib.monitoring.cell import StatusCell
41
+ from kstlib.monitoring.config import (
42
+ CollectorConfig,
43
+ MonitoringConfig,
44
+ MonitoringConfigCollectorError,
45
+ MonitoringConfigFileNotFoundError,
46
+ MonitoringConfigFormatError,
47
+ create_services_from_directory,
48
+ discover_monitoring_configs,
49
+ load_monitoring_config,
50
+ )
51
+ from kstlib.monitoring.delivery import (
52
+ DeliveryBackend,
53
+ DeliveryConfigError,
54
+ DeliveryError,
55
+ DeliveryIOError,
56
+ DeliveryResult,
57
+ FileDelivery,
58
+ FileDeliveryConfig,
59
+ MailDelivery,
60
+ MailDeliveryConfig,
61
+ )
62
+ from kstlib.monitoring.exceptions import (
63
+ CollectorError,
64
+ MonitoringConfigError,
65
+ MonitoringError,
66
+ RenderError,
67
+ )
68
+ from kstlib.monitoring.image import MonitorImage
69
+ from kstlib.monitoring.kv import MonitorKV
70
+ from kstlib.monitoring.list import MonitorList
71
+ from kstlib.monitoring.metric import MonitorMetric
72
+ from kstlib.monitoring.monitoring import Monitoring
73
+ from kstlib.monitoring.renderer import create_environment, render_html, render_template
74
+ from kstlib.monitoring.service import MonitoringResult, MonitoringService
75
+ from kstlib.monitoring.table import MonitorTable
76
+ from kstlib.monitoring.types import CellValue, Renderable, StatusLevel
77
+
78
+ __all__ = [
79
+ "CellValue",
80
+ "CollectorConfig",
81
+ "CollectorError",
82
+ "DeliveryBackend",
83
+ "DeliveryConfigError",
84
+ "DeliveryError",
85
+ "DeliveryIOError",
86
+ "DeliveryResult",
87
+ "FileDelivery",
88
+ "FileDeliveryConfig",
89
+ "MailDelivery",
90
+ "MailDeliveryConfig",
91
+ "MonitorImage",
92
+ "MonitorKV",
93
+ "MonitorList",
94
+ "MonitorMetric",
95
+ "MonitorTable",
96
+ "Monitoring",
97
+ "MonitoringConfig",
98
+ "MonitoringConfigCollectorError",
99
+ "MonitoringConfigError",
100
+ "MonitoringConfigFileNotFoundError",
101
+ "MonitoringConfigFormatError",
102
+ "MonitoringError",
103
+ "MonitoringResult",
104
+ "MonitoringService",
105
+ "RenderError",
106
+ "Renderable",
107
+ "StatusCell",
108
+ "StatusLevel",
109
+ "create_environment",
110
+ "create_services_from_directory",
111
+ "discover_monitoring_configs",
112
+ "get_css_classes",
113
+ "load_monitoring_config",
114
+ "render_html",
115
+ "render_template",
116
+ ]
@@ -0,0 +1,163 @@
1
+ """Centralized colors and CSS helpers for monitoring HTML rendering.
2
+
3
+ All colors, CSS class names, and inline style strings are defined here
4
+ to ensure visual consistency across all render types.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from kstlib.monitoring.types import StatusLevel
10
+
11
+ # ---------------------------------------------------------------------------
12
+ # Color palette
13
+ # ---------------------------------------------------------------------------
14
+
15
+ #: Mapping of status levels to their hex color codes.
16
+ STATUS_COLORS: dict[StatusLevel, str] = {
17
+ StatusLevel.OK: "#16A085",
18
+ StatusLevel.WARNING: "#F1C40F",
19
+ StatusLevel.ERROR: "#E85A4F",
20
+ StatusLevel.CRITICAL: "#c0392b",
21
+ }
22
+
23
+ #: Mapping of status levels to their text color (for contrast).
24
+ STATUS_TEXT_COLORS: dict[StatusLevel, str] = {
25
+ StatusLevel.OK: "#ffffff",
26
+ StatusLevel.WARNING: "#2c3e50",
27
+ StatusLevel.ERROR: "#ffffff",
28
+ StatusLevel.CRITICAL: "#ffffff",
29
+ }
30
+
31
+ # ---------------------------------------------------------------------------
32
+ # CSS class names
33
+ # ---------------------------------------------------------------------------
34
+
35
+ #: Mapping of status levels to their CSS class names.
36
+ STATUS_CSS_CLASSES: dict[StatusLevel, str] = {
37
+ StatusLevel.OK: "status-ok",
38
+ StatusLevel.WARNING: "status-warning",
39
+ StatusLevel.ERROR: "status-error",
40
+ StatusLevel.CRITICAL: "status-critical",
41
+ }
42
+
43
+ # ---------------------------------------------------------------------------
44
+ # Table styling constants
45
+ # ---------------------------------------------------------------------------
46
+
47
+ TABLE_BORDER_COLOR = "#ddd"
48
+ TABLE_HEADER_BG = "#2c3e50"
49
+ TABLE_HEADER_TEXT = "#ffffff"
50
+ TABLE_ROW_BG = "#ffffff"
51
+ TABLE_ROW_TEXT = "#2c3e50"
52
+ TABLE_STRIPE_BG = "#f0f0f0"
53
+ TABLE_FONT_FAMILY = "Consolas, Monaco, 'Courier New', monospace"
54
+
55
+ # ---------------------------------------------------------------------------
56
+ # Metric styling constants
57
+ # ---------------------------------------------------------------------------
58
+
59
+ METRIC_FONT_SIZE = "2.5em"
60
+ METRIC_LABEL_COLOR = "#7f8c8d"
61
+
62
+ # ---------------------------------------------------------------------------
63
+ # Helpers
64
+ # ---------------------------------------------------------------------------
65
+
66
+
67
+ def inline_badge_style(level: StatusLevel) -> str:
68
+ """Return an inline CSS style string for a status badge.
69
+
70
+ Args:
71
+ level: The status severity level.
72
+
73
+ Returns:
74
+ CSS style string suitable for a ``style`` attribute.
75
+
76
+ Examples:
77
+ >>> from kstlib.monitoring._styles import inline_badge_style
78
+ >>> from kstlib.monitoring.types import StatusLevel
79
+ >>> "background" in inline_badge_style(StatusLevel.OK)
80
+ True
81
+ """
82
+ bg = STATUS_COLORS[level]
83
+ fg = STATUS_TEXT_COLORS[level]
84
+ return f"background:{bg};color:{fg};padding:2px 8px;border-radius:4px;font-weight:bold;font-size:0.85em"
85
+
86
+
87
+ def get_css_classes() -> str:
88
+ """Return a ``<style>`` block with all monitoring CSS classes.
89
+
90
+ This should be included once in the ``<head>`` of an HTML document
91
+ when using class-based rendering (``inline_css=False``).
92
+
93
+ Returns:
94
+ Complete ``<style>`` element as a string.
95
+
96
+ Examples:
97
+ >>> from kstlib.monitoring._styles import get_css_classes
98
+ >>> css = get_css_classes()
99
+ >>> "<style>" in css
100
+ True
101
+ >>> ".status-ok" in css
102
+ True
103
+ """
104
+ rules: list[str] = []
105
+
106
+ # Status badge classes
107
+ for level in StatusLevel:
108
+ cls = STATUS_CSS_CLASSES[level]
109
+ bg = STATUS_COLORS[level]
110
+ fg = STATUS_TEXT_COLORS[level]
111
+ rules.append(
112
+ f".{cls} {{"
113
+ f" background:{bg}; color:{fg};"
114
+ f" padding:2px 8px; border-radius:4px;"
115
+ f" font-weight:bold; font-size:0.85em;"
116
+ f" }}"
117
+ )
118
+
119
+ # Monitor table
120
+ rules.append(
121
+ f".monitor-table {{"
122
+ f" border-collapse:collapse; width:100%; font-family:{TABLE_FONT_FAMILY};"
123
+ f" background:{TABLE_ROW_BG}; color:{TABLE_ROW_TEXT};"
124
+ f" }}"
125
+ )
126
+ rules.append(
127
+ f".monitor-table th {{"
128
+ f" background:{TABLE_HEADER_BG}; color:{TABLE_HEADER_TEXT};"
129
+ f" padding:8px 12px; text-align:left;"
130
+ f" }}"
131
+ )
132
+ rules.append(f".monitor-table td {{ padding:8px 12px; border-bottom:1px solid {TABLE_BORDER_COLOR}; }}")
133
+ rules.append(f".monitor-table tr:nth-child(even) {{ background:{TABLE_STRIPE_BG}; }}")
134
+
135
+ # Monitor KV
136
+ rules.append(".monitor-kv { display:grid; grid-template-columns:auto 1fr; gap:4px 12px; }")
137
+ rules.append(".monitor-kv dt { font-weight:bold; }")
138
+
139
+ # Monitor metric
140
+ rules.append(".monitor-metric { text-align:center; padding:12px; }")
141
+ rules.append(f".monitor-metric .metric-value {{ font-size:{METRIC_FONT_SIZE}; font-weight:bold; }}")
142
+ rules.append(f".monitor-metric .metric-label {{ color:{METRIC_LABEL_COLOR}; font-size:0.9em; }}")
143
+
144
+ body = "\n".join(rules)
145
+ return f"<style>\n{body}\n</style>"
146
+
147
+
148
+ __all__ = [
149
+ "METRIC_FONT_SIZE",
150
+ "METRIC_LABEL_COLOR",
151
+ "STATUS_COLORS",
152
+ "STATUS_CSS_CLASSES",
153
+ "STATUS_TEXT_COLORS",
154
+ "TABLE_BORDER_COLOR",
155
+ "TABLE_FONT_FAMILY",
156
+ "TABLE_HEADER_BG",
157
+ "TABLE_HEADER_TEXT",
158
+ "TABLE_ROW_BG",
159
+ "TABLE_ROW_TEXT",
160
+ "TABLE_STRIPE_BG",
161
+ "get_css_classes",
162
+ "inline_badge_style",
163
+ ]
@@ -0,0 +1,57 @@
1
+ """StatusCell render type for colored status badges.
2
+
3
+ A ``StatusCell`` renders as a ``<span>`` badge with color coding based on
4
+ the severity level (OK, WARNING, ERROR, CRITICAL).
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import html
10
+ from dataclasses import dataclass
11
+ from typing import TYPE_CHECKING
12
+
13
+ from kstlib.monitoring._styles import STATUS_CSS_CLASSES, inline_badge_style
14
+
15
+ if TYPE_CHECKING:
16
+ from kstlib.monitoring.types import StatusLevel
17
+
18
+
19
+ @dataclass(frozen=True, slots=True)
20
+ class StatusCell:
21
+ """A colored status badge rendered as an HTML ``<span>``.
22
+
23
+ Attributes:
24
+ label: Display text for the badge (e.g. "UP", "DOWN", "DEGRADED").
25
+ level: Severity level controlling badge color.
26
+
27
+ Examples:
28
+ >>> from kstlib.monitoring.cell import StatusCell
29
+ >>> from kstlib.monitoring.types import StatusLevel
30
+ >>> cell = StatusCell("UP", StatusLevel.OK)
31
+ >>> "<span" in cell.render()
32
+ True
33
+ """
34
+
35
+ label: str
36
+ level: StatusLevel
37
+
38
+ def render(self, *, inline_css: bool = False) -> str:
39
+ """Render the status badge as an HTML ``<span>``.
40
+
41
+ Args:
42
+ inline_css: If True, use inline styles instead of CSS classes.
43
+
44
+ Returns:
45
+ HTML ``<span>`` string.
46
+ """
47
+ escaped = html.escape(self.label)
48
+ if inline_css:
49
+ style = inline_badge_style(self.level)
50
+ return f'<span style="{style}">{escaped}</span>'
51
+ cls = STATUS_CSS_CLASSES[self.level]
52
+ return f'<span class="{cls}">{escaped}</span>'
53
+
54
+
55
+ __all__ = [
56
+ "StatusCell",
57
+ ]