command_watcher 0.4.1__tar.gz → 0.5.0__tar.gz
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.
- {command_watcher-0.4.1 → command_watcher-0.5.0}/PKG-INFO +2 -3
- {command_watcher-0.4.1 → command_watcher-0.5.0}/command_watcher/__init__.py +4 -7
- {command_watcher-0.4.1 → command_watcher-0.5.0}/command_watcher/email.py +2 -2
- {command_watcher-0.4.1 → command_watcher-0.5.0}/command_watcher/log.py +2 -4
- {command_watcher-0.4.1 → command_watcher-0.5.0}/command_watcher/report.py +38 -23
- {command_watcher-0.4.1 → command_watcher-0.5.0}/pyproject.toml +2 -3
- command_watcher-0.4.1/command_watcher/icinga.py +0 -42
- {command_watcher-0.4.1 → command_watcher-0.5.0}/LICENSE +0 -0
- {command_watcher-0.4.1 → command_watcher-0.5.0}/README.rst +0 -0
- {command_watcher-0.4.1 → command_watcher-0.5.0}/command_watcher/py.typed +0 -0
- {command_watcher-0.4.1 → command_watcher-0.5.0}/command_watcher/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: command_watcher
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Module to watch the execution of shell scripts. Both streams (`stdout` and `stderr`) are captured.
|
|
5
5
|
Home-page: https://github.com/Josef-Friedrich/command-watcher
|
|
6
6
|
License: MIT
|
|
@@ -15,8 +15,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
17
|
Requires-Dist: conf2levels (>=0,<1)
|
|
18
|
-
Requires-Dist:
|
|
19
|
-
Requires-Dist: icinga2apic-stubs (>=0,<1)
|
|
18
|
+
Requires-Dist: pretiac (>=0,<1)
|
|
20
19
|
Requires-Dist: termcolor (>=1,<2)
|
|
21
20
|
Requires-Dist: types-requests (>=2,<3)
|
|
22
21
|
Requires-Dist: types-termcolor (>=1,<2)
|
|
@@ -316,7 +316,7 @@ class Watch:
|
|
|
316
316
|
"""
|
|
317
317
|
|
|
318
318
|
_hostname: str
|
|
319
|
-
"""The hostname of machine the watcher running on."""
|
|
319
|
+
"""The hostname of machine the watcher is running on."""
|
|
320
320
|
|
|
321
321
|
_service_name: str
|
|
322
322
|
"""A name of the watched service."""
|
|
@@ -345,7 +345,7 @@ class Watch:
|
|
|
345
345
|
raise_exceptions: bool = True,
|
|
346
346
|
config_reader: Optional[ConfigReader] = None,
|
|
347
347
|
report_channels: Optional[List[BaseChannel]] = None,
|
|
348
|
-
):
|
|
348
|
+
) -> None:
|
|
349
349
|
self._hostname = HOSTNAME
|
|
350
350
|
|
|
351
351
|
self._service_name = service_name
|
|
@@ -390,9 +390,6 @@ class Watch:
|
|
|
390
390
|
try:
|
|
391
391
|
config_reader.check_section("icinga")
|
|
392
392
|
icinga_reporter = IcingaChannel(
|
|
393
|
-
url=self._conf.icinga.url,
|
|
394
|
-
user=self._conf.icinga.user,
|
|
395
|
-
password=self._conf.icinga.password,
|
|
396
393
|
service_name=self._service_name,
|
|
397
394
|
)
|
|
398
395
|
reporter.add_channel(icinga_reporter)
|
|
@@ -415,12 +412,12 @@ class Watch:
|
|
|
415
412
|
self._timer = Timer()
|
|
416
413
|
|
|
417
414
|
@property
|
|
418
|
-
def stdout(self):
|
|
415
|
+
def stdout(self) -> str:
|
|
419
416
|
"""Alias / shortcut for `self._log_handler.stdout`."""
|
|
420
417
|
return self._log_handler.stdout
|
|
421
418
|
|
|
422
419
|
@property
|
|
423
|
-
def stderr(self):
|
|
420
|
+
def stderr(self) -> str:
|
|
424
421
|
"""Alias / shortcut for `self._log_handler.stderr`."""
|
|
425
422
|
return self._log_handler.stderr
|
|
426
423
|
|
|
@@ -12,7 +12,7 @@ def send_email(
|
|
|
12
12
|
smtp_login: str,
|
|
13
13
|
smtp_password: str,
|
|
14
14
|
smtp_server: str,
|
|
15
|
-
):
|
|
15
|
+
) -> dict[str, tuple[int, bytes]]:
|
|
16
16
|
"""
|
|
17
17
|
Send a email.
|
|
18
18
|
|
|
@@ -29,7 +29,7 @@ def send_email(
|
|
|
29
29
|
"""
|
|
30
30
|
message = MIMEText(body, "plain", "utf-8")
|
|
31
31
|
|
|
32
|
-
message["Subject"] = Header(subject, "utf-8")
|
|
32
|
+
message["Subject"] = str(Header(subject, "utf-8"))
|
|
33
33
|
message["From"] = from_addr
|
|
34
34
|
message["To"] = to_addr
|
|
35
35
|
message["Date"] = formatdate(localtime=True)
|
|
@@ -136,11 +136,9 @@ class LoggingHandler(BufferingHandler):
|
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
class ExtendedLogger(logging.Logger):
|
|
139
|
-
def stdout(self, line: object, *args: Any, **kws: Any) -> None:
|
|
140
|
-
...
|
|
139
|
+
def stdout(self, line: object, *args: Any, **kws: Any) -> None: ...
|
|
141
140
|
|
|
142
|
-
def stderr(self, line: object, *args: Any, **kws: Any) -> None:
|
|
143
|
-
...
|
|
141
|
+
def stderr(self, line: object, *args: Any, **kws: Any) -> None: ...
|
|
144
142
|
|
|
145
143
|
|
|
146
144
|
def _log_stdout(self: ExtendedLogger, message: object, *args: Any, **kws: Any) -> None:
|
|
@@ -7,9 +7,10 @@ import subprocess
|
|
|
7
7
|
import textwrap
|
|
8
8
|
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, TypedDict, Union
|
|
9
9
|
|
|
10
|
+
from pretiac import Client as PretiacClient
|
|
11
|
+
from pretiac import get_default_client
|
|
10
12
|
from typing_extensions import Unpack
|
|
11
13
|
|
|
12
|
-
from . import icinga
|
|
13
14
|
from .email import send_email
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
@@ -59,6 +60,9 @@ class MessageParams(MinimalMessageParams, total=False):
|
|
|
59
60
|
service_name: str
|
|
60
61
|
"""The name of the service."""
|
|
61
62
|
|
|
63
|
+
service_display_name: str
|
|
64
|
+
"""The human readable version of a service name."""
|
|
65
|
+
|
|
62
66
|
log_records: str
|
|
63
67
|
"""Log records separated by new lines"""
|
|
64
68
|
|
|
@@ -73,10 +77,10 @@ class Message(BaseClass):
|
|
|
73
77
|
|
|
74
78
|
_data: MessageParams
|
|
75
79
|
|
|
76
|
-
def __init__(self, **data: Unpack[MessageParams]):
|
|
80
|
+
def __init__(self, **data: Unpack[MessageParams]) -> None:
|
|
77
81
|
self._data = data
|
|
78
82
|
|
|
79
|
-
def __str__(self):
|
|
83
|
+
def __str__(self) -> str:
|
|
80
84
|
return self._obj_to_str()
|
|
81
85
|
|
|
82
86
|
@property
|
|
@@ -88,12 +92,23 @@ class Message(BaseClass):
|
|
|
88
92
|
@property
|
|
89
93
|
def status_text(self) -> str:
|
|
90
94
|
"""The status as a text word like `OK`."""
|
|
91
|
-
|
|
95
|
+
if self.status == 0:
|
|
96
|
+
return "OK"
|
|
97
|
+
elif self.status == 1:
|
|
98
|
+
return "WARNING"
|
|
99
|
+
elif self.status == 2:
|
|
100
|
+
return "CRITICAL"
|
|
101
|
+
else:
|
|
102
|
+
return "UNKNOWN"
|
|
92
103
|
|
|
93
104
|
@property
|
|
94
105
|
def service_name(self) -> str:
|
|
95
106
|
return self._data.get("service_name", "service_not_set")
|
|
96
107
|
|
|
108
|
+
@property
|
|
109
|
+
def service_display_name(self) -> str | None:
|
|
110
|
+
return self._data.get("service_display_name", None)
|
|
111
|
+
|
|
97
112
|
@property
|
|
98
113
|
def performance_data(self) -> str:
|
|
99
114
|
"""
|
|
@@ -248,32 +263,32 @@ class EmailChannel(BaseChannel):
|
|
|
248
263
|
|
|
249
264
|
|
|
250
265
|
class IcingaChannel(BaseChannel):
|
|
251
|
-
url: str
|
|
252
|
-
user: str
|
|
253
|
-
password: str
|
|
254
266
|
service_name: str
|
|
255
267
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
self
|
|
268
|
+
client: PretiacClient
|
|
269
|
+
|
|
270
|
+
def __init__(
|
|
271
|
+
self,
|
|
272
|
+
service_name: str,
|
|
273
|
+
) -> None:
|
|
260
274
|
self.service_name = service_name
|
|
275
|
+
self.client = get_default_client()
|
|
261
276
|
|
|
262
277
|
def __str__(self) -> str:
|
|
263
|
-
|
|
264
|
-
return self._obj_to_str(["url", "user", "service_name"])
|
|
278
|
+
return "external configured icinga2 api client"
|
|
265
279
|
|
|
266
280
|
def report(self, message: Message) -> None:
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
281
|
+
try:
|
|
282
|
+
self.client.send_service_check_result(
|
|
283
|
+
service=message.service_name,
|
|
284
|
+
host=HOSTNAME,
|
|
285
|
+
exit_status=message.status,
|
|
286
|
+
plugin_output=message.message,
|
|
287
|
+
performance_data=message.performance_data,
|
|
288
|
+
display_name=message.service_display_name,
|
|
289
|
+
)
|
|
290
|
+
except Exception:
|
|
291
|
+
print("sending to icinga failed")
|
|
277
292
|
|
|
278
293
|
|
|
279
294
|
class BeepChannel(BaseChannel):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "command_watcher"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.0"
|
|
4
4
|
description = "Module to watch the execution of shell scripts. Both streams (`stdout` and `stderr`) are captured."
|
|
5
5
|
authors = ["Josef Friedrich <josef@friedrich.rocks>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -18,11 +18,10 @@ classifiers = [
|
|
|
18
18
|
[tool.poetry.dependencies]
|
|
19
19
|
python = "^3.10"
|
|
20
20
|
conf2levels = "^0"
|
|
21
|
-
icinga2apic = "^0"
|
|
22
21
|
termcolor = "^1"
|
|
23
22
|
types-requests = "^2"
|
|
24
23
|
types-termcolor = "^1"
|
|
25
|
-
|
|
24
|
+
pretiac = "^0"
|
|
26
25
|
|
|
27
26
|
[tool.poetry.group.dev.dependencies]
|
|
28
27
|
pytest = "^8"
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
from typing import Literal, Optional
|
|
2
|
-
|
|
3
|
-
import urllib3
|
|
4
|
-
from icinga2apic.client import Client
|
|
5
|
-
|
|
6
|
-
urllib3.disable_warnings() # type: ignore
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
STATE_OK = 0
|
|
10
|
-
STATE_WARNING = 1
|
|
11
|
-
STATE_CRITICAL = 2
|
|
12
|
-
STATE_UNKNOWN = 3
|
|
13
|
-
|
|
14
|
-
States = {
|
|
15
|
-
STATE_OK: "OK",
|
|
16
|
-
STATE_WARNING: "WARNING",
|
|
17
|
-
STATE_CRITICAL: "CRITICAL",
|
|
18
|
-
STATE_UNKNOWN: "UNKNOWN",
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def send_passive_check(
|
|
23
|
-
url: str,
|
|
24
|
-
user: str,
|
|
25
|
-
password: str,
|
|
26
|
-
status: Literal[0, 1, 2, 3],
|
|
27
|
-
host_name: str,
|
|
28
|
-
service_name: str,
|
|
29
|
-
text_output: str,
|
|
30
|
-
performance_data: Optional[str] = None,
|
|
31
|
-
):
|
|
32
|
-
"""
|
|
33
|
-
https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#process-check-result
|
|
34
|
-
"""
|
|
35
|
-
client = Client(url=url, username=user, password=password)
|
|
36
|
-
return client.actions.process_check_result(
|
|
37
|
-
object_type="Service",
|
|
38
|
-
name="{}!{}".format(host_name, service_name),
|
|
39
|
-
exit_status=status,
|
|
40
|
-
plugin_output=text_output,
|
|
41
|
-
performance_data=performance_data,
|
|
42
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|