ominfra 0.0.0.dev157__tar.gz → 0.0.0.dev158__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. {ominfra-0.0.0.dev157/ominfra.egg-info → ominfra-0.0.0.dev158}/PKG-INFO +3 -3
  2. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/journald2aws/main.py +1 -1
  3. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/journald/tailer.py +2 -2
  4. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/bootstrap_.py +1 -1
  5. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/commands/subprocess.py +4 -4
  6. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/apps.py +14 -15
  7. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/config.py +3 -0
  8. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/git.py +11 -27
  9. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/paths.py +48 -48
  10. ominfra-0.0.0.dev158/ominfra/manage/deploy/specs.py +32 -0
  11. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/venvs.py +10 -5
  12. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/spawning.py +3 -3
  13. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/system/packages.py +1 -1
  14. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/pyremote.py +26 -26
  15. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/scripts/journald2aws.py +461 -350
  16. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/scripts/manage.py +1783 -1693
  17. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/scripts/supervisor.py +353 -332
  18. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/http.py +1 -1
  19. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/main.py +2 -2
  20. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158/ominfra.egg-info}/PKG-INFO +3 -3
  21. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra.egg-info/SOURCES.txt +1 -0
  22. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra.egg-info/requires.txt +2 -2
  23. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/pyproject.toml +3 -3
  24. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/LICENSE +0 -0
  25. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/MANIFEST.in +0 -0
  26. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/README.rst +0 -0
  27. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/.manifests.json +0 -0
  28. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/__about__.py +0 -0
  29. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/__init__.py +0 -0
  30. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/__init__.py +0 -0
  31. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/__init__.py +0 -0
  32. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/__main__.py +0 -0
  33. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/auth.py +0 -0
  34. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/cli.py +0 -0
  35. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/dataclasses.py +0 -0
  36. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  37. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  38. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  39. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/journald2aws/driver.py +0 -0
  40. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  41. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/logs.py +0 -0
  42. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/aws/metadata.py +0 -0
  43. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/gcp/__init__.py +0 -0
  44. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/clouds/gcp/auth.py +0 -0
  45. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/cmds.py +0 -0
  46. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/configs.py +0 -0
  47. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/journald/__init__.py +0 -0
  48. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/journald/fields.py +0 -0
  49. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/journald/genmessages.py +0 -0
  50. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/journald/messages.py +0 -0
  51. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/__init__.py +0 -0
  52. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/__main__.py +0 -0
  53. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/bootstrap.py +0 -0
  54. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/commands/__init__.py +0 -0
  55. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/commands/base.py +0 -0
  56. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/commands/inject.py +0 -0
  57. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/commands/local.py +0 -0
  58. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/commands/marshal.py +0 -0
  59. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/commands/ping.py +0 -0
  60. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/commands/types.py +0 -0
  61. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/config.py +0 -0
  62. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/__init__.py +0 -0
  63. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/commands.py +0 -0
  64. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/inject.py +0 -0
  65. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/interp.py +0 -0
  66. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/deploy/types.py +0 -0
  67. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/inject.py +0 -0
  68. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/main.py +0 -0
  69. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/marshal.py +0 -0
  70. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/__init__.py +0 -0
  71. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/_main.py +0 -0
  72. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/channel.py +0 -0
  73. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/config.py +0 -0
  74. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/connection.py +0 -0
  75. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/execution.py +0 -0
  76. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/inject.py +0 -0
  77. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/remote/payload.py +0 -0
  78. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/system/__init__.py +0 -0
  79. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/system/commands.py +0 -0
  80. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/system/config.py +0 -0
  81. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/system/inject.py +0 -0
  82. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/system/platforms.py +0 -0
  83. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/targets/__init__.py +0 -0
  84. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/targets/connection.py +0 -0
  85. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/targets/inject.py +0 -0
  86. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/manage/targets/targets.py +0 -0
  87. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/scripts/__init__.py +0 -0
  88. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/ssh.py +0 -0
  89. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/LICENSE.txt +0 -0
  90. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/__init__.py +0 -0
  91. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/__main__.py +0 -0
  92. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/configs.py +0 -0
  93. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/dispatchers.py +0 -0
  94. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/dispatchersimpl.py +0 -0
  95. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/events.py +0 -0
  96. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/exceptions.py +0 -0
  97. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/groups.py +0 -0
  98. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/groupsimpl.py +0 -0
  99. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/inject.py +0 -0
  100. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/io.py +0 -0
  101. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/pipes.py +0 -0
  102. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/privileges.py +0 -0
  103. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/process.py +0 -0
  104. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/processimpl.py +0 -0
  105. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/setup.py +0 -0
  106. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/setupimpl.py +0 -0
  107. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/signals.py +0 -0
  108. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/spawning.py +0 -0
  109. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/spawningimpl.py +0 -0
  110. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/states.py +0 -0
  111. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/supervisor.py +0 -0
  112. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/types.py +0 -0
  113. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/__init__.py +0 -0
  114. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/collections.py +0 -0
  115. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/diag.py +0 -0
  116. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/fds.py +0 -0
  117. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/fs.py +0 -0
  118. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/os.py +0 -0
  119. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/ostypes.py +0 -0
  120. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/signals.py +0 -0
  121. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/strings.py +0 -0
  122. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/supervisor/utils/users.py +0 -0
  123. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/tailscale/__init__.py +0 -0
  124. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/tailscale/api.py +0 -0
  125. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/tailscale/cli.py +0 -0
  126. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/threadworkers.py +0 -0
  127. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/tools/__init__.py +0 -0
  128. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra/tools/listresources.py +0 -0
  129. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra.egg-info/dependency_links.txt +0 -0
  130. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra.egg-info/entry_points.txt +0 -0
  131. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/ominfra.egg-info/top_level.txt +0 -0
  132. {ominfra-0.0.0.dev157 → ominfra-0.0.0.dev158}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev157
