ominfra 0.0.0.dev132__tar.gz → 0.0.0.dev134__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. {ominfra-0.0.0.dev132/ominfra.egg-info → ominfra-0.0.0.dev134}/PKG-INFO +3 -3
  2. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/_executor.py +10 -10
  3. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/_main.py +6 -6
  4. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/remote.py +1 -1
  5. ominfra-0.0.0.dev134/ominfra/pyremote.py +389 -0
  6. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/scripts/supervisor.py +1 -1
  7. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/http.py +1 -1
  8. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134/ominfra.egg-info}/PKG-INFO +3 -3
  9. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra.egg-info/SOURCES.txt +28 -31
  10. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra.egg-info/requires.txt +2 -2
  11. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/pyproject.toml +3 -3
  12. ominfra-0.0.0.dev132/ominfra/pyremote/_runcommands.py +0 -1201
  13. ominfra-0.0.0.dev132/ominfra/pyremote/bootstrap.py +0 -149
  14. ominfra-0.0.0.dev132/ominfra/pyremote/runcommands.py +0 -56
  15. ominfra-0.0.0.dev132/ominfra/tools/__init__.py +0 -0
  16. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/LICENSE +0 -0
  17. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/MANIFEST.in +0 -0
  18. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/README.rst +0 -0
  19. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/.manifests.json +0 -0
  20. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/__about__.py +0 -0
  21. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/__init__.py +0 -0
  22. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/__init__.py +0 -0
  23. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/__init__.py +0 -0
  24. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/__main__.py +0 -0
  25. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/auth.py +0 -0
  26. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/cli.py +0 -0
  27. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/dataclasses.py +0 -0
  28. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  29. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  30. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  31. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/journald2aws/driver.py +0 -0
  32. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/journald2aws/main.py +0 -0
  33. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  34. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/logs.py +0 -0
  35. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/aws/metadata.py +0 -0
  36. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/gcp/__init__.py +0 -0
  37. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/clouds/gcp/auth.py +0 -0
  38. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/cmds.py +0 -0
  39. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/configs.py +0 -0
  40. {ominfra-0.0.0.dev132/ominfra/deploy → ominfra-0.0.0.dev134/ominfra/journald}/__init__.py +0 -0
  41. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/journald/fields.py +0 -0
  42. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/journald/genmessages.py +0 -0
  43. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/journald/messages.py +0 -0
  44. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/journald/tailer.py +0 -0
  45. {ominfra-0.0.0.dev132/ominfra/deploy/executor/concerns → ominfra-0.0.0.dev134/ominfra/manage}/__init__.py +0 -0
  46. {ominfra-0.0.0.dev132/ominfra/journald → ominfra-0.0.0.dev134/ominfra/manage/deploy}/__init__.py +0 -0
  47. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/configs.py +0 -0
  48. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/__init__.py +0 -0
  49. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/base.py +0 -0
  50. {ominfra-0.0.0.dev132/ominfra/manage → ominfra-0.0.0.dev134/ominfra/manage/deploy/executor/concerns}/__init__.py +0 -0
  51. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/concerns/dirs.py +0 -0
  52. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/concerns/nginx.py +0 -0
  53. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/concerns/repo.py +0 -0
  54. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/concerns/supervisor.py +0 -0
  55. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/concerns/systemd.py +0 -0
  56. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/concerns/user.py +0 -0
  57. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/concerns/venv.py +0 -0
  58. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/executor/main.py +0 -0
  59. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/__init__.py +0 -0
  60. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/base.py +0 -0
  61. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/configs.py +0 -0
  62. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/deploy.py +0 -0
  63. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/main.py +0 -0
  64. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/nginx.py +0 -0
  65. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/repo.py +0 -0
  66. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/runtime.py +0 -0
  67. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/site.py +0 -0
  68. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/supervisor.py +0 -0
  69. {ominfra-0.0.0.dev132/ominfra → ominfra-0.0.0.dev134/ominfra/manage}/deploy/poly/venv.py +0 -0
  70. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/manage/manage.py +0 -0
  71. {ominfra-0.0.0.dev132/ominfra/pyremote → ominfra-0.0.0.dev134/ominfra/scripts}/__init__.py +0 -0
  72. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/scripts/journald2aws.py +0 -0
  73. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/ssh.py +0 -0
  74. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/LICENSE.txt +0 -0
  75. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/__init__.py +0 -0
  76. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/__main__.py +0 -0
  77. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/configs.py +0 -0
  78. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/dispatchers.py +0 -0
  79. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/dispatchersimpl.py +0 -0
  80. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/events.py +0 -0
  81. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/exceptions.py +0 -0
  82. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/groups.py +0 -0
  83. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/groupsimpl.py +0 -0
  84. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/inject.py +0 -0
  85. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/io.py +0 -0
  86. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/main.py +0 -0
  87. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/pipes.py +0 -0
  88. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/privileges.py +0 -0
  89. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/process.py +0 -0
  90. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/processimpl.py +0 -0
  91. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/setup.py +0 -0
  92. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/setupimpl.py +0 -0
  93. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/signals.py +0 -0
  94. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/spawning.py +0 -0
  95. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/spawningimpl.py +0 -0
  96. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/states.py +0 -0
  97. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/supervisor.py +0 -0
  98. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/types.py +0 -0
  99. {ominfra-0.0.0.dev132/ominfra/scripts → ominfra-0.0.0.dev134/ominfra/supervisor/utils}/__init__.py +0 -0
  100. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/collections.py +0 -0
  101. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/diag.py +0 -0
  102. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/fds.py +0 -0
  103. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/fs.py +0 -0
  104. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/os.py +0 -0
  105. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/ostypes.py +0 -0
  106. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/signals.py +0 -0
  107. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/strings.py +0 -0
  108. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/supervisor/utils/users.py +0 -0
  109. {ominfra-0.0.0.dev132/ominfra/supervisor/utils → ominfra-0.0.0.dev134/ominfra/tailscale}/__init__.py +0 -0
  110. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/tailscale/api.py +0 -0
  111. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/tailscale/cli.py +0 -0
  112. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/threadworkers.py +0 -0
  113. {ominfra-0.0.0.dev132/ominfra/tailscale → ominfra-0.0.0.dev134/ominfra/tools}/__init__.py +0 -0
  114. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra/tools/listresources.py +0 -0
  115. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra.egg-info/dependency_links.txt +0 -0
  116. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra.egg-info/entry_points.txt +0 -0
  117. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/ominfra.egg-info/top_level.txt +0 -0
  118. {ominfra-0.0.0.dev132 → ominfra-0.0.0.dev134}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev132
