ominfra 0.0.0.dev120__py3-none-any.whl → 0.0.0.dev121__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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