3
+ Version: 0.0.0.dev158
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.dev157
16
- Requires-Dist: omlish==0.0.0.dev157
15
+ Requires-Dist: omdev==0.0.0.dev158
16
+ Requires-Dist: omlish==0.0.0.dev158
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -5,7 +5,7 @@ import dataclasses as dc
5
5
  import os.path
6
6
  import sys
7
7
 
8
- from omlish.lite.logs import configure_standard_logging
8
+ from omlish.logs.standard import configure_standard_logging
9
9
 
10
10
  from ....configs import read_config_file
11
11
  from .driver import JournalctlToAwsDriver
@@ -410,8 +410,8 @@ import typing as ta
410
410
  from omlish.lite.cached import cached_nullary
411
411
  from omlish.lite.check import check
412
412
  from omlish.lite.logs import log
413
- from omlish.lite.subprocesses import subprocess_close
414
- from omlish.lite.subprocesses import subprocess_shell_wrap_exec
413
+ from omlish.subprocesses import subprocess_close
414
+ from omlish.subprocesses import subprocess_shell_wrap_exec
415
415
 
416
416
  from ..threadworkers import ThreadWorker
417
417
  from .messages import JournalctlMessage # noqa
@@ -1,7 +1,7 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  from omlish.lite.inject import Injector
3
3
  from omlish.lite.inject import inj
4
- from omlish.lite.logs import configure_standard_logging
4
+ from omlish.logs.standard import configure_standard_logging
5
5
 
6
6
  from .bootstrap import MainBootstrap
7
7
  from .inject import bind_main
@@ -6,11 +6,11 @@ import subprocess
6
6
  import time
7
7
  import typing as ta
8
8
 
9
- from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
9
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
10
10
  from omlish.lite.check import check
11
- from omlish.lite.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
12
- from omlish.lite.subprocesses import SubprocessChannelOption
13
- from omlish.lite.subprocesses import subprocess_maybe_shell_wrap_exec
11
+ from omlish.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
12
+ from omlish.subprocesses import SubprocessChannelOption
13
+ from omlish.subprocesses import subprocess_maybe_shell_wrap_exec
14
14
 
15
15
  from .base import Command
16
16
  from .base import CommandExecutor
@@ -3,12 +3,13 @@ import datetime
3
3
  import os.path
4
4
  import typing as ta
5
5
 
6
+ from omlish.lite.cached import cached_nullary
7
+ from omlish.lite.check import check
8
+
6
9
  from .git import DeployGitManager
7
- from .git import DeployGitRepo
8
- from .git import DeployGitSpec
9
10
  from .paths import DeployPath
10
11
  from .paths import DeployPathOwner
11
- from .types import DeployApp
12
+ from .specs import DeploySpec
12
13
  from .types import DeployAppTag
13
14
  from .types import DeployHome
14
15
  from .types import DeployRev
@@ -24,14 +25,14 @@ def make_deploy_tag(
24
25
  now = datetime.datetime.utcnow() # noqa
25
26
  now_fmt = '%Y%m%dT%H%M%S'
26
27
  now_str = now.strftime(now_fmt)
27
- return DeployTag('-'.join([rev, now_str]))
28
+ return DeployTag('-'.join([now_str, rev]))
28
29
 
29
30
 
30
31
  class DeployAppManager(DeployPathOwner):
31
32
  def __init__(
32
33
  self,
33
34
  *,
34
- deploy_home: DeployHome,
35
+ deploy_home: ta.Optional[DeployHome] = None,
35
36
  git: DeployGitManager,
36
37
  venvs: DeployVenvManager,
37
38
  ) -> None:
@@ -41,7 +42,9 @@ class DeployAppManager(DeployPathOwner):
41
42
  self._git = git
42
43
  self._venvs = venvs
43
44
 
44
- self._dir = os.path.join(deploy_home, 'apps')
45
+ @cached_nullary
46
+ def _dir(self) -> str:
47
+ return os.path.join(check.non_empty_str(self._deploy_home), 'apps')
45
48
 
46
49
  def get_deploy_paths(self) -> ta.AbstractSet[DeployPath]:
47
50
  return {
@@ -50,20 +53,16 @@ class DeployAppManager(DeployPathOwner):
50
53
 
51
54
  async def prepare_app(
52
55
  self,
53
- app: DeployApp,
54
- rev: DeployRev,
55
- repo: DeployGitRepo,
56
+ spec: DeploySpec,
56
57
  ):
57
- app_tag = DeployAppTag(app, make_deploy_tag(rev))
58
- app_dir = os.path.join(self._dir, app, app_tag.tag)
58
+ app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.rev))
59
+ app_dir = os.path.join(self._dir(), spec.app, app_tag.tag)
59
60
 
60
61
  #
61
62
 
62
63
  await self._git.checkout(
63
- DeployGitSpec(
64
- repo=repo,
65
- rev=rev,
66
- ),
64
+ spec.repo,
65
+ spec.rev,
67
66
  app_dir,
68
67
  )
69
68
 
@@ -3,6 +3,9 @@ import dataclasses as dc
3
3
  import typing as ta
4
4
 
5
5
 
6
+ ##
7
+
8
+
6
9
  @dc.dataclass(frozen=True)
7
10
  class DeployConfig:
8
11
  deploy_home: ta.Optional[str] = None
@@ -8,17 +8,18 @@ git/github.com/wrmsr/omlish <- bootstrap repo
8
8
 
9
9
  github.com/wrmsr/omlish@rev
