ominfra 0.0.0.dev181__tar.gz → 0.0.0.dev183__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. {ominfra-0.0.0.dev181/ominfra.egg-info → ominfra-0.0.0.dev183}/PKG-INFO +3 -3
  2. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/configs.py +33 -0
  3. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/apps.py +1 -1
  4. ominfra-0.0.0.dev183/ominfra/manage/deploy/conf/inject.py +17 -0
  5. ominfra-0.0.0.dev181/ominfra/manage/deploy/conf.py → ominfra-0.0.0.dev183/ominfra/manage/deploy/conf/manager.py +28 -6
  6. ominfra-0.0.0.dev183/ominfra/manage/deploy/conf/specs.py +95 -0
  7. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/inject.py +9 -18
  8. ominfra-0.0.0.dev183/ominfra/manage/deploy/inject_.py +13 -0
  9. ominfra-0.0.0.dev183/ominfra/manage/deploy/paths/specs.py +10 -0
  10. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/specs.py +1 -59
  11. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/tags.py +2 -3
  12. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/scripts/journald2aws.py +42 -0
  13. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/scripts/manage.py +664 -548
  14. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/scripts/supervisor.py +42 -0
  15. ominfra-0.0.0.dev183/ominfra/tools/__init__.py +0 -0
  16. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183/ominfra.egg-info}/PKG-INFO +3 -3
  17. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra.egg-info/SOURCES.txt +6 -2
  18. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra.egg-info/requires.txt +2 -2
  19. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/pyproject.toml +3 -3
  20. ominfra-0.0.0.dev181/ominfra/systemd.py +0 -18
  21. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/LICENSE +0 -0
  22. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/MANIFEST.in +0 -0
  23. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/README.rst +0 -0
  24. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/.manifests.json +0 -0
  25. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/__about__.py +0 -0
  26. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/__init__.py +0 -0
  27. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/__init__.py +0 -0
  28. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/__init__.py +0 -0
  29. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/__main__.py +0 -0
  30. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/auth.py +0 -0
  31. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/cli.py +0 -0
  32. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/dataclasses.py +0 -0
  33. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  34. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  35. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  36. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/journald2aws/driver.py +0 -0
  37. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/journald2aws/main.py +0 -0
  38. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  39. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/logs.py +0 -0
  40. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/aws/metadata.py +0 -0
  41. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/gcp/__init__.py +0 -0
  42. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/clouds/gcp/auth.py +0 -0
  43. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/cmds.py +0 -0
  44. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/journald/__init__.py +0 -0
  45. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/journald/fields.py +0 -0
  46. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/journald/genmessages.py +0 -0
  47. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/journald/messages.py +0 -0
  48. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/journald/tailer.py +0 -0
  49. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/__init__.py +0 -0
  50. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/__main__.py +0 -0
  51. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/bootstrap.py +0 -0
  52. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/bootstrap_.py +0 -0
  53. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/commands/__init__.py +0 -0
  54. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/commands/base.py +0 -0
  55. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/commands/inject.py +0 -0
  56. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/commands/local.py +0 -0
  57. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/commands/marshal.py +0 -0
  58. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/commands/ping.py +0 -0
  59. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/commands/subprocess.py +0 -0
  60. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/commands/types.py +0 -0
  61. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/config.py +0 -0
  62. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/__init__.py +0 -0
  63. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/commands.py +0 -0
  64. {ominfra-0.0.0.dev181/ominfra/manage/deploy/paths → ominfra-0.0.0.dev183/ominfra/manage/deploy/conf}/__init__.py +0 -0
  65. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/config.py +0 -0
  66. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/deploy.py +0 -0
  67. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/driver.py +0 -0
  68. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/git.py +0 -0
  69. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/interp.py +0 -0
  70. {ominfra-0.0.0.dev181/ominfra/manage/remote → ominfra-0.0.0.dev183/ominfra/manage/deploy/paths}/__init__.py +0 -0
  71. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/paths/inject.py +0 -0
  72. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/paths/manager.py +0 -0
  73. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/paths/owners.py +0 -0
  74. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/paths/paths.py +0 -0
  75. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/paths/types.py +0 -0
  76. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/tmp.py +0 -0
  77. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/types.py +0 -0
  78. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/deploy/venvs.py +0 -0
  79. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/inject.py +0 -0
  80. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/main.py +0 -0
  81. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/marshal.py +0 -0
  82. {ominfra-0.0.0.dev181/ominfra/manage/system → ominfra-0.0.0.dev183/ominfra/manage/remote}/__init__.py +0 -0
  83. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/remote/_main.py +0 -0
  84. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/remote/channel.py +0 -0
  85. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/remote/config.py +0 -0
  86. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/remote/connection.py +0 -0
  87. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/remote/execution.py +0 -0
  88. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/remote/inject.py +0 -0
  89. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/remote/payload.py +0 -0
  90. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/remote/spawning.py +0 -0
  91. {ominfra-0.0.0.dev181/ominfra/manage/targets → ominfra-0.0.0.dev183/ominfra/manage/system}/__init__.py +0 -0
  92. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/system/commands.py +0 -0
  93. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/system/config.py +0 -0
  94. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/system/inject.py +0 -0
  95. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/system/packages.py +0 -0
  96. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/system/platforms.py +0 -0
  97. {ominfra-0.0.0.dev181/ominfra/scripts → ominfra-0.0.0.dev183/ominfra/manage/targets}/__init__.py +0 -0
  98. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/targets/bestpython.py +0 -0
  99. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/targets/bestpython.sh +0 -0
  100. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/targets/connection.py +0 -0
  101. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/targets/inject.py +0 -0
  102. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/manage/targets/targets.py +0 -0
  103. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/pyremote.py +0 -0
  104. {ominfra-0.0.0.dev181/ominfra/supervisor/utils → ominfra-0.0.0.dev183/ominfra/scripts}/__init__.py +0 -0
  105. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/ssh.py +0 -0
  106. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/LICENSE.txt +0 -0
  107. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/__init__.py +0 -0
  108. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/__main__.py +0 -0
  109. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/configs.py +0 -0
  110. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/dispatchers.py +0 -0
  111. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/dispatchersimpl.py +0 -0
  112. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/events.py +0 -0
  113. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/exceptions.py +0 -0
  114. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/groups.py +0 -0
  115. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/groupsimpl.py +0 -0
  116. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/http.py +0 -0
  117. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/inject.py +0 -0
  118. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/io.py +0 -0
  119. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/main.py +0 -0
  120. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/pipes.py +0 -0
  121. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/privileges.py +0 -0
  122. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/process.py +0 -0
  123. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/processimpl.py +0 -0
  124. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/setup.py +0 -0
  125. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/setupimpl.py +0 -0
  126. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/signals.py +0 -0
  127. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/spawning.py +0 -0
  128. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/spawningimpl.py +0 -0
  129. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/states.py +0 -0
  130. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/supervisor.py +0 -0
  131. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/types.py +0 -0
  132. {ominfra-0.0.0.dev181/ominfra/tailscale → ominfra-0.0.0.dev183/ominfra/supervisor/utils}/__init__.py +0 -0
  133. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/collections.py +0 -0
  134. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/diag.py +0 -0
  135. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/fds.py +0 -0
  136. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/fs.py +0 -0
  137. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/os.py +0 -0
  138. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/ostypes.py +0 -0
  139. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/signals.py +0 -0
  140. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/strings.py +0 -0
  141. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/supervisor/utils/users.py +0 -0
  142. {ominfra-0.0.0.dev181/ominfra/tools → ominfra-0.0.0.dev183/ominfra/tailscale}/__init__.py +0 -0
  143. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/tailscale/api.py +0 -0
  144. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/tailscale/cli.py +0 -0
  145. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/threadworkers.py +0 -0
  146. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra/tools/listresources.py +0 -0
  147. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra.egg-info/dependency_links.txt +0 -0
  148. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra.egg-info/entry_points.txt +0 -0
  149. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/ominfra.egg-info/top_level.txt +0 -0
  150. {ominfra-0.0.0.dev181 → ominfra-0.0.0.dev183}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev181
