ominfra 0.0.0.dev191__tar.gz → 0.0.0.dev192__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. {ominfra-0.0.0.dev191/ominfra.egg-info → ominfra-0.0.0.dev192}/PKG-INFO +4 -4
  2. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/apps.py +10 -0
  3. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/conf/manager.py +8 -2
  4. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/deploy.py +12 -5
  5. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/git.py +3 -1
  6. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/specs.py +2 -0
  7. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/systemd.py +2 -1
  8. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/scripts/manage.py +36 -9
  9. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/scripts/supervisor.py +18 -9
  10. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/configs.py +6 -0
  11. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/http.py +1 -1
  12. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/inject.py +11 -8
  13. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192/ominfra.egg-info}/PKG-INFO +4 -4
  14. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra.egg-info/requires.txt +3 -3
  15. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/pyproject.toml +4 -4
  16. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/LICENSE +0 -0
  17. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/MANIFEST.in +0 -0
  18. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/README.rst +0 -0
  19. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/.manifests.json +0 -0
  20. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/__about__.py +0 -0
  21. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/__init__.py +0 -0
  22. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/__init__.py +0 -0
  23. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/__init__.py +0 -0
  24. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/__main__.py +0 -0
  25. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/auth.py +0 -0
  26. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/cli.py +0 -0
  27. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/dataclasses.py +0 -0
  28. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  29. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  30. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  31. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/journald2aws/driver.py +0 -0
  32. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/journald2aws/main.py +0 -0
  33. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  34. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/logs.py +0 -0
  35. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/aws/metadata.py +0 -0
  36. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/gcp/__init__.py +0 -0
  37. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/clouds/gcp/auth.py +0 -0
  38. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/cmds.py +0 -0
  39. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/configs.py +0 -0
  40. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/journald/__init__.py +0 -0
  41. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/journald/fields.py +0 -0
  42. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/journald/genmessages.py +0 -0
  43. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/journald/messages.py +0 -0
  44. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/journald/tailer.py +0 -0
  45. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/__init__.py +0 -0
  46. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/__main__.py +0 -0
  47. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/bootstrap.py +0 -0
  48. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/bootstrap_.py +0 -0
  49. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/commands/__init__.py +0 -0
  50. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/commands/base.py +0 -0
  51. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/commands/inject.py +0 -0
  52. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/commands/local.py +0 -0
  53. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/commands/marshal.py +0 -0
  54. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/commands/ping.py +0 -0
  55. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/commands/subprocess.py +0 -0
  56. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/commands/types.py +0 -0
  57. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/config.py +0 -0
  58. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/__init__.py +0 -0
  59. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/commands.py +0 -0
  60. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/conf/__init__.py +0 -0
  61. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/conf/inject.py +0 -0
  62. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/conf/specs.py +0 -0
  63. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/config.py +0 -0
  64. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/inject.py +0 -0
  65. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/inject_.py +0 -0
  66. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/interp.py +0 -0
  67. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/nginx.py +0 -0
  68. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/paths/__init__.py +0 -0
  69. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/paths/inject.py +0 -0
  70. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/paths/manager.py +0 -0
  71. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/paths/owners.py +0 -0
  72. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/paths/paths.py +0 -0
  73. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/paths/specs.py +0 -0
  74. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/paths/types.py +0 -0
  75. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/tags.py +0 -0
  76. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/tmp.py +0 -0
  77. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/types.py +0 -0
  78. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/deploy/venvs.py +0 -0
  79. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/inject.py +0 -0
  80. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/main.py +0 -0
  81. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/marshal.py +0 -0
  82. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/__init__.py +0 -0
  83. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/_main.py +0 -0
  84. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/channel.py +0 -0
  85. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/config.py +0 -0
  86. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/connection.py +0 -0
  87. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/execution.py +0 -0
  88. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/inject.py +0 -0
  89. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/payload.py +0 -0
  90. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/remote/spawning.py +0 -0
  91. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/system/__init__.py +0 -0
  92. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/system/commands.py +0 -0
  93. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/system/config.py +0 -0
  94. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/system/inject.py +0 -0
  95. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/system/packages.py +0 -0
  96. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/system/platforms.py +0 -0
  97. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/targets/__init__.py +0 -0
  98. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/targets/bestpython.py +0 -0
  99. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/targets/bestpython.sh +0 -0
  100. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/targets/connection.py +0 -0
  101. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/targets/inject.py +0 -0
  102. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/manage/targets/targets.py +0 -0
  103. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/pyremote.py +0 -0
  104. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/scripts/__init__.py +0 -0
  105. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/scripts/journald2aws.py +0 -0
  106. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/ssh.py +0 -0
  107. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/LICENSE.txt +0 -0
  108. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/__init__.py +0 -0
  109. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/__main__.py +0 -0
  110. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/dispatchers.py +0 -0
  111. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/dispatchersimpl.py +0 -0
  112. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/events.py +0 -0
  113. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/exceptions.py +0 -0
  114. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/groups.py +0 -0
  115. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/groupsimpl.py +0 -0
  116. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/io.py +0 -0
  117. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/main.py +0 -0
  118. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/pipes.py +0 -0
  119. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/privileges.py +0 -0
  120. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/process.py +0 -0
  121. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/processimpl.py +0 -0
  122. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/setup.py +0 -0
  123. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/setupimpl.py +0 -0
  124. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/signals.py +0 -0
  125. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/spawning.py +0 -0
  126. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/spawningimpl.py +0 -0
  127. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/states.py +0 -0
  128. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/supervisor.py +0 -0
  129. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/types.py +0 -0
  130. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/__init__.py +0 -0
  131. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/collections.py +0 -0
  132. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/diag.py +0 -0
  133. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/fds.py +0 -0
  134. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/fs.py +0 -0
  135. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/os.py +0 -0
  136. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/ostypes.py +0 -0
  137. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/signals.py +0 -0
  138. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/strings.py +0 -0
  139. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/supervisor/utils/users.py +0 -0
  140. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/systemd.py +0 -0
  141. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/tailscale/__init__.py +0 -0
  142. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/tailscale/api.py +0 -0
  143. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/tailscale/cli.py +0 -0
  144. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/threadworkers.py +0 -0
  145. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/tools/__init__.py +0 -0
  146. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra/tools/listresources.py +0 -0
  147. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra.egg-info/SOURCES.txt +0 -0
  148. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra.egg-info/dependency_links.txt +0 -0
  149. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra.egg-info/entry_points.txt +0 -0
  150. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/ominfra.egg-info/top_level.txt +0 -0
  151. {ominfra-0.0.0.dev191 → ominfra-0.0.0.dev192}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev191
3
+ Version: 0.0.0.dev192
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,9 +12,9 @@ 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.dev191
16
- Requires-Dist: omlish==0.0.0.dev191
17
- Requires-Dist: omserv==0.0.0.dev191
15
+ Requires-Dist: omdev==0.0.0.dev192
16
+ Requires-Dist: omlish==0.0.0.dev192
17
+ Requires-Dist: omserv==0.0.0.dev192
18
18
  Provides-Extra: all
19
19
  Requires-Dist: paramiko~=3.5; extra == "all"
20
20
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -84,6 +84,8 @@ class DeployAppManager(DeployPathOwner):
84
84
  spec: DeployAppSpec,
85
85
  home: DeployHome,
86
86
  tags: DeployTagMap,
87
+ *,
88
+ conf_string_ns: ta.Optional[ta.Mapping[str, ta.Any]] = None,
87
89
  ) -> PreparedApp:
88
90
  spec_json = json_dumps_pretty(self._msh.marshal_obj(spec))
89
91
 
@@ -140,9 +142,17 @@ class DeployAppManager(DeployPathOwner):
140
142
  if spec.conf is not None:
141
143
  conf_dir = os.path.join(app_dir, 'conf')
142
144
  rkw.update(conf_dir=conf_dir)
145
+
146
+ conf_ns: ta.Dict[str, ta.Any] = dict(
147
+ **(conf_string_ns or {}),
148
+ app=spec.app.s,
149
+ app_dir=app_dir.rstrip('/'),
150
+ )
151
+
143
152
  await self._conf.write_app_conf(
144
153
  spec.conf,
145
154
  conf_dir,
155
+ string_ns=conf_ns,
146
156
  )
147
157
 
148
158
  #
@@ -133,9 +133,15 @@ class DeployConfManager:
133
133
  self,
134
134
  spec: DeployAppConfSpec,
135
135
  app_conf_dir: str,
136
+ *,
137
+ string_ns: ta.Optional[ta.Mapping[str, ta.Any]] = None,
136
138
  ) -> None:
137
- def process_str(s: str) -> str:
138
- return s
139
+ process_str: ta.Any
140
+ if string_ns is not None:
141
+ def process_str(s: str) -> str:
142
+ return s.format(**string_ns)
143
+ else:
144
+ process_str = None
139
145
 
140
146
  for acf in spec.files or []:
141
147
  await self._write_app_conf_file(
@@ -30,7 +30,7 @@ from .types import DeployHome
30
30
  ##
31
31
 
32
32
 
33
- DEPLOY_TAG_DATETIME_FMT = '%Y%m%dT%H%M%SZ'
33
+ DEPLOY_TAG_DATETIME_FMT = '%Y-%m-%d-T-%H-%M-%S-%f-Z'
34
34
 
35
35
 
36
36
  DeployManagerUtcClock = ta.NewType('DeployManagerUtcClock', Func0[datetime.datetime])
@@ -183,8 +183,9 @@ class DeployDriver:
183
183
 
184
184
  das: ta.Set[DeployApp] = {a.app for a in self._spec.apps}
185
185
  las: ta.Set[DeployApp] = set(self._spec.app_links.apps)
186
- if (ras := das & las):
187
- raise RuntimeError(f'Must not specify apps as both deploy and link: {sorted(a.s for a in ras)}')
186
+ ras: ta.Set[DeployApp] = set(self._spec.app_links.removed_apps)
187
+ check.empty(das & (las | ras))
188
+ check.empty(las & ras)
188
189
 
189
190
  #
190
191
 
@@ -230,10 +231,10 @@ class DeployDriver:
230
231
  cad = abs_real_path(os.path.join(current_link, 'apps'))
231
232
  if os.path.exists(cad):
232
233
  for d in os.listdir(cad):
233
- if (da := DeployApp(d)) not in das:
234
+ if (da := DeployApp(d)) not in das and da not in ras:
234
235
  las.add(da)
235
236
 
236
- for la in self._spec.app_links.apps:
237
+ for la in las:
237
238
  await self._drive_app_link(
238
239
  la,
239
240
  current_link,
@@ -263,10 +264,16 @@ class DeployDriver:
263
264
  #
264
265
 
265
266
  async def _drive_app_deploy(self, app: DeployAppSpec) -> None:
267
+ current_deploy_link = os.path.join(self._home, self._deploys.CURRENT_DEPLOY_LINK.render())
268
+
266
269
  pa = await self._apps.prepare_app(
267
270
  app,
268
271
  self._home,
269
272
  self.tags,
273
+ conf_string_ns=dict(
274
+ deploy_home=self._home,
275
+ current_deploy_link=current_deploy_link,
276
+ ),
270
277
  )
271
278
 
272
279
  #
@@ -91,7 +91,9 @@ class DeployGitManager(SingleDirDeployPathOwner):
91
91
 
92
92
  async def fetch(self, rev: DeployRev) -> None:
93
93
  await self.init()
94
- await self._call('git', 'fetch', '--depth=1', 'origin', rev)
94
+
95
+ # This fetch shouldn't be depth=1 - git doesn't reuse local data with shallow fetches.
96
+ await self._call('git', 'fetch', 'origin', rev)
95
97
 
96
98
  #
97
99
 
@@ -95,6 +95,8 @@ class DeployAppSpec(DeploySpecKeyed[DeployAppKey]):
95
95
  class DeployAppLinksSpec:
96
96
  apps: ta.Sequence[DeployApp] = ()
97
97
 
98
+ removed_apps: ta.Sequence[DeployApp] = ()
99
+
98
100
  exclude_unspecified: bool = False
99
101
 
100
102
 
@@ -8,6 +8,7 @@ TODO:
8
8
  - ominfra.systemd / x.sd_orphans
9
9
  """
10
10
  import os.path
11
+ import shutil
11
12
  import sys
12
13
  import typing as ta
13
14
 
@@ -101,7 +102,7 @@ class DeploySystemdManager:
101
102
 
102
103
  #
103
104
 
104
- if sys.platform == 'linux':
105
+ if sys.platform == 'linux' and shutil.which('systemctl') is not None:
105
106
  async def reload() -> None:
106
107
  await asyncio_subprocesses.check_call('systemctl', '--user', 'daemon-reload')
107
108
 
@@ -9353,9 +9353,15 @@ class DeployConfManager:
9353
9353
  self,
9354
9354
  spec: DeployAppConfSpec,
9355
9355
  app_conf_dir: str,
9356
+ *,
9357
+ string_ns: ta.Optional[ta.Mapping[str, ta.Any]] = None,
9356
9358
  ) -> None:
9357
- def process_str(s: str) -> str:
9358
- return s
9359
+ process_str: ta.Any
9360
+ if string_ns is not None:
9361
+ def process_str(s: str) -> str:
9362
+ return s.format(**string_ns)
9363
+ else:
9364
+ process_str = None
9359
9365
 
9360
9366
  for acf in spec.files or []:
9361
9367
  await self._write_app_conf_file(
@@ -9608,6 +9614,8 @@ class DeployAppSpec(DeploySpecKeyed[DeployAppKey]):
9608
9614
  class DeployAppLinksSpec:
9609
9615
  apps: ta.Sequence[DeployApp] = ()
9610
9616
 
9617
+ removed_apps: ta.Sequence[DeployApp] = ()
9618
+
9611
9619
  exclude_unspecified: bool = False
9612
9620
 
9613
9621
 
@@ -10967,7 +10975,9 @@ class DeployGitManager(SingleDirDeployPathOwner):
10967
10975
 
10968
10976
  async def fetch(self, rev: DeployRev) -> None:
10969
10977
  await self.init()
10970
- await self._call('git', 'fetch', '--depth=1', 'origin', rev)
10978
+
10979
+ # This fetch shouldn't be depth=1 - git doesn't reuse local data with shallow fetches.
10980
+ await self._call('git', 'fetch', 'origin', rev)
10971
10981
 
10972
10982
  #
10973
10983
 
@@ -11125,7 +11135,7 @@ class DeploySystemdManager:
11125
11135
 
11126
11136
  #
11127
11137
 
11128
- if sys.platform == 'linux':
11138
+ if sys.platform == 'linux' and shutil.which('systemctl') is not None:
11129
11139
  async def reload() -> None:
11130
11140
  await asyncio_subprocesses.check_call('systemctl', '--user', 'daemon-reload')
11131
11141
 
@@ -11614,6 +11624,8 @@ class DeployAppManager(DeployPathOwner):
11614
11624
  spec: DeployAppSpec,
11615
11625
  home: DeployHome,
11616
11626
  tags: DeployTagMap,
11627
+ *,
11628
+ conf_string_ns: ta.Optional[ta.Mapping[str, ta.Any]] = None,
11617
11629
  ) -> PreparedApp:
11618
11630
  spec_json = json_dumps_pretty(self._msh.marshal_obj(spec))
11619
11631
 
@@ -11670,9 +11682,17 @@ class DeployAppManager(DeployPathOwner):
11670
11682
  if spec.conf is not None:
11671
11683
  conf_dir = os.path.join(app_dir, 'conf')
11672
11684
  rkw.update(conf_dir=conf_dir)
11685
+
11686
+ conf_ns: ta.Dict[str, ta.Any] = dict(
11687
+ **(conf_string_ns or {}),
11688
+ app=spec.app.s,
11689
+ app_dir=app_dir.rstrip('/'),
11690
+ )
11691
+
11673
11692
  await self._conf.write_app_conf(
11674
11693
  spec.conf,
11675
11694
  conf_dir,
11695
+ string_ns=conf_ns,
11676
11696
  )
11677
11697
 
11678
11698
  #
@@ -11735,7 +11755,7 @@ class DeployAppManager(DeployPathOwner):
11735
11755
  ##
11736
11756
 
11737
11757
 
11738
- DEPLOY_TAG_DATETIME_FMT = '%Y%m%dT%H%M%SZ'
11758
+ DEPLOY_TAG_DATETIME_FMT = '%Y-%m-%d-T-%H-%M-%S-%f-Z'
11739
11759
 
11740
11760
 
11741
11761
  DeployManagerUtcClock = ta.NewType('DeployManagerUtcClock', Func0[datetime.datetime])
@@ -11888,8 +11908,9 @@ class DeployDriver:
11888
11908
 
11889
11909
  das: ta.Set[DeployApp] = {a.app for a in self._spec.apps}
11890
11910
  las: ta.Set[DeployApp] = set(self._spec.app_links.apps)
11891
- if (ras := das & las):
11892
- raise RuntimeError(f'Must not specify apps as both deploy and link: {sorted(a.s for a in ras)}')
11911
+ ras: ta.Set[DeployApp] = set(self._spec.app_links.removed_apps)
11912
+ check.empty(das & (las | ras))
11913
+ check.empty(las & ras)
11893
11914
 
11894
11915
  #
11895
11916
 
@@ -11935,10 +11956,10 @@ class DeployDriver:
11935
11956
  cad = abs_real_path(os.path.join(current_link, 'apps'))
11936
11957
  if os.path.exists(cad):
11937
11958
  for d in os.listdir(cad):
11938
- if (da := DeployApp(d)) not in das:
11959
+ if (da := DeployApp(d)) not in das and da not in ras:
11939
11960
  las.add(da)
11940
11961
 
11941
- for la in self._spec.app_links.apps:
11962
+ for la in las:
11942
11963
  await self._drive_app_link(
11943
11964
  la,
11944
11965
  current_link,
@@ -11968,10 +11989,16 @@ class DeployDriver:
11968
11989
  #
11969
11990
 
11970
11991
  async def _drive_app_deploy(self, app: DeployAppSpec) -> None:
11992
+ current_deploy_link = os.path.join(self._home, self._deploys.CURRENT_DEPLOY_LINK.render())
11993
+
11971
11994
  pa = await self._apps.prepare_app(
11972
11995
  app,
11973
11996
  self._home,
11974
11997
  self.tags,
11998
+ conf_string_ns=dict(
11999
+ deploy_home=self._home,
12000
+ current_deploy_link=current_deploy_link,
12001
+ ),
11975
12002
  )
11976
12003
 
11977
12004
  #
@@ -6481,6 +6481,12 @@ class ServerConfig:
6481
6481
  # TODO: implement - make sure to accept broken symlinks
6482
6482
  group_config_dirs: ta.Optional[ta.Sequence[str]] = None
6483
6483
 
6484
+ #
6485
+
6486
+ http_port: ta.Optional[int] = None
6487
+
6488
+ #
6489
+
6484
6490
  @classmethod
6485
6491
  def new(
6486
6492
  cls,
@@ -8354,7 +8360,7 @@ class HttpServer(HasDispatchers):
8354
8360
  def __init__(
8355
8361
  self,
8356
8362
  handler: Handler,
8357
- addr: Address = Address(('localhost', 8000)),
8363
+ addr: Address, # = Address(('localhost', 8000)),
8358
8364
  *,
8359
8365
  exit_stack: contextlib.ExitStack,
8360
8366
  ) -> None:
@@ -9617,16 +9623,19 @@ def bind_server(
9617
9623
 
9618
9624
  #
9619
9625
 
9620
- def _provide_http_handler(s: SupervisorHttpHandler) -> HttpServer.Handler:
9621
- return HttpServer.Handler(s.handle)
9626
+ if config.http_port is not None:
9627
+ def _provide_http_handler(s: SupervisorHttpHandler) -> HttpServer.Handler:
9628
+ return HttpServer.Handler(s.handle)
9622
9629
 
9623
- lst.extend([
9624
- inj.bind(HttpServer, singleton=True, eager=True),
9625
- inj.bind(HasDispatchers, array=True, to_key=HttpServer),
9630
+ lst.extend([
9631
+ inj.bind(HttpServer, singleton=True, eager=True),
9632
+ inj.bind(HasDispatchers, array=True, to_key=HttpServer),
9626
9633
 
9627
- inj.bind(SupervisorHttpHandler, singleton=True),
9628
- inj.bind(_provide_http_handler),
9629
- ])
9634
+ inj.bind(HttpServer.Address(('localhost', config.http_port))),
9635
+
9636
+ inj.bind(SupervisorHttpHandler, singleton=True),
9637
+ inj.bind(_provide_http_handler),
9638
+ ])
9630
9639
 
9631
9640
  #
9632
9641
 
@@ -248,6 +248,12 @@ class ServerConfig:
248
248
  # TODO: implement - make sure to accept broken symlinks
249
249
  group_config_dirs: ta.Optional[ta.Sequence[str]] = None
250
250
 
251
+ #
252
+
253
+ http_port: ta.Optional[int] = None
254
+
255
+ #
256
+
251
257
  @classmethod
252
258
  def new(
253
259
  cls,
@@ -60,7 +60,7 @@ class HttpServer(HasDispatchers):
60
60
  def __init__(
61
61
  self,
62
62
  handler: Handler,
63
- addr: Address = Address(('localhost', 8000)),
63
+ addr: Address, # = Address(('localhost', 8000)),
64
64
  *,
65
65
  exit_stack: contextlib.ExitStack,
66
66
  ) -> None:
@@ -131,16 +131,19 @@ def bind_server(
131
131
 
132
132
  #
133
133
 
134
- def _provide_http_handler(s: SupervisorHttpHandler) -> HttpServer.Handler:
135
- return HttpServer.Handler(s.handle)
134
+ if config.http_port is not None:
135
+ def _provide_http_handler(s: SupervisorHttpHandler) -> HttpServer.Handler:
136
+ return HttpServer.Handler(s.handle)
136
137
 
137
- lst.extend([
138
- inj.bind(HttpServer, singleton=True, eager=True),
139
- inj.bind(HasDispatchers, array=True, to_key=HttpServer),
138
+ lst.extend([
139
+ inj.bind(HttpServer, singleton=True, eager=True),
140
+ inj.bind(HasDispatchers, array=True, to_key=HttpServer),
140
141
 
141
- inj.bind(SupervisorHttpHandler, singleton=True),
142
- inj.bind(_provide_http_handler),
143
- ])
142
+ inj.bind(HttpServer.Address(('localhost', config.http_port))),
143
+
144
+ inj.bind(SupervisorHttpHandler, singleton=True),
145
+ inj.bind(_provide_http_handler),
146
+ ])
144
147
 
145
148
  #
146
149
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev191
3
+ Version: 0.0.0.dev192
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,9 +12,9 @@ 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.dev191
16
- Requires-Dist: omlish==0.0.0.dev191
17
- Requires-Dist: omserv==0.0.0.dev191
15
+ Requires-Dist: omdev==0.0.0.dev192
16
+ Requires-Dist: omlish==0.0.0.dev192
17
+ Requires-Dist: omserv==0.0.0.dev192
18
18
  Provides-Extra: all
19
19
  Requires-Dist: paramiko~=3.5; extra == "all"
20
20
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -1,6 +1,6 @@
1
- omdev==0.0.0.dev191
2
- omlish==0.0.0.dev191
3
- omserv==0.0.0.dev191
1
+ omdev==0.0.0.dev192
2
+ omlish==0.0.0.dev192
3
+ omserv==0.0.0.dev192
4
4
 
5
5
  [all]
6
6
  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.dev191'
15
+ version = '0.0.0.dev192'
16
16
  classifiers = [
17
17
  'License :: OSI Approved :: BSD License',
18
18
  'Development Status :: 2 - Pre-Alpha',
@@ -22,9 +22,9 @@ classifiers = [
22
22
  ]
23
23
  description = 'ominfra'
24
24
  dependencies = [
25
- 'omdev == 0.0.0.dev191',
26
- 'omlish == 0.0.0.dev191',
27
- 'omserv == 0.0.0.dev191',
25
+ 'omdev == 0.0.0.dev192',
26
+ 'omlish == 0.0.0.dev192',
27
+ 'omserv == 0.0.0.dev192',
28
28
  ]
29
29
 
30
30
  [project.optional-dependencies]
File without changes
File without changes