ominfra 0.0.0.dev120__py3-none-any.whl → 0.0.0.dev121__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.
- ominfra/clouds/aws/journald2aws/__main__.py +4 -0
- ominfra/clouds/aws/journald2aws/driver.py +34 -13
- ominfra/clouds/aws/journald2aws/main.py +2 -5
- ominfra/configs.py +70 -0
- ominfra/deploy/_executor.py +1 -1
- ominfra/deploy/poly/_main.py +1 -1
- ominfra/pyremote/_runcommands.py +1 -1
- ominfra/scripts/journald2aws.py +994 -26
- ominfra/scripts/supervisor.py +1836 -138
- ominfra/supervisor/compat.py +13 -0
- ominfra/supervisor/configs.py +21 -0
- ominfra/supervisor/context.py +13 -2
- ominfra/supervisor/main.py +82 -11
- ominfra/supervisor/process.py +39 -4
- ominfra/supervisor/supervisor.py +23 -2
- ominfra/supervisor/types.py +5 -0
- ominfra/threadworkers.py +66 -9
- {ominfra-0.0.0.dev120.dist-info → ominfra-0.0.0.dev121.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev120.dist-info → ominfra-0.0.0.dev121.dist-info}/RECORD +23 -21
- {ominfra-0.0.0.dev120.dist-info → ominfra-0.0.0.dev121.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev120.dist-info → ominfra-0.0.0.dev121.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev120.dist-info → ominfra-0.0.0.dev121.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev120.dist-info → ominfra-0.0.0.dev121.dist-info}/top_level.txt +0 -0
@@ -46,6 +46,7 @@ from omlish.lite.runtime import is_debugger_attached
|
|
46
46
|
|
47
47
|
from ....journald.messages import JournalctlMessage # noqa
|
48
48
|
from ....journald.tailer import JournalctlTailerWorker
|
49
|
+
from ....threadworkers import ThreadWorkerGroup
|
49
50
|
from ..auth import AwsSigner
|
50
51
|
from ..logs import AwsLogMessageBuilder
|
51
52
|
from .cursor import JournalctlToAwsCursor
|
@@ -63,6 +64,7 @@ class JournalctlToAwsDriver(ExitStacked):
|
|
63
64
|
cursor_file: ta.Optional[str] = None
|
64
65
|
|
65
66
|
runtime_limit: ta.Optional[float] = None
|
67
|
+
heartbeat_age_limit: ta.Optional[float] = 60.
|
66
68
|
|
67
69
|
#
|
68
70
|
|
@@ -139,6 +141,12 @@ class JournalctlToAwsDriver(ExitStacked):
|
|
139
141
|
|
140
142
|
#
|
141
143
|
|
144
|
+
@cached_nullary
|
145
|
+
def _worker_group(self) -> ThreadWorkerGroup:
|
146
|
+
return ThreadWorkerGroup()
|
147
|
+
|
148
|
+
#
|
149
|
+
|
142
150
|
@cached_nullary
|
143
151
|
def _journalctl_message_queue(self): # type: () -> queue.Queue[ta.Sequence[JournalctlMessage]]
|
144
152
|
return queue.Queue()
|
@@ -165,6 +173,8 @@ class JournalctlToAwsDriver(ExitStacked):
|
|
165
173
|
|
166
174
|
cmd=self._config.journalctl_cmd,
|
167
175
|
shell_wrap=is_debugger_attached(),
|
176
|
+
|
177
|
+
worker_groups=[self._worker_group()],
|
168
178
|
)
|
169
179
|
|
170
180
|
#
|
@@ -178,26 +188,38 @@ class JournalctlToAwsDriver(ExitStacked):
|
|
178
188
|
|
179
189
|
ensure_locked=self._ensure_locked,
|
180
190
|
dry_run=self._config.aws_dry_run,
|
191
|
+
|
192
|
+
worker_groups=[self._worker_group()],
|
181
193
|
)
|
182
194
|
|
183
195
|
#
|
184
196
|
|
185
|
-
def
|
186
|
-
|
187
|
-
|
197
|
+
def _exit_contexts(self) -> None:
|
198
|
+
wg = self._worker_group()
|
199
|
+
wg.stop_all()
|
200
|
+
wg.join_all()
|
188
201
|
|
189
|
-
|
202
|
+
def run(self) -> None:
|
203
|
+
self._aws_poster_worker()
|
204
|
+
self._journalctl_tailer_worker()
|
190
205
|
|
191
|
-
|
192
|
-
|
206
|
+
wg = self._worker_group()
|
207
|
+
wg.start_all()
|
193
208
|
|
194
209
|
start = time.time()
|
195
210
|
|
196
211
|
while True:
|
197
|
-
for w in
|
198
|
-
|
199
|
-
|
200
|
-
|
212
|
+
for w in wg.get_dead():
|
213
|
+
log.critical('Worker died: %r', w)
|
214
|
+
break
|
215
|
+
|
216
|
+
if (al := self._config.heartbeat_age_limit) is not None:
|
217
|
+
hbs = wg.check_heartbeats()
|
218
|
+
log.debug('Worker heartbeats: %r', hbs)
|
219
|
+
for w, age in hbs.items():
|
220
|
+
if age > al:
|
221
|
+
log.critical('Worker heartbeat age limit exceeded: %r %f > %f', w, age, al)
|
222
|
+
break
|
201
223
|
|
202
224
|
if (rl := self._config.runtime_limit) is not None and time.time() - start >= rl:
|
203
225
|
log.warning('Runtime limit reached')
|
@@ -205,6 +227,5 @@ class JournalctlToAwsDriver(ExitStacked):
|
|
205
227
|
|
206
228
|
time.sleep(1.)
|
207
229
|
|
208
|
-
|
209
|
-
|
210
|
-
w.join()
|
230
|
+
wg.stop_all()
|
231
|
+
wg.join_all()
|
@@ -2,13 +2,12 @@
|
|
2
2
|
# @omlish-amalg ../../../scripts/journald2aws.py
|
3
3
|
import argparse
|
4
4
|
import dataclasses as dc
|
5
|
-
import json
|
6
5
|
import os.path
|
7
6
|
import sys
|
8
7
|
|
9
8
|
from omlish.lite.logs import configure_standard_logging
|
10
|
-
from omlish.lite.marshal import unmarshal_obj
|
11
9
|
|
10
|
+
from ....configs import read_config_file
|
12
11
|
from .driver import JournalctlToAwsDriver
|
13
12
|
|
14
13
|
|
@@ -37,9 +36,7 @@ def _main() -> None:
|
|
37
36
|
|
38
37
|
config: JournalctlToAwsDriver.Config
|
39
38
|
if args.config_file:
|
40
|
-
|
41
|
-
config_dct = json.load(cf)
|
42
|
-
config = unmarshal_obj(config_dct, JournalctlToAwsDriver.Config)
|
39
|
+
config = read_config_file(os.path.expanduser(args.config_file), JournalctlToAwsDriver.Config)
|
43
40
|
else:
|
44
41
|
config = JournalctlToAwsDriver.Config()
|
45
42
|
|
ominfra/configs.py
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
# @omlish-lite
|
3
|
+
import json
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
from omdev.toml.parser import toml_loads
|
7
|
+
from omlish.lite.check import check_isinstance
|
8
|
+
from omlish.lite.check import check_not_isinstance
|
9
|
+
from omlish.lite.marshal import unmarshal_obj
|
10
|
+
|
11
|
+
|
12
|
+
T = ta.TypeVar('T')
|
13
|
+
|
14
|
+
ConfigMapping = ta.Mapping[str, ta.Any]
|
15
|
+
|
16
|
+
|
17
|
+
def read_config_file(
|
18
|
+
path: str,
|
19
|
+
cls: ta.Type[T],
|
20
|
+
*,
|
21
|
+
prepare: ta.Optional[ta.Callable[[ConfigMapping], ConfigMapping]] = None,
|
22
|
+
) -> T:
|
23
|
+
with open(path) as cf:
|
24
|
+
if path.endswith('.toml'):
|
25
|
+
config_dct = toml_loads(cf.read())
|
26
|
+
else:
|
27
|
+
config_dct = json.loads(cf.read())
|
28
|
+
|
29
|
+
if prepare is not None:
|
30
|
+
config_dct = prepare(config_dct) # type: ignore
|
31
|
+
|
32
|
+
return unmarshal_obj(config_dct, cls)
|
33
|
+
|
34
|
+
|
35
|
+
def build_config_named_children(
|
36
|
+
o: ta.Union[
|
37
|
+
ta.Sequence[ConfigMapping],
|
38
|
+
ta.Mapping[str, ConfigMapping],
|
39
|
+
None,
|
40
|
+
],
|
41
|
+
*,
|
42
|
+
name_key: str = 'name',
|
43
|
+
) -> ta.Optional[ta.Sequence[ConfigMapping]]:
|
44
|
+
if o is None:
|
45
|
+
return None
|
46
|
+
|
47
|
+
lst: ta.List[ConfigMapping] = []
|
48
|
+
if isinstance(o, ta.Mapping):
|
49
|
+
for k, v in o.items():
|
50
|
+
check_isinstance(v, ta.Mapping)
|
51
|
+
if name_key in v:
|
52
|
+
n = v[name_key]
|
53
|
+
if k != n:
|
54
|
+
raise KeyError(f'Given names do not match: {n} != {k}')
|
55
|
+
lst.append(v)
|
56
|
+
else:
|
57
|
+
lst.append({name_key: k, **v})
|
58
|
+
|
59
|
+
else:
|
60
|
+
check_not_isinstance(o, str)
|
61
|
+
lst.extend(o)
|
62
|
+
|
63
|
+
seen = set()
|
64
|
+
for d in lst:
|
65
|
+
n = d['name']
|
66
|
+
if n in d:
|
67
|
+
raise KeyError(f'Duplicate name: {n}')
|
68
|
+
seen.add(n)
|
69
|
+
|
70
|
+
return lst
|
ominfra/deploy/_executor.py
CHANGED
ominfra/deploy/poly/_main.py
CHANGED
ominfra/pyremote/_runcommands.py
CHANGED