3
+ Version: 0.0.0.dev134
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.dev132
16
- Requires-Dist: omlish==0.0.0.dev132
15
+ Requires-Dist: omdev==0.0.0.dev134
16
+ Requires-Dist: omlish==0.0.0.dev134
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -82,10 +82,10 @@ if sys.version_info < (3, 8):
82
82
  ########################################
83
83
 
84
84
 
85
- # ../../../omlish/lite/cached.py
85
+ # ../../../../omlish/lite/cached.py
86
86
  T = ta.TypeVar('T')
87
87
 
88
- # ../../../omlish/lite/check.py
88
+ # ../../../../omlish/lite/check.py
89
89
  SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
90
90
 
91
91
 
@@ -112,7 +112,7 @@ class HostConfig:
112
112
 
113
113
 
114
114
  ########################################
115
- # ../../../../omlish/lite/cached.py
115
+ # ../../../../../omlish/lite/cached.py
116
116
 
117
117
 
118
118
  class _cached_nullary: # noqa
@@ -137,7 +137,7 @@ def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
137
137
 
138
138
 
139
139
  ########################################
140
- # ../../../../omlish/lite/check.py
140
+ # ../../../../../omlish/lite/check.py
141
141
 
142
142
 
143
143
  def check_isinstance(v: ta.Any, spec: ta.Union[ta.Type[T], tuple]) -> T:
@@ -234,7 +234,7 @@ def check_non_empty(v: SizedT) -> SizedT:
234
234
 
235
235
 
236
236
  ########################################
237
- # ../../../../omlish/lite/json.py
237
+ # ../../../../../omlish/lite/json.py
238
238
 
239
239
 
240
240
  ##