10
10
  """
11
- import dataclasses as dc
12
11
  import functools
13
12
  import os.path
14
13
  import typing as ta
15
14
 
16
- from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
15
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
17
16
  from omlish.lite.cached import async_cached_nullary
17
+ from omlish.lite.cached import cached_nullary
18
18
  from omlish.lite.check import check
19
19
 
20
20
  from .paths import DeployPath
21
21
  from .paths import DeployPathOwner
22
+ from .specs import DeployGitRepo
22
23
  from .types import DeployHome
23
24
  from .types import DeployRev
24
25
 
@@ -26,39 +27,22 @@ from .types import DeployRev
26
27
  ##
27
28
 
28
29
 
29
- @dc.dataclass(frozen=True)
30
- class DeployGitRepo:
31
- host: ta.Optional[str] = None
32
- username: ta.Optional[str] = None
33
- path: ta.Optional[str] = None
34
-
35
- def __post_init__(self) -> None:
36
- check.not_in('..', check.non_empty_str(self.host))
37
- check.not_in('.', check.non_empty_str(self.path))
38
-
39
-
40
- @dc.dataclass(frozen=True)
41
- class DeployGitSpec:
42
- repo: DeployGitRepo
43
- rev: DeployRev
44
-
45
-
46
- ##
47
-
48
-
49
30
  class DeployGitManager(DeployPathOwner):
50
31
  def __init__(
51
32
  self,
52
33
  *,
53
- deploy_home: DeployHome,
34
+ deploy_home: ta.Optional[DeployHome] = None,
54
35
  ) -> None:
55
36
  super().__init__()
56
37
 
57
38
  self._deploy_home = deploy_home
58
- self._dir = os.path.join(deploy_home, 'git')
59
39
 
60
40
  self._repo_dirs: ta.Dict[DeployGitRepo, DeployGitManager.RepoDir] = {}
61
41
 
42
+ @cached_nullary
43
+ def _dir(self) -> str:
44
+ return os.path.join(check.non_empty_str(self._deploy_home), 'git')
45
+
62
46
  def get_deploy_paths(self) -> ta.AbstractSet[DeployPath]:
63
47
  return {
64
48
  DeployPath.parse('git'),
@@ -75,7 +59,7 @@ class DeployGitManager(DeployPathOwner):
75
59
  self._git = git
76
60
  self._repo = repo
77
61
  self._dir = os.path.join(
78
- self._git._dir, # noqa
62
+ self._git._dir(), # noqa
79
63
  check.non_empty_str(repo.host),
80
64
  check.non_empty_str(repo.path),
81
65
  )
@@ -132,5 +116,5 @@ class DeployGitManager(DeployPathOwner):
132
116
  repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(self, repo)
133
117
  return repo_dir
134
118
 
135
- async def checkout(self, spec: DeployGitSpec, dst_dir: str) -> None:
136
- await self.get_repo_dir(spec.repo).checkout(spec.rev, dst_dir)
119
+ async def checkout(self, repo: DeployGitRepo, rev: DeployRev, dst_dir: str) -> None:
120
+ await self.get_repo_dir(repo).checkout(rev, dst_dir)
@@ -3,22 +3,22 @@
3
3
  ~deploy
4
4
  deploy.pid (flock)
5
5
  /app
6
- /<appspec> - shallow clone
6
+ /<appplaceholder> - shallow clone
7
7
  /conf
8
8
  /env
9
- <appspec>.env
9
+ <appplaceholder>.env
10
10
  /nginx
11
- <appspec>.conf
11
+ <appplaceholder>.conf
12
12
  /supervisor
13
- <appspec>.conf
13
+ <appplaceholder>.conf
14
14
  /venv
15
- /<appspec>
15
+ /<appplaceholder>
16
16
 
17
17
  ?
18
18
  /logs
19
- /wrmsr--omlish--<spec>
19
+ /wrmsr--omlish--<placeholder>
20
20
 
21
- spec = <name>--<rev>--<when>
21
+ placeholder = <name>--<rev>--<when>
22
22
 
23
23
  ==
24
24
 
@@ -43,16 +43,16 @@ from omlish.lite.check import check
43
43
 
44
44
 
45
45
  DeployPathKind = ta.Literal['dir', 'file'] # ta.TypeAlias
46
- DeployPathSpec = ta.Literal['app', 'tag'] # ta.TypeAlias
46
+ DeployPathPlaceholder = ta.Literal['app', 'tag'] # ta.TypeAlias
47
47
 
48
48
 
49
49
  ##
50
50
 
51
51
 
52
- DEPLOY_PATH_SPEC_PLACEHOLDER = '@'
53
- DEPLOY_PATH_SPEC_SEPARATORS = '-.'
52
+ DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER = '@'
53
+ DEPLOY_PATH_PLACEHOLDER_SEPARATORS = '-.'
54
54
 
55
- DEPLOY_PATH_SPECS: ta.FrozenSet[str] = frozenset([
55
+ DEPLOY_PATH_PLACEHOLDERS: ta.FrozenSet[str] = frozenset([
56
56
  'app',
57
57
  'tag', # <rev>-<dt>
58
58
  ])
@@ -70,7 +70,7 @@ class DeployPathPart(abc.ABC): # noqa
70
70
  raise NotImplementedError
71
71
 
72
72
  @abc.abstractmethod
73
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
73
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
74
74
  raise NotImplementedError
75
75
 
76
76
 
@@ -84,9 +84,9 @@ class DirDeployPathPart(DeployPathPart, abc.ABC):
84
84
 
85
85
  @classmethod
86
86
  def parse(cls, s: str) -> 'DirDeployPathPart':
87
- if DEPLOY_PATH_SPEC_PLACEHOLDER in s:
88
- check.equal(s[0], DEPLOY_PATH_SPEC_PLACEHOLDER)
89
- return SpecDirDeployPathPart(s[1:])
87
+ if DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER in s:
88
+ check.equal(s[0], DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER)
89
+ return PlaceholderDirDeployPathPart(s[1:])
90
90
  else:
91
91
  return ConstDirDeployPathPart(s)
92
92
 
@@ -98,13 +98,13 @@ class FileDeployPathPart(DeployPathPart, abc.ABC):
98
98
 
99
99
  @classmethod
100
100
  def parse(cls, s: str) -> 'FileDeployPathPart':
101
- if DEPLOY_PATH_SPEC_PLACEHOLDER in s:
102
- check.equal(s[0], DEPLOY_PATH_SPEC_PLACEHOLDER)
103
- if not any(c in s for c in DEPLOY_PATH_SPEC_SEPARATORS):
104
- return SpecFileDeployPathPart(s[1:], '')
101
+ if DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER in s:
102
+ check.equal(s[0], DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER)
103
+ if not any(c in s for c in DEPLOY_PATH_PLACEHOLDER_SEPARATORS):
104
+ return PlaceholderFileDeployPathPart(s[1:], '')
105
105
  else:
106
- p = min(f for c in DEPLOY_PATH_SPEC_SEPARATORS if (f := s.find(c)) > 0)
107
- return SpecFileDeployPathPart(s[1:p], s[p:])
106
+ p = min(f for c in DEPLOY_PATH_PLACEHOLDER_SEPARATORS if (f := s.find(c)) > 0)
107
+ return PlaceholderFileDeployPathPart(s[1:p], s[p:])
108
108
  else:
109
109
  return ConstFileDeployPathPart(s)
110
110
 
@@ -119,9 +119,9 @@ class ConstDeployPathPart(DeployPathPart, abc.ABC):
119
119
  def __post_init__(self) -> None:
120
120
  check.non_empty_str(self.name)
121
121
  check.not_in('/', self.name)
122
- check.not_in(DEPLOY_PATH_SPEC_PLACEHOLDER, self.name)
122
+ check.not_in(DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER, self.name)
123
123
 
124
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
124
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
125
125
  return self.name
126
126
 
127
127
 
@@ -137,40 +137,40 @@ class ConstFileDeployPathPart(ConstDeployPathPart, FileDeployPathPart):
137
137
 
138
138
 
139
139
  @dc.dataclass(frozen=True)
140
- class SpecDeployPathPart(DeployPathPart, abc.ABC):
141
- spec: str # DeployPathSpec
140
+ class PlaceholderDeployPathPart(DeployPathPart, abc.ABC):
141
+ placeholder: str # DeployPathPlaceholder
142
142
 
143
143
  def __post_init__(self) -> None:
144
- check.non_empty_str(self.spec)
145
- for c in [*DEPLOY_PATH_SPEC_SEPARATORS, DEPLOY_PATH_SPEC_PLACEHOLDER, '/']:
146
- check.not_in(c, self.spec)
147
- check.in_(self.spec, DEPLOY_PATH_SPECS)
148
-
149
- def _render_spec(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
150
- if specs is not None:
151
- return specs[self.spec] # type: ignore
144
+ check.non_empty_str(self.placeholder)
145
+ for c in [*DEPLOY_PATH_PLACEHOLDER_SEPARATORS, DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER, '/']:
146
+ check.not_in(c, self.placeholder)
147
+ check.in_(self.placeholder, DEPLOY_PATH_PLACEHOLDERS)
148
+
149
+ def _render_placeholder(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
150
+ if placeholders is not None:
151
+ return placeholders[self.placeholder] # type: ignore
152
152
  else:
153
- return DEPLOY_PATH_SPEC_PLACEHOLDER + self.spec
153
+ return DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER + self.placeholder
154
154
 
155
155
 
156
156
  @dc.dataclass(frozen=True)
157
- class SpecDirDeployPathPart(SpecDeployPathPart, DirDeployPathPart):
158
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
159
- return self._render_spec(specs)
157
+ class PlaceholderDirDeployPathPart(PlaceholderDeployPathPart, DirDeployPathPart):
158
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
159
+ return self._render_placeholder(placeholders)
160
160
 
161
161
 
162
162
  @dc.dataclass(frozen=True)
163
- class SpecFileDeployPathPart(SpecDeployPathPart, FileDeployPathPart):
163
+ class PlaceholderFileDeployPathPart(PlaceholderDeployPathPart, FileDeployPathPart):
164
164
  suffix: str
165
165
 
166
166
  def __post_init__(self) -> None:
167
167
  super().__post_init__()
168
168
  if self.suffix:
169
- for c in [DEPLOY_PATH_SPEC_PLACEHOLDER, '/']:
169
+ for c in [DEPLOY_PATH_PLACEHOLDER_PLACEHOLDER, '/']:
170
170
  check.not_in(c, self.suffix)
171
171
 
172
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
173
- return self._render_spec(specs) + self.suffix
172
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
173
+ return self._render_placeholder(placeholders) + self.suffix
174
174
 
175
175
 
176
176
  ##
@@ -187,22 +187,22 @@ class DeployPath:
187
187
 
188
188
  pd = {}
189
189
  for i, p in enumerate(self.parts):
190
- if isinstance(p, SpecDeployPathPart):
191
- if p.spec in pd:
192
- raise DeployPathError('Duplicate specs in path', self)
193
- pd[p.spec] = i
190
+ if isinstance(p, PlaceholderDeployPathPart):
191
+ if p.placeholder in pd:
192
+ raise DeployPathError('Duplicate placeholders in path', self)
193
+ pd[p.placeholder] = i
194
194
 
195
195
  if 'tag' in pd:
196
196
  if 'app' not in pd or pd['app'] >= pd['tag']:
197
- raise DeployPathError('Tag spec in path without preceding app', self)
197
+ raise DeployPathError('Tag placeholder in path without preceding app', self)
198
198
 
199
199
  @property
200
200
  def kind(self) -> ta.Literal['file', 'dir']:
201
201
  return self.parts[-1].kind
202
202
 
203
- def render(self, specs: ta.Optional[ta.Mapping[DeployPathSpec, str]] = None) -> str:
203
+ def render(self, placeholders: ta.Optional[ta.Mapping[DeployPathPlaceholder, str]] = None) -> str:
204
204
  return os.path.join( # noqa
205
- *[p.render(specs) for p in self.parts],
205
+ *[p.render(placeholders) for p in self.parts],
206
206
  *([''] if self.kind == 'dir' else []),
207
207
  )
208
208
 
@@ -0,0 +1,32 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+ from omlish.lite.check import check
6
+
7
+ from .types import DeployApp
8
+ from .types import DeployRev
9
+
10
+
11
+ ##
12
+
13
+
14
+ @dc.dataclass(frozen=True)
15
+ class DeployGitRepo:
16
+ host: ta.Optional[str] = None
17
+ username: ta.Optional[str] = None
18
+ path: ta.Optional[str] = None
19
+
20
+ def __post_init__(self) -> None:
21
+ check.not_in('..', check.non_empty_str(self.host))
22
+ check.not_in('.', check.non_empty_str(self.path))
23
+
24
+
25
+ ##
26
+
27
+
28
+ @dc.dataclass(frozen=True)
29
+ class DeploySpec:
30
+ app: DeployApp
31
+ repo: DeployGitRepo
32
+ rev: DeployRev
@@ -7,7 +7,9 @@ TODO:
7
7
  import os.path
8
8
  import typing as ta
9
9
 
10
- from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
10
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
11
+ from omlish.lite.cached import cached_nullary
12
+ from omlish.lite.check import check
11
13
 
12
14
  from .paths import DeployPath
13
15
  from .paths import DeployPathOwner
@@ -19,12 +21,15 @@ class DeployVenvManager(DeployPathOwner):
19
21
  def __init__(
20
22
  self,
21
23
  *,
22
- deploy_home: DeployHome,
24
+ deploy_home: ta.Optional[DeployHome] = None,
23
25
  ) -> None:
24
26
  super().__init__()
25
27
 
26
28
  self._deploy_home = deploy_home
27
- self._dir = os.path.join(deploy_home, 'venvs')
29
+
30
+ @cached_nullary
31
+ def _dir(self) -> str:
32
+ return os.path.join(check.non_empty_str(self._deploy_home), 'venvs')
28
33
 
29
34
  def get_deploy_paths(self) -> ta.AbstractSet[DeployPath]:
30
35
  return {
@@ -61,6 +66,6 @@ class DeployVenvManager(DeployPathOwner):
61
66
 
62
67
  async def setup_app_venv(self, app_tag: DeployAppTag) -> None:
63
68
  await self.setup_venv(
64
- os.path.join(self._deploy_home, 'apps', app_tag.app, app_tag.tag),
65
- os.path.join(self._deploy_home, 'venvs', app_tag.app, app_tag.tag),
69
+ os.path.join(check.non_empty_str(self._deploy_home), 'apps', app_tag.app, app_tag.tag),
70
+ os.path.join(self._dir(), app_tag.app, app_tag.tag),
66
71
  )
@@ -7,10 +7,10 @@ import shlex
7
7
  import subprocess
8
8
  import typing as ta
9
9
 
10
- from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
10
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
11
11
  from omlish.lite.check import check
12
- from omlish.lite.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
13
- from omlish.lite.subprocesses import SubprocessChannelOption
12
+ from omlish.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
13
+ from omlish.subprocesses import SubprocessChannelOption
14
14
 
15
15
 
16
16
  ##
@@ -9,7 +9,7 @@ import json
9
9
  import os
10
10
  import typing as ta
11
11
 
12
- from omlish.lite.asyncio.subprocesses import asyncio_subprocesses
12
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
13
13
  from omlish.lite.check import check
14
14
 
15
15
 
@@ -162,7 +162,7 @@ def _pyremote_bootstrap_main(context_name: str) -> None:
162
162
  # Get pid
163
163
  pid = os.getpid()
164
164
 
165
- # Two copies of main src to be sent to parent
165
+ # Two copies of payload src to be sent to parent
166
166
  r0, w0 = os.pipe()
167
167
  r1, w1 = os.pipe()
168
168
 
@@ -201,17 +201,17 @@ def _pyremote_bootstrap_main(context_name: str) -> None:
201
201
  # Write pid
202
202
  os.write(1, struct.pack('<Q', pid))
203
203
 
204
- # Read main src from stdin
205
- main_z_len = struct.unpack('<I', os.read(0, 4))[0]
206
- if len(main_z := os.fdopen(0, 'rb').read(main_z_len)) != main_z_len:
204
+ # Read payload src from stdin
205
+ payload_z_len = struct.unpack('<I', os.read(0, 4))[0]
206
+ if len(payload_z := os.fdopen(0, 'rb').read(payload_z_len)) != payload_z_len:
207
207
  raise EOFError
208
- main_src = zlib.decompress(main_z)
208
+ payload_src = zlib.decompress(payload_z)
209
209
 
210
- # Write both copies of main src. Must write to w0 (parent stdin) before w1 (copy pipe) as pipe will likely fill
211
- # and block and need to be drained by pyremote_bootstrap_finalize running in parent.
210
+ # Write both copies of payload src. Must write to w0 (parent stdin) before w1 (copy pipe) as pipe will likely
211
+ # fill and block and need to be drained by pyremote_bootstrap_finalize running in parent.
212
212
  for w in [w0, w1]:
213
213
  fp = os.fdopen(w, 'wb', 0)
214
- fp.write(main_src)
214
+ fp.write(payload_src)
215
215
  fp.close()
216
216
 
217
217
  # Write second ack
@@ -275,7 +275,7 @@ class PyremotePayloadRuntime:
275
275
  input: ta.BinaryIO
276
276
  output: ta.BinaryIO
277
277
  context_name: str
278
- main_src: str
278
+ payload_src: str
279
279
  options: PyremoteBootstrapOptions
280
280
  env_info: PyremoteEnvInfo
281
281
 
@@ -283,9 +283,9 @@ class PyremotePayloadRuntime:
283
283
  def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
284
284
  # If src file var is not present we need to do initial finalization
285
285
  if _PYREMOTE_BOOTSTRAP_SRC_FILE_VAR not in os.environ:
286
- # Read second copy of main src
286
+ # Read second copy of payload src
287
287
  r1 = os.fdopen(_PYREMOTE_BOOTSTRAP_SRC_FD, 'rb', 0)
288
- main_src = r1.read().decode('utf-8')
288
+ payload_src = r1.read().decode('utf-8')
289
289
  r1.close()
290
290
 
291
291
  # Reap boostrap child. Must be done after reading second copy of source because source may be too big to fit in
@@ -303,7 +303,7 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
303
303
  # Write temp source file
304
304
  import tempfile
305
305
  tfd, tfn = tempfile.mkstemp('-pyremote.py')
306
- os.write(tfd, main_src.encode('utf-8'))
306
+ os.write(tfd, payload_src.encode('utf-8'))
307
307
  os.close(tfd)
308
308
 
309
309
  # Set vars
@@ -322,7 +322,7 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
322
322
 
323
323
  # Read temp source file
324
324
  with open(os.environ.pop(_PYREMOTE_BOOTSTRAP_SRC_FILE_VAR)) as sf:
325
- main_src = sf.read()
325
+ payload_src = sf.read()
326
326
 
327
327
  # Restore vars
328
328
  sys.executable = os.environ.pop(_PYREMOTE_BOOTSTRAP_ARGV0_VAR)
@@ -355,7 +355,7 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
355
355
  input=input,
356
356
  output=output,
357
357
  context_name=context_name,
358
- main_src=main_src,
358
+ payload_src=payload_src,
359
359
  options=options,
360
360
  env_info=env_info,
361
361
  )
@@ -367,31 +367,31 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
367
367
  class PyremoteBootstrapDriver:
368
368
  def __init__(
369
369
  self,
370
- main_src: ta.Union[str, ta.Sequence[str]],
370
+ payload_src: ta.Union[str, ta.Sequence[str]],
371
371
  options: PyremoteBootstrapOptions = PyremoteBootstrapOptions(),
372
372
  ) -> None:
373
373
  super().__init__()
374
374
 
375
- self._main_src = main_src
375
+ self._payload_src = payload_src
376
376
  self._options = options
377
377
 
378
- self._prepared_main_src = self._prepare_main_src(main_src, options)
379
- self._main_z = zlib.compress(self._prepared_main_src.encode('utf-8'))
378
+ self._prepared_payload_src = self._prepare_payload_src(payload_src, options)
379
+ self._payload_z = zlib.compress(self._prepared_payload_src.encode('utf-8'))
380
380
 
381
381
  self._options_json = json.dumps(dc.asdict(options), indent=None, separators=(',', ':')).encode('utf-8') # noqa
382
382
  #
383
383
 
384
384
  @classmethod
385
- def _prepare_main_src(
385
+ def _prepare_payload_src(
386
386
  cls,
387
- main_src: ta.Union[str, ta.Sequence[str]],
387
+ payload_src: ta.Union[str, ta.Sequence[str]],
388
388
  options: PyremoteBootstrapOptions,
389
389
  ) -> str:
390
390
  parts: ta.List[str]
391
- if isinstance(main_src, str):
392
- parts = [main_src]
391
+ if isinstance(payload_src, str):
392
+ parts = [payload_src]
393
393
  else:
394
- parts = list(main_src)
394
+ parts = list(payload_src)
395
395
 
396
396
  if (mn := options.main_name_override) is not None:
397
397
  parts.insert(0, f'__name__ = {mn!r}')
@@ -427,9 +427,9 @@ class PyremoteBootstrapDriver:
427
427
  d = yield from self._read(8)
428
428
  pid = struct.unpack('<Q', d)[0]
429
429
 
430
- # Write main src
431
- yield from self._write(struct.pack('<I', len(self._main_z)))
432
- yield from self._write(self._main_z)
430
+ # Write payload src
431
+ yield from self._write(struct.pack('<I', len(self._payload_z)))
432
+ yield from self._write(self._payload_z)
433
433
 
434
434
  # Read second ack (after writing src copies)
435
435
  yield from self._expect(_PYREMOTE_BOOTSTRAP_ACK1)