ominfra 0.0.0.dev119__tar.gz → 0.0.0.dev121__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. {ominfra-0.0.0.dev119/ominfra.egg-info → ominfra-0.0.0.dev121}/PKG-INFO +3 -3
  2. ominfra-0.0.0.dev121/ominfra/clouds/aws/journald2aws/__main__.py +4 -0
  3. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/journald2aws/driver.py +34 -13
  4. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/journald2aws/main.py +2 -5
  5. ominfra-0.0.0.dev121/ominfra/configs.py +70 -0
  6. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/_executor.py +1 -1
  7. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/_main.py +1 -1
  8. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/pyremote/_runcommands.py +1 -1
  9. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/scripts/journald2aws.py +994 -26
  10. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/scripts/supervisor.py +1969 -262
  11. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/compat.py +13 -0
  12. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/configs.py +21 -0
  13. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/context.py +13 -2
  14. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/dispatchers.py +4 -4
  15. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/events.py +4 -7
  16. ominfra-0.0.0.dev121/ominfra/supervisor/main.py +139 -0
  17. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/process.py +46 -10
  18. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/supervisor.py +118 -88
  19. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/types.py +5 -0
  20. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/threadworkers.py +66 -9
  21. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121/ominfra.egg-info}/PKG-INFO +3 -3
  22. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra.egg-info/SOURCES.txt +2 -0
  23. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra.egg-info/requires.txt +2 -2
  24. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/pyproject.toml +3 -3
  25. ominfra-0.0.0.dev119/ominfra/supervisor/main.py +0 -68
  26. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/LICENSE +0 -0
  27. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/MANIFEST.in +0 -0
  28. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/README.rst +0 -0
  29. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/.manifests.json +0 -0
  30. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/__about__.py +0 -0
  31. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/__init__.py +0 -0
  32. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/__init__.py +0 -0
  33. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/__init__.py +0 -0
  34. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/__main__.py +0 -0
  35. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/auth.py +0 -0
  36. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/cli.py +0 -0
  37. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/dataclasses.py +0 -0
  38. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  39. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  40. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  41. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/logs.py +0 -0
  42. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/aws/metadata.py +0 -0
  43. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/gcp/__init__.py +0 -0
  44. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/clouds/gcp/auth.py +0 -0
  45. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/cmds.py +0 -0
  46. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/__init__.py +0 -0
  47. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/configs.py +0 -0
  48. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/__init__.py +0 -0
  49. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/base.py +0 -0
  50. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/concerns/__init__.py +0 -0
  51. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/concerns/dirs.py +0 -0
  52. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/concerns/nginx.py +0 -0
  53. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/concerns/repo.py +0 -0
  54. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/concerns/supervisor.py +0 -0
  55. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/concerns/systemd.py +0 -0
  56. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/concerns/user.py +0 -0
  57. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/concerns/venv.py +0 -0
  58. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/executor/main.py +0 -0
  59. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/__init__.py +0 -0
  60. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/base.py +0 -0
  61. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/configs.py +0 -0
  62. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/deploy.py +0 -0
  63. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/main.py +0 -0
  64. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/nginx.py +0 -0
  65. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/repo.py +0 -0
  66. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/runtime.py +0 -0
  67. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/site.py +0 -0
  68. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/supervisor.py +0 -0
  69. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/poly/venv.py +0 -0
  70. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/deploy/remote.py +0 -0
  71. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/journald/__init__.py +0 -0
  72. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/journald/fields.py +0 -0
  73. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/journald/genmessages.py +0 -0
  74. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/journald/messages.py +0 -0
  75. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/journald/tailer.py +0 -0
  76. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/manage/__init__.py +0 -0
  77. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/manage/manage.py +0 -0
  78. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/pyremote/__init__.py +0 -0
  79. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/pyremote/bootstrap.py +0 -0
  80. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/pyremote/runcommands.py +0 -0
  81. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/scripts/__init__.py +0 -0
  82. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/ssh.py +0 -0
  83. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/__init__.py +0 -0
  84. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/__main__.py +0 -0
  85. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/datatypes.py +0 -0
  86. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/exceptions.py +0 -0
  87. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/poller.py +0 -0
  88. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/supervisor/states.py +0 -0
  89. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/tailscale/__init__.py +0 -0
  90. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/tailscale/api.py +0 -0
  91. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/tailscale/cli.py +0 -0
  92. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/tools/__init__.py +0 -0
  93. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra/tools/listresources.py +0 -0
  94. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra.egg-info/dependency_links.txt +0 -0
  95. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra.egg-info/entry_points.txt +0 -0
  96. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/ominfra.egg-info/top_level.txt +0 -0
  97. {ominfra-0.0.0.dev119 → ominfra-0.0.0.dev121}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev119
3
+ Version: 0.0.0.dev121
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,8 +12,8 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Operating System :: POSIX
13
13
  Requires-Python: >=3.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omdev==0.0.0.dev119
16
- Requires-Dist: omlish==0.0.0.dev119
15
+ Requires-Dist: omdev==0.0.0.dev121
16
+ Requires-Dist: omlish==0.0.0.dev121
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -0,0 +1,4 @@
1
+ if __name__ == '__main__':
2
+ from .main import _main
3
+
4
+ _main()
@@ -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 run(self) -> None:
186
- pw: JournalctlToAwsPosterWorker = self._aws_poster_worker()
187
- tw: JournalctlTailerWorker = self._journalctl_tailer_worker()
197
+ def _exit_contexts(self) -> None:
198
+ wg = self._worker_group()
199
+ wg.stop_all()
200
+ wg.join_all()
188
201
 
189
- ws = [pw, tw]
202
+ def run(self) -> None:
203
+ self._aws_poster_worker()
204
+ self._journalctl_tailer_worker()
190
205
 
191
- for w in ws:
192
- w.start()
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 ws:
198
- if not w.is_alive():
199
- log.critical('Worker died: %r', w)
200
- break
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
- for w in reversed(ws):
209
- w.stop()
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
- with open(os.path.expanduser(args.config_file)) as cf:
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
 
@@ -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
@@ -129,7 +129,7 @@ class _cached_nullary: # noqa
129
129
  return bound
130
130
 
131
131
 
132
- def cached_nullary(fn: ta.Callable[..., T]) -> ta.Callable[..., T]:
132
+ def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
133
133
  return _cached_nullary(fn)
134
134
 
135
135
 
@@ -103,7 +103,7 @@ class _cached_nullary: # noqa
103
103
  return bound
104
104
 
105
105
 
106
- def cached_nullary(fn: ta.Callable[..., T]) -> ta.Callable[..., T]:
106
+ def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
107
107
  return _cached_nullary(fn)
108
108
 
109
109
 
@@ -212,7 +212,7 @@ class _cached_nullary: # noqa
212
212
  return bound
213
213
 
214
214
 
215
- def cached_nullary(fn: ta.Callable[..., T]) -> ta.Callable[..., T]:
215
+ def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
216
216
  return _cached_nullary(fn)
217
217
 
218
218