@@ -265,7 +265,7 @@ json_dumps_compact: ta.Callable[..., str] = functools.partial(json.dumps, **JSON
265
265
 
266
266
 
267
267
  ########################################
268
- # ../../../../omlish/lite/reflect.py
268
+ # ../../../../../omlish/lite/reflect.py
269
269
 
270
270
 
271
271
  _GENERIC_ALIAS_TYPES = (
@@ -320,7 +320,7 @@ def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
320
320
 
321
321
 
322
322
  ########################################
323
- # ../../../../omlish/lite/logs.py
323
+ # ../../../../../omlish/lite/logs.py
324
324
  """
325
325
  TODO:
326
326
  - translate json keys
@@ -590,7 +590,7 @@ def configure_standard_logging(
590
590
 
591
591
 
592
592
  ########################################
593
- # ../../../../omlish/lite/marshal.py
593
+ # ../../../../../omlish/lite/marshal.py
594
594
  """
595
595
  TODO:
596
596
  - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
@@ -934,7 +934,7 @@ def unmarshal_obj(o: ta.Any, ty: ta.Union[ta.Type[T], ta.Any]) -> T:
934
934
 
935
935
 
936
936
  ########################################
937
- # ../../../../omlish/lite/runtime.py
937
+ # ../../../../../omlish/lite/runtime.py
938
938
 
939
939
 
940
940
  @cached_nullary
@@ -951,7 +951,7 @@ def check_runtime_version() -> None:
951
951
 
952
952
 
953
953
  ########################################
954
- # ../../../../omlish/lite/subprocesses.py
954
+ # ../../../../../omlish/lite/subprocesses.py
955
955
 
956
956
 
957
957
  ##
@@ -33,7 +33,7 @@ if sys.version_info < (3, 8):
33
33
  ########################################
34
34
 
35
35
 
36
- # ../../../omlish/lite/cached.py
36
+ # ../../../../omlish/lite/cached.py
37
37
  T = ta.TypeVar('T')
38
38
 
39
39
  # base.py
@@ -84,7 +84,7 @@ class DeployConfig:
84
84
 
85
85
 
86
86
  ########################################
87
- # ../../../../omlish/lite/cached.py
87
+ # ../../../../../omlish/lite/cached.py
88
88
 
89
89
 
90
90
  class _cached_nullary: # noqa
@@ -109,7 +109,7 @@ def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
109
109
 
110
110
 
111
111
  ########################################
112
- # ../../../../omlish/lite/json.py
112
+ # ../../../../../omlish/lite/json.py
113
113
 
114
114
 
115
115
  ##
@@ -301,7 +301,7 @@ class Deploy(ConcernsContainer[DeployConcern, DeployConfig]):
301
301
 
302
302
 
303
303
  ########################################
304
- # ../../../../omlish/lite/logs.py
304
+ # ../../../../../omlish/lite/logs.py
305
305
  """
306
306
  TODO:
307
307
  - translate json keys
@@ -571,7 +571,7 @@ def configure_standard_logging(
571
571
 
572
572
 
573
573
  ########################################
574
- # ../../../../omlish/lite/runtime.py
574
+ # ../../../../../omlish/lite/runtime.py
575
575
 
576
576
 
577
577
  @cached_nullary
@@ -708,7 +708,7 @@ class SiteImpl(Site):
708
708
 
709
709
 
710
710
  ########################################
711
- # ../../../../omlish/lite/subprocesses.py
711
+ # ../../../../../omlish/lite/subprocesses.py
712
712
 
713
713
 
714
714
  ##
@@ -23,7 +23,7 @@ import tempfile
23
23
 
24
24
  from omlish import check
25
25
 
26
- from .. import cmds
26
+ from ... import cmds
27
27
 
28
28
 
29
29
  def render_script(*cs: list[str] | tuple[str, ...]) -> str:
@@ -0,0 +1,389 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ """
4
+ Basically this: https://mitogen.networkgenomics.com/howitworks.html
5
+ """
6
+ import base64
7
+ import dataclasses as dc
8
+ import inspect
9
+ import json
10
+ import os
11
+ import platform
12
+ import pwd
13
+ import site
14
+ import struct
15
+ import sys
16
+ import textwrap
17
+ import typing as ta
18
+ import zlib
19
+
20
+
21
+ ##
22
+
23
+
24
+ _PYREMOTE_BOOTSTRAP_COMM_FD = 100
25
+ _PYREMOTE_BOOTSTRAP_SRC_FD = 101
26
+
27
+ _PYREMOTE_BOOTSTRAP_CHILD_PID_VAR = '_OPYR_CPID'
28
+ _PYREMOTE_BOOTSTRAP_ARGV0_VAR = '_OPYR_ARGV0'
29
+
30
+ _PYREMOTE_BOOTSTRAP_ACK0 = b'OPYR000\n'
31
+ _PYREMOTE_BOOTSTRAP_ACK1 = b'OPYR001\n'
32
+ _PYREMOTE_BOOTSTRAP_ACK2 = b'OPYR002\n'
33
+ _PYREMOTE_BOOTSTRAP_ACK3 = b'OPYR003\n'
34
+
35
+ _PYREMOTE_BOOTSTRAP_PROC_TITLE_FMT = '(pyremote:%s)'
36
+
37
+ _PYREMOTE_BOOTSTRAP_IMPORTS = [
38
+ 'base64',
39
+ 'os',
40
+ 'struct',
41
+ 'sys',
42
+ 'zlib',
43
+ ]
44
+
45
+
46
+ def _pyremote_bootstrap_main(context_name: str) -> None:
47
+ # Get pid
48
+ pid = os.getpid()
49
+
50
+ # Two copies of main src to be sent to parent
51
+ r0, w0 = os.pipe()
52
+ r1, w1 = os.pipe()
53
+
54
+ if (cp := os.fork()):
55
+ # Parent process
56
+
57
+ # Dup original stdin to comm_fd for use as comm channel
58
+ os.dup2(0, _PYREMOTE_BOOTSTRAP_COMM_FD)
59
+
60
+ # Overwrite stdin (fed to python repl) with first copy of src
61
+ os.dup2(r0, 0)
62
+
63
+ # Dup second copy of src to src_fd to recover after launch
64
+ os.dup2(r1, _PYREMOTE_BOOTSTRAP_SRC_FD)
65
+
66
+ # Close remaining fd's
67
+ for f in [r0, w0, r1, w1]:
68
+ os.close(f)
69
+
70
+ # Save child pid to close after relaunch
71
+ os.environ[_PYREMOTE_BOOTSTRAP_CHILD_PID_VAR] = str(cp)
72
+
73
+ # Save original argv0
74
+ os.environ[_PYREMOTE_BOOTSTRAP_ARGV0_VAR] = sys.executable
75
+
76
+ # Start repl reading stdin from r0
77
+ os.execl(sys.executable, sys.executable + (_PYREMOTE_BOOTSTRAP_PROC_TITLE_FMT % (context_name,)))
78
+
79
+ else:
80
+ # Child process
81
+
82
+ # Write first ack
83
+ os.write(1, _PYREMOTE_BOOTSTRAP_ACK0)
84
+
85
+ # Write pid
86
+ os.write(1, struct.pack('<Q', pid))
87
+
88
+ # Read main src from stdin
89
+ main_z_len = struct.unpack('<I', os.read(0, 4))[0]
90
+ main_src = zlib.decompress(os.fdopen(0, 'rb').read(main_z_len))
91
+
92
+ # Write both copies of main src. Must write to w0 (parent stdin) before w1 (copy pipe) as pipe will likely fill
93
+ # and block and need to be drained by pyremote_bootstrap_finalize running in parent.
94
+ for w in [w0, w1]:
95
+ fp = os.fdopen(w, 'wb', 0)
96
+ fp.write(main_src)
97
+ fp.close()
98
+
99
+ # Write second ack
100
+ os.write(1, _PYREMOTE_BOOTSTRAP_ACK1)
101
+
102
+ # Exit child
103
+ sys.exit(0)
104
+
105
+
106
+ ##
107
+
108
+
109
+ def pyremote_build_bootstrap_cmd(context_name: str) -> str:
110
+ bs_src = textwrap.dedent(inspect.getsource(_pyremote_bootstrap_main))
111
+
112
+ for gl in [
113
+ '_PYREMOTE_BOOTSTRAP_COMM_FD',
114
+ '_PYREMOTE_BOOTSTRAP_SRC_FD',
115
+
116
+ '_PYREMOTE_BOOTSTRAP_CHILD_PID_VAR',
117
+ '_PYREMOTE_BOOTSTRAP_ARGV0_VAR',
118
+
119
+ '_PYREMOTE_BOOTSTRAP_ACK0',
120
+ '_PYREMOTE_BOOTSTRAP_ACK1',
121
+
122
+ '_PYREMOTE_BOOTSTRAP_PROC_TITLE_FMT',
123
+ ]:
124
+ bs_src = bs_src.replace(gl, repr(globals()[gl]))
125
+
126
+ bs_src = '\n'.join(
127
+ cl
128
+ for l in bs_src.splitlines()
129
+ if (cl := (l.split('#')[0]).rstrip())
130
+ if cl.strip()
131
+ )
132
+
133
+ bs_z = zlib.compress(bs_src.encode('utf-8'))
134
+ bs_z64 = base64.encodebytes(bs_z).replace(b'\n', b'')
135
+
136
+ stmts = [
137
+ f'import {", ".join(_PYREMOTE_BOOTSTRAP_IMPORTS)}',
138
+ f'exec(zlib.decompress(base64.decodebytes({bs_z64!r})))',
139
+ f'_pyremote_bootstrap_main({context_name!r})',
140
+ ]
141
+
142
+ cmd = '; '.join(stmts)
143
+ return cmd
144
+
145
+
146
+ ##
147
+
148
+
149
+ @dc.dataclass(frozen=True)
150
+ class PyremoteEnvInfo:
151
+ sys_base_prefix: str
152
+ sys_byteorder: str
153
+ sys_defaultencoding: str
154
+ sys_exec_prefix: str
155
+ sys_executable: str
156
+ sys_implementation_name: str
157
+ sys_path: ta.List[str]
158
+ sys_platform: str
159
+ sys_prefix: str
160
+ sys_version: str
161
+ sys_version_info: ta.List[ta.Union[int, str]]
162
+
163
+ platform_architecture: ta.List[str]
164
+ platform_machine: str
165
+ platform_platform: str
166
+ platform_processor: str
167
+ platform_system: str
168
+ platform_release: str
169
+ platform_version: str
170
+
171
+ site_userbase: str
172
+
173
+ os_cwd: str
174
+ os_gid: int
175
+ os_loadavg: ta.List[float]
176
+ os_login: ta.Optional[str]
177
+ os_pgrp: int
178
+ os_pid: int
179
+ os_ppid: int
180
+ os_uid: int
181
+
182
+ pw_name: str
183
+ pw_uid: int
184
+ pw_gid: int
185
+ pw_gecos: str
186
+ pw_dir: str
187
+ pw_shell: str
188
+
189
+ env_path: ta.Optional[str]
190
+
191
+
192
+ def _get_pyremote_env_info() -> PyremoteEnvInfo:
193
+ os_uid = os.getuid()
194
+
195
+ pw = pwd.getpwuid(os_uid)
196
+
197
+ os_login: ta.Optional[str]
198
+ try:
199
+ os_login = os.getlogin()
200
+ except OSError:
201
+ os_login = None
202
+
203
+ return PyremoteEnvInfo(
204
+ sys_base_prefix=sys.base_prefix,
205
+ sys_byteorder=sys.byteorder,
206
+ sys_defaultencoding=sys.getdefaultencoding(),
207
+ sys_exec_prefix=sys.exec_prefix,
208
+ sys_executable=sys.executable,
209
+ sys_implementation_name=sys.implementation.name,
210
+ sys_path=sys.path,
211
+ sys_platform=sys.platform,
212
+ sys_prefix=sys.prefix,
213
+ sys_version=sys.version,
214
+ sys_version_info=list(sys.version_info),
215
+
216
+ platform_architecture=list(platform.architecture()),
217
+ platform_machine=platform.machine(),
218
+ platform_platform=platform.platform(),
219
+ platform_processor=platform.processor(),
220
+ platform_system=platform.system(),
221
+ platform_release=platform.release(),
222
+ platform_version=platform.version(),
223
+
224
+ site_userbase=site.getuserbase(),
225
+
226
+ os_cwd=os.getcwd(),
227
+ os_gid=os.getgid(),
228
+ os_loadavg=list(os.getloadavg()),
229
+ os_login=os_login,
230
+ os_pgrp=os.getpgrp(),
231
+ os_pid=os.getpid(),
232
+ os_ppid=os.getppid(),
233
+ os_uid=os_uid,
234
+
235
+ pw_name=pw.pw_name,
236
+ pw_uid=pw.pw_uid,
237
+ pw_gid=pw.pw_gid,
238
+ pw_gecos=pw.pw_gecos,
239
+ pw_dir=pw.pw_dir,
240
+ pw_shell=pw.pw_shell,
241
+
242
+ env_path=os.environ.get('PATH'),
243
+ )
244
+
245
+
246
+ ##
247
+
248
+
249
+ class PyremoteBootstrapDriver:
250
+ def __init__(self, main_src: str) -> None:
251
+ super().__init__()
252
+
253
+ self._main_src = main_src
254
+ self._main_z = zlib.compress(main_src.encode('utf-8'))
255
+
256
+ #
257
+
258
+ @dc.dataclass(frozen=True)
259
+ class Read:
260
+ sz: int
261
+
262
+ @dc.dataclass(frozen=True)
263
+ class Write:
264
+ d: bytes
265
+
266
+ class ProtocolError(Exception):
267
+ pass
268
+
269
+ @dc.dataclass(frozen=True)
270
+ class Result:
271
+ pid: int
272
+ env_info: PyremoteEnvInfo
273
+
274
+ def gen(self) -> ta.Generator[ta.Union[Read, Write], ta.Optional[bytes], Result]:
275
+ # Read first ack
276
+ yield from self._expect(_PYREMOTE_BOOTSTRAP_ACK0)
277
+
278
+ # Read pid
279
+ d = yield from self._read(8)
280
+ pid = struct.unpack('<Q', d)[0]
281
+
282
+ # Write main src
283
+ yield from self._write(struct.pack('<I', len(self._main_z)))
284
+ yield from self._write(self._main_z)
285
+
286
+ # Read second and third ack
287
+ yield from self._expect(_PYREMOTE_BOOTSTRAP_ACK1)
288
+ yield from self._expect(_PYREMOTE_BOOTSTRAP_ACK2)
289
+
290
+ # Read env info
291
+ d = yield from self._read(4)
292
+ env_info_json_len = struct.unpack('<I', d)[0]
293
+ d = yield from self._read(env_info_json_len)
294
+ env_info_json = d.decode('utf-8')
295
+ env_info = PyremoteEnvInfo(**json.loads(env_info_json))
296
+
297
+ # Read fourth ack
298
+ yield from self._expect(_PYREMOTE_BOOTSTRAP_ACK3)
299
+
300
+ # Return
301
+ return self.Result(
302
+ pid=pid,
303
+ env_info=env_info,
304
+ )
305
+
306
+ def _read(self, sz: int) -> ta.Generator[Read, bytes, bytes]:
307
+ d = yield self.Read(sz)
308
+ if not isinstance(d, bytes):
309
+ raise self.ProtocolError(f'Expected bytes after read, got {d!r}')
310
+ if len(d) != sz:
311
+ raise self.ProtocolError(f'Read {len(d)} bytes, expected {sz}')
312
+ return d
313
+
314
+ def _expect(self, e: bytes) -> ta.Generator[Read, bytes, None]:
315
+ d = yield from self._read(len(e))
316
+ if d != e:
317
+ raise self.ProtocolError(f'Read {d!r}, expected {e!r}')
318
+
319
+ def _write(self, d: bytes) -> ta.Generator[Write, ta.Optional[bytes], None]:
320
+ i = yield self.Write(d)
321
+ if i is not None:
322
+ raise self.ProtocolError('Unexpected input after write')
323
+
324
+ #
325
+
326
+ def run(self, stdin: ta.IO, stdout: ta.IO) -> Result:
327
+ gen = self.gen()
328
+
329
+ gi: bytes | None = None
330
+ while True:
331
+ try:
332
+ if gi is not None:
333
+ go = gen.send(gi)
334
+ else:
335
+ go = next(gen)
336
+ except StopIteration as e:
337
+ return e.value
338
+
339
+ if isinstance(go, self.Read):
340
+ gi = stdout.read(go.sz)
341
+ elif isinstance(go, self.Write):
342
+ gi = None
343
+ stdin.write(go.d)
344
+ stdin.flush()
345
+ else:
346
+ raise TypeError(go)
347
+
348
+
349
+ ##
350
+
351
+
352
+ @dc.dataclass(frozen=True)
353
+ class PyremotePayloadRuntime:
354
+ input: ta.BinaryIO
355
+ main_src: str
356
+ env_info: PyremoteEnvInfo
357
+
358
+
359
+ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
360
+ # Restore original argv0
361
+ sys.executable = os.environ.pop(_PYREMOTE_BOOTSTRAP_ARGV0_VAR)
362
+
363
+ # Read second copy of main src
364
+ r1 = os.fdopen(_PYREMOTE_BOOTSTRAP_SRC_FD, 'rb', 0)
365
+ main_src = r1.read().decode('utf-8')
366
+ r1.close()
367
+
368
+ # Reap boostrap child. Must be done after reading second copy of source because source may be too big to fit in a
369
+ # pipe at once.
370
+ os.waitpid(int(os.environ.pop(_PYREMOTE_BOOTSTRAP_CHILD_PID_VAR)), 0)
371
+
372
+ # Write third ack
373
+ os.write(1, _PYREMOTE_BOOTSTRAP_ACK2)
374
+
375
+ # Write env info
376
+ env_info = _get_pyremote_env_info()
377
+ env_info_json = json.dumps(dc.asdict(env_info), indent=None, separators=(',', ':')) # noqa
378
+ os.write(1, struct.pack('<I', len(env_info_json)))
379
+ os.write(1, env_info_json.encode('utf-8'))
380
+
381
+ # Write fourth ack
382
+ os.write(1, _PYREMOTE_BOOTSTRAP_ACK3)
383
+
384
+ # Return
385
+ return PyremotePayloadRuntime(
386
+ input=os.fdopen(_PYREMOTE_BOOTSTRAP_COMM_FD, 'rb', 0),
387
+ main_src=main_src,
388
+ env_info=env_info,
389
+ )
@@ -3,7 +3,7 @@
3
3
  # @omlish-lite
4
4
  # @omlish-script
5
5
  # @omlish-amalg-output ../supervisor/main.py
6
- # ruff: noqa: N802 U006 UP006 UP007 UP012 UP036
6
+ # ruff: noqa: N802 UP006 UP007 UP012 UP036
7
7
  # Supervisor is licensed under the following license:
8
8
  #
9
9
  # A copyright notice accompanies this license document that identifies the copyright holders.
@@ -1,4 +1,4 @@
1
- # ruff: noqa: U006 UP007
1
+ # ruff: noqa: UP006 UP007
2
2
  import contextlib
3
3
  import json
4
4
  import socket
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev132
3
+ Version: 0.0.0.dev134
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.dev132
16
- Requires-Dist: omlish==0.0.0.dev132
15
+ Requires-Dist: omdev==0.0.0.dev134
16
+ Requires-Dist: omlish==0.0.0.dev134
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -7,6 +7,7 @@ ominfra/__about__.py
7
7
  ominfra/__init__.py
8
8
  ominfra/cmds.py
9
9
  ominfra/configs.py
10
+ ominfra/pyremote.py
10
11
  ominfra/ssh.py
11
12
  ominfra/threadworkers.py
12
13
  ominfra.egg-info/PKG-INFO
@@ -31,33 +32,6 @@ ominfra/clouds/aws/journald2aws/main.py
31
32
  ominfra/clouds/aws/journald2aws/poster.py
32
33
  ominfra/clouds/gcp/__init__.py
33
34
  ominfra/clouds/gcp/auth.py
34
- ominfra/deploy/__init__.py
35
- ominfra/deploy/_executor.py
36
- ominfra/deploy/configs.py
37
- ominfra/deploy/remote.py
38
- ominfra/deploy/executor/__init__.py
39
- ominfra/deploy/executor/base.py
40
- ominfra/deploy/executor/main.py
41
- ominfra/deploy/executor/concerns/__init__.py
42
- ominfra/deploy/executor/concerns/dirs.py
43
- ominfra/deploy/executor/concerns/nginx.py
44
- ominfra/deploy/executor/concerns/repo.py
45
- ominfra/deploy/executor/concerns/supervisor.py
46
- ominfra/deploy/executor/concerns/systemd.py
47
- ominfra/deploy/executor/concerns/user.py
48
- ominfra/deploy/executor/concerns/venv.py
49
- ominfra/deploy/poly/__init__.py
50
- ominfra/deploy/poly/_main.py
51
- ominfra/deploy/poly/base.py
52
- ominfra/deploy/poly/configs.py
53
- ominfra/deploy/poly/deploy.py
54
- ominfra/deploy/poly/main.py
55
- ominfra/deploy/poly/nginx.py
56
- ominfra/deploy/poly/repo.py
57
- ominfra/deploy/poly/runtime.py
58
- ominfra/deploy/poly/site.py
59
- ominfra/deploy/poly/supervisor.py
60
- ominfra/deploy/poly/venv.py
61
35
  ominfra/journald/__init__.py
62
36
  ominfra/journald/fields.py
63
37
  ominfra/journald/genmessages.py
@@ -65,10 +39,33 @@ ominfra/journald/messages.py
65
39
  ominfra/journald/tailer.py
66
40
  ominfra/manage/__init__.py
67
41
  ominfra/manage/manage.py
68
- ominfra/pyremote/__init__.py
69
- ominfra/pyremote/_runcommands.py
70
- ominfra/pyremote/bootstrap.py
71
- ominfra/pyremote/runcommands.py
42
+ ominfra/manage/deploy/__init__.py
43
+ ominfra/manage/deploy/_executor.py
44
+ ominfra/manage/deploy/configs.py
45
+ ominfra/manage/deploy/remote.py
46
+ ominfra/manage/deploy/executor/__init__.py
47
+ ominfra/manage/deploy/executor/base.py
48
+ ominfra/manage/deploy/executor/main.py
49
+ ominfra/manage/deploy/executor/concerns/__init__.py
50
+ ominfra/manage/deploy/executor/concerns/dirs.py
51
+ ominfra/manage/deploy/executor/concerns/nginx.py
52
+ ominfra/manage/deploy/executor/concerns/repo.py
53
+ ominfra/manage/deploy/executor/concerns/supervisor.py
54
+ ominfra/manage/deploy/executor/concerns/systemd.py
55
+ ominfra/manage/deploy/executor/concerns/user.py
56
+ ominfra/manage/deploy/executor/concerns/venv.py
57
+ ominfra/manage/deploy/poly/__init__.py
58
+ ominfra/manage/deploy/poly/_main.py
59
+ ominfra/manage/deploy/poly/base.py
60
+ ominfra/manage/deploy/poly/configs.py
61
+ ominfra/manage/deploy/poly/deploy.py
62
+ ominfra/manage/deploy/poly/main.py
63
+ ominfra/manage/deploy/poly/nginx.py
64
+ ominfra/manage/deploy/poly/repo.py
65
+ ominfra/manage/deploy/poly/runtime.py
66
+ ominfra/manage/deploy/poly/site.py
67
+ ominfra/manage/deploy/poly/supervisor.py
68
+ ominfra/manage/deploy/poly/venv.py
72
69
  ominfra/scripts/__init__.py
73
70
  ominfra/scripts/journald2aws.py
74
71
  ominfra/scripts/supervisor.py
@@ -1,5 +1,5 @@
1
- omdev==0.0.0.dev132
2
- omlish==0.0.0.dev132
1
+ omdev==0.0.0.dev134
2
+ omlish==0.0.0.dev134
3
3
 
4
4
  [all]
5
5
  paramiko~=3.5
@@ -12,7 +12,7 @@ authors = [
12
12
  urls = {source = 'https://github.com/wrmsr/omlish'}
13
13
  license = {text = 'BSD-3-Clause'}
14
14
  requires-python = '>=3.12'
15
- version = '0.0.0.dev132'
15
+ version = '0.0.0.dev134'
16
16
  classifiers = [
17
17
  'License :: OSI Approved :: BSD License',
18
18
  'Development Status :: 2 - Pre-Alpha',
@@ -22,8 +22,8 @@ classifiers = [
22
22
  ]
23
23
  description = 'ominfra'
24
24
  dependencies = [
25
- 'omdev == 0.0.0.dev132',
26
- 'omlish == 0.0.0.dev132',
25
+ 'omdev == 0.0.0.dev134',
26
+ 'omlish == 0.0.0.dev134',
27
27
  ]
28
28
 
29
29
  [project.optional-dependencies]