3
+ Version: 0.0.0.dev183
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.dev181
16
- Requires-Dist: omlish==0.0.0.dev181
15
+ Requires-Dist: omdev==0.0.0.dev183
16
+ Requires-Dist: omlish==0.0.0.dev183
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -1,5 +1,6 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  # @omlish-lite
3
+ import io
3
4
  import json
4
5
  import os.path
5
6
  import typing as ta
@@ -14,6 +15,11 @@ T = ta.TypeVar('T')
14
15
 
15
16
  ConfigMapping = ta.Mapping[str, ta.Any]
16
17
 
18
+ IniConfigSectionSettingsMap = ta.Mapping[str, ta.Mapping[str, ta.Union[str, ta.Sequence[str]]]] # ta.TypeAlias
19
+
20
+
21
+ ##
22
+
17
23
 
18
24
  def parse_config_file(
19
25
  name: str,
@@ -58,6 +64,9 @@ def read_config_file(
58
64
  return msh.unmarshal_obj(config_dct, cls)
59
65
 
60
66
 
67
+ ##
68
+
69
+
61
70
  def build_config_named_children(
62
71
  o: ta.Union[
63
72
  ta.Sequence[ConfigMapping],
@@ -94,3 +103,27 @@ def build_config_named_children(
94
103
  seen.add(n)
95
104
 
96
105
  return lst
106
+
107
+
108
+ ##
109
+
110
+
111
+ def render_ini_config(
112
+ settings_by_section: IniConfigSectionSettingsMap,
113
+ ) -> str:
114
+ out = io.StringIO()
115
+
116
+ for i, (section, settings) in enumerate(settings_by_section.items()):
117
+ if i:
118
+ out.write('\n')
119
+
120
+ out.write(f'[{section}]\n')
121
+
122
+ for k, v in settings.items():
123
+ if isinstance(v, str):
124
+ out.write(f'{k}={v}\n')
125
+ else:
126
+ for vv in v:
127
+ out.write(f'{k}={vv}\n')
128
+
129
+ return out.getvalue()
@@ -6,7 +6,7 @@ from omlish.lite.cached import cached_nullary
6
6
  from omlish.lite.check import check
7
7
  from omlish.os.paths import relative_symlink
8
8
 
9
- from .conf import DeployConfManager
9
+ from .conf.manager import DeployConfManager
10
10
  from .git import DeployGitManager
11
11
  from .paths.owners import DeployPathOwner
12
12
  from .paths.paths import DeployPath
@@ -0,0 +1,17 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.inject import InjectorBindingOrBindings
5
+ from omlish.lite.inject import InjectorBindings
6
+ from omlish.lite.inject import inj
7
+
8
+ from ..inject_ import bind_deploy_manager
9
+ from .manager import DeployConfManager
10
+
11
+
12
+ def bind_deploy_conf() -> InjectorBindings:
13
+ lst: ta.List[InjectorBindingOrBindings] = [
14
+ bind_deploy_manager(DeployConfManager),
15
+ ]
16
+
17
+ return inj.as_bindings(*lst)
@@ -20,20 +20,40 @@ import os.path
20
20
  import typing as ta
21
21
 
22
22
  from omlish.lite.check import check
23
+ from omlish.lite.json import json_dumps_pretty
24
+ from omlish.lite.strings import strip_with_newline
23
25
  from omlish.os.paths import is_path_in_dir
24
26
  from omlish.os.paths import relative_symlink
25
27
 
26
- from .paths.paths import DeployPath
28
+ from ....configs import render_ini_config
29
+ from ..paths.paths import DeployPath
30
+ from ..tags import DEPLOY_TAG_SEPARATOR
31
+ from ..tags import DeployApp
32
+ from ..tags import DeployConf
33
+ from ..tags import DeployTagMap
34
+ from .specs import DeployAppConfContent
27
35
  from .specs import DeployAppConfFile
28
36
  from .specs import DeployAppConfLink
29
37
  from .specs import DeployAppConfSpec
30
- from .tags import DEPLOY_TAG_SEPARATOR
31
- from .tags import DeployApp
32
- from .tags import DeployConf
33
- from .tags import DeployTagMap
38
+ from .specs import IniDeployAppConfContent
39
+ from .specs import JsonDeployAppConfContent
40
+ from .specs import RawDeployAppConfContent
34
41
 
35
42
 
36
43
  class DeployConfManager:
44
+ def _render_app_conf_content(self, ac: DeployAppConfContent) -> str:
45
+ if isinstance(ac, RawDeployAppConfContent):
46
+ return ac.body
47
+
48
+ elif isinstance(ac, JsonDeployAppConfContent):
49
+ return strip_with_newline(json_dumps_pretty(ac.obj))
50
+
51
+ elif isinstance(ac, IniDeployAppConfContent):
52
+ return strip_with_newline(render_ini_config(ac.sections))
53
+
54
+ else:
55
+ raise TypeError(ac)
56
+
37
57
  async def _write_app_conf_file(
38
58
  self,
39
59
  acf: DeployAppConfFile,
@@ -42,10 +62,12 @@ class DeployConfManager:
42
62
  conf_file = os.path.join(app_conf_dir, acf.path)
43
63
  check.arg(is_path_in_dir(app_conf_dir, conf_file))
44
64
 
65
+ body = self._render_app_conf_content(acf.content)
66
+
45
67
  os.makedirs(os.path.dirname(conf_file), exist_ok=True)
46
68
 
47
69
  with open(conf_file, 'w') as f: # noqa
48
- f.write(acf.body)
70
+ f.write(body)
49
71
 
50
72
  #
51
73
 
@@ -0,0 +1,95 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import abc
3
+ import dataclasses as dc
4
+ import typing as ta
5
+
6
+ from omlish.lite.check import check
7
+ from omlish.lite.marshal import register_single_field_type_obj_marshaler
8
+
9
+ from ....configs import IniConfigSectionSettingsMap
10
+ from ..paths.specs import check_valid_deploy_spec_path
11
+
12
+
13
+ ##
14
+
15
+
16
+ class DeployAppConfContent(abc.ABC): # noqa
17
+ pass
18
+
19
+
20
+ #
21
+
22
+
23
+ @register_single_field_type_obj_marshaler('body')
24
+ @dc.dataclass(frozen=True)
25
+ class RawDeployAppConfContent(DeployAppConfContent):
26
+ body: str
27
+
28
+
29
+ #
30
+
31
+
32
+ @register_single_field_type_obj_marshaler('obj')
33
+ @dc.dataclass(frozen=True)
34
+ class JsonDeployAppConfContent(DeployAppConfContent):
35
+ obj: ta.Any
36
+
37
+
38
+ #
39
+
40
+
41
+ @register_single_field_type_obj_marshaler('sections')
42
+ @dc.dataclass(frozen=True)
43
+ class IniDeployAppConfContent(DeployAppConfContent):
44
+ sections: IniConfigSectionSettingsMap
45
+
46
+
47
+ ##
48
+
49
+
50
+ @dc.dataclass(frozen=True)
51
+ class DeployAppConfFile:
52
+ path: str
53
+ content: DeployAppConfContent
54
+
55
+ def __post_init__(self) -> None:
56
+ check_valid_deploy_spec_path(self.path)
57
+
58
+
59
+ ##
60
+
61
+
62
+ @dc.dataclass(frozen=True)
63
+ class DeployAppConfLink: # noqa
64
+ """
65
+ May be either:
66
+ - @conf(.ext)* - links a single file in root of app conf dir to conf/@conf/@dst(.ext)*
67
+ - @conf/file - links a single file in a single subdir to conf/@conf/@dst--file
68
+ - @conf/ - links a directory in root of app conf dir to conf/@conf/@dst/
69
+ """
70
+
71
+ src: str
72
+
73
+ kind: ta.Literal['current_only', 'all_active'] = 'current_only'
74
+
75
+ def __post_init__(self) -> None:
76
+ check_valid_deploy_spec_path(self.src)
77
+ if '/' in self.src:
78
+ check.equal(self.src.count('/'), 1)
79
+
80
+
81
+ ##
82
+
83
+
84
+ @dc.dataclass(frozen=True)
85
+ class DeployAppConfSpec:
86
+ files: ta.Optional[ta.Sequence[DeployAppConfFile]] = None
87
+
88
+ links: ta.Optional[ta.Sequence[DeployAppConfLink]] = None
89
+
90
+ def __post_init__(self) -> None:
91
+ if self.files:
92
+ seen: ta.Set[str] = set()
93
+ for f in self.files:
94
+ check.not_in(f.path, seen)
95
+ seen.add(f.path)
@@ -14,16 +14,16 @@ from ..commands.inject import bind_command
14
14
  from .apps import DeployAppManager
15
15
  from .commands import DeployCommand
16
16
  from .commands import DeployCommandExecutor
17
- from .conf import DeployConfManager
17
+ from .conf.inject import bind_deploy_conf
18
18
  from .config import DeployConfig
19
19
  from .deploy import DeployManager
20
20
  from .driver import DeployDriver
21
21
  from .driver import DeployDriverFactory
22
22
  from .git import DeployGitManager
23
+ from .inject_ import bind_deploy_manager
23
24
  from .interp import InterpCommand
24
25
  from .interp import InterpCommandExecutor
25
26
  from .paths.inject import bind_deploy_paths
26
- from .paths.owners import DeployPathOwner
27
27
  from .specs import DeploySpec
28
28
  from .tags import DeployTime
29
29
  from .tmp import DeployHomeAtomics
@@ -90,6 +90,8 @@ def bind_deploy(
90
90
  lst: ta.List[InjectorBindingOrBindings] = [
91
91
  inj.bind(deploy_config),
92
92
 
93
+ bind_deploy_conf(),
94
+
93
95
  bind_deploy_paths(),
94
96
 
95
97
  bind_deploy_scope(),
@@ -97,27 +99,16 @@ def bind_deploy(
97
99
 
98
100
  #
99
101
 
100
- def bind_manager(cls: type) -> InjectorBindings:
101
- return inj.as_bindings(
102
- inj.bind(cls, singleton=True),
103
-
104
- *([inj.bind(DeployPathOwner, to_key=cls, array=True)] if issubclass(cls, DeployPathOwner) else []),
105
- )
106
-
107
- #
108
-
109
102
  lst.extend([
110
- bind_manager(DeployAppManager),
111
-
112
- bind_manager(DeployConfManager),
103
+ bind_deploy_manager(DeployAppManager),
113
104
 
114
- bind_manager(DeployGitManager),
105
+ bind_deploy_manager(DeployGitManager),
115
106
 
116
- bind_manager(DeployManager),
107
+ bind_deploy_manager(DeployManager),
117
108
 
118
- bind_manager(DeployTmpManager),
109
+ bind_deploy_manager(DeployTmpManager),
119
110
 
120
- bind_manager(DeployVenvManager),
111
+ bind_deploy_manager(DeployVenvManager),
121
112
  ])
122
113
 
123
114
  #
@@ -0,0 +1,13 @@
1
+ # ruff: noqa: UP006 UP007
2
+ from omlish.lite.inject import InjectorBindings
3
+ from omlish.lite.inject import inj
4
+
5
+ from .paths.owners import DeployPathOwner
6
+
7
+
8
+ def bind_deploy_manager(cls: type) -> InjectorBindings:
9
+ return inj.as_bindings(
10
+ inj.bind(cls, singleton=True),
11
+
12
+ *([inj.bind(DeployPathOwner, to_key=cls, array=True)] if issubclass(cls, DeployPathOwner) else []),
13
+ )
@@ -0,0 +1,10 @@
1
+ # ruff: noqa: UP006 UP007
2
+ from omlish.lite.check import check
3
+
4
+
5
+ def check_valid_deploy_spec_path(s: str) -> str:
6
+ check.non_empty_str(s)
7
+ for c in ['..', '//']:
8
+ check.not_in(c, s)
9
+ check.arg(not s.startswith('/'))
10
+ return s
@@ -7,6 +7,7 @@ import typing as ta
7
7
  from omlish.lite.cached import cached_nullary
8
8
  from omlish.lite.check import check
9
9
 
10
+ from .conf.specs import DeployAppConfSpec
10
11
  from .tags import DeployApp
11
12
  from .tags import DeployAppKey
12
13
  from .tags import DeployKey
@@ -21,14 +22,6 @@ KeyDeployTagT = ta.TypeVar('KeyDeployTagT', bound='KeyDeployTag')
21
22
  ##
22
23
 
23
24
 
24
- def check_valid_deploy_spec_path(s: str) -> str:
25
- check.non_empty_str(s)
26
- for c in ['..', '//']:
27
- check.not_in(c, s)
28
- check.arg(not s.startswith('/'))
29
- return s
30
-
31
-
32
25
  class DeploySpecKeyed(ta.Generic[KeyDeployTagT]):
33
26
  @cached_nullary
34
27
  def _key_str(self) -> str:
@@ -83,57 +76,6 @@ class DeployVenvSpec:
83
76
  ##
84
77
 
85
78
 
86
- @dc.dataclass(frozen=True)
87
- class DeployAppConfFile:
88
- path: str
89
- body: str
90
-
91
- def __post_init__(self) -> None:
92
- check_valid_deploy_spec_path(self.path)
93
-
94
-
95
- #
96
-
97
-
98
- @dc.dataclass(frozen=True)
99
- class DeployAppConfLink: # noqa
100
- """
101
- May be either:
102
- - @conf(.ext)* - links a single file in root of app conf dir to conf/@conf/@dst(.ext)*
103
- - @conf/file - links a single file in a single subdir to conf/@conf/@dst--file
104
- - @conf/ - links a directory in root of app conf dir to conf/@conf/@dst/
105
- """
106
-
107
- src: str
108
-
109
- kind: ta.Literal['current_only', 'all_active'] = 'current_only'
110
-
111
- def __post_init__(self) -> None:
112
- check_valid_deploy_spec_path(self.src)
113
- if '/' in self.src:
114
- check.equal(self.src.count('/'), 1)
115
-
116
-
117
- #
118
-
119
-
120
- @dc.dataclass(frozen=True)
121
- class DeployAppConfSpec:
122
- files: ta.Optional[ta.Sequence[DeployAppConfFile]] = None
123
-
124
- links: ta.Optional[ta.Sequence[DeployAppConfLink]] = None
125
-
126
- def __post_init__(self) -> None:
127
- if self.files:
128
- seen: ta.Set[str] = set()
129
- for f in self.files:
130
- check.not_in(f.path, seen)
131
- seen.add(f.path)
132
-
133
-
134
- ##
135
-
136
-
137
79
  @dc.dataclass(frozen=True)
138
80
  class DeployAppSpec(DeploySpecKeyed[DeployAppKey]):
139
81
  app: DeployApp
@@ -4,8 +4,7 @@ import dataclasses as dc
4
4
  import typing as ta
5
5
 
6
6
  from omlish.lite.check import check
7
- from omlish.lite.marshal import SingleFieldObjMarshaler
8
- from omlish.lite.marshal import register_type_obj_marshaler
7
+ from omlish.lite.marshal import register_single_field_type_obj_marshaler
9
8
 
10
9
 
11
10
  ##
@@ -84,7 +83,7 @@ def _register_deploy_tag(cls):
84
83
  _DEPLOY_TAGS_BY_NAME[cls.tag_name] = cls
85
84
  _DEPLOY_TAGS_BY_KWARG[cls.tag_kwarg] = cls
86
85
 
87
- register_type_obj_marshaler(cls, SingleFieldObjMarshaler(cls, 's'))
86
+ register_single_field_type_obj_marshaler('s', cls)
88
87
 
89
88
  return cls
90
89
 
@@ -74,6 +74,7 @@ ExitStackedT = ta.TypeVar('ExitStackedT', bound='ExitStacked')
74
74
 
75
75
  # ../../../configs.py
76
76
  ConfigMapping = ta.Mapping[str, ta.Any]
77
+ IniConfigSectionSettingsMap = ta.Mapping[str, ta.Mapping[str, ta.Union[str, ta.Sequence[str]]]] # ta.TypeAlias
77
78
 
78
79
  # ../../../threadworkers.py
79
80
  ThreadWorkerT = ta.TypeVar('ThreadWorkerT', bound='ThreadWorker')
@@ -2804,6 +2805,17 @@ def register_type_obj_marshaler(ty: type, om: ObjMarshaler) -> None:
2804
2805
  _REGISTERED_OBJ_MARSHALERS_BY_TYPE[ty] = om
2805
2806
 
2806
2807
 
2808
+ def register_single_field_type_obj_marshaler(fld, ty=None):
2809
+ def inner(ty): # noqa
2810
+ register_type_obj_marshaler(ty, SingleFieldObjMarshaler(ty, fld))
2811
+ return ty
2812
+
2813
+ if ty is not None:
2814
+ return inner(ty)
2815
+ else:
2816
+ return inner
2817
+
2818
+
2807
2819
  ##
2808
2820
 
2809
2821
 
@@ -3261,6 +3273,9 @@ class AwsLogMessageBuilder:
3261
3273
  # ../../../../configs.py
3262
3274
 
3263
3275
 
3276
+ ##
3277
+
3278
+
3264
3279
  def parse_config_file(
3265
3280
  name: str,
3266
3281
  f: ta.TextIO,
@@ -3304,6 +3319,9 @@ def read_config_file(
3304
3319
  return msh.unmarshal_obj(config_dct, cls)
3305
3320
 
3306
3321
 
3322
+ ##
3323
+
3324
+
3307
3325
  def build_config_named_children(
3308
3326
  o: ta.Union[
3309
3327
  ta.Sequence[ConfigMapping],
@@ -3342,6 +3360,30 @@ def build_config_named_children(
3342
3360
  return lst
3343
3361
 
3344
3362
 
3363
+ ##
3364
+
3365
+
3366
+ def render_ini_config(
3367
+ settings_by_section: IniConfigSectionSettingsMap,
3368
+ ) -> str:
3369
+ out = io.StringIO()
3370
+
3371
+ for i, (section, settings) in enumerate(settings_by_section.items()):
3372
+ if i:
3373
+ out.write('\n')
3374
+
3375
+ out.write(f'[{section}]\n')
3376
+
3377
+ for k, v in settings.items():
3378
+ if isinstance(v, str):
3379
+ out.write(f'{k}={v}\n')
3380
+ else:
3381
+ for vv in v:
3382
+ out.write(f'{k}={vv}\n')
3383
+
3384
+ return out.getvalue()
3385
+
3386
+
3345
3387
  ########################################
3346
3388
  # ../../../../journald/messages.py
3347
3389