ominfra 0.0.0.dev191__py3-none-any.whl → 0.0.0.dev193__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ominfra/configs.py CHANGED
@@ -1,11 +1,10 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  # @omlish-lite
3
- import io
4
3
  import json
5
4
  import os.path
6
5
  import typing as ta
7
6
 
8
- from omdev.toml.parser import toml_loads
7
+ from omlish.formats.toml.parser import toml_loads
9
8
  from omlish.lite.check import check
10
9
  from omlish.lite.marshal import OBJ_MARSHALER_MANAGER
11
10
  from omlish.lite.marshal import ObjMarshalerManager
@@ -15,8 +14,6 @@ T = ta.TypeVar('T')
15
14
 
16
15
  ConfigMapping = ta.Mapping[str, ta.Any]
17
16
 
18
- IniConfigSectionSettingsMap = ta.Mapping[str, ta.Mapping[str, ta.Union[str, ta.Sequence[str]]]] # ta.TypeAlias
19
-
20
17
 
21
18
  ##
22
19
 
@@ -103,27 +100,3 @@ def build_config_named_children(
103
100
  seen.add(n)
104
101
 
105
102
  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()
@@ -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
  #
@@ -29,7 +29,7 @@ from omlish.os.paths import relative_symlink
29
29
  from omserv.nginx.configs import NginxConfigItems
30
30
  from omserv.nginx.configs import render_nginx_config_str
31
31
 
32
- from ....configs import render_ini_config
32
+ from omlish.formats.ini.sections import render_ini_sections
33
33
  from ..paths.paths import DeployPath
34
34
  from ..tags import DEPLOY_TAG_SEPARATOR
35
35
  from ..tags import DeployApp
@@ -100,7 +100,7 @@ class DeployConfManager:
100
100
 
101
101
  elif isinstance(ac, IniDeployAppConfContent):
102
102
  ini_sections = pcc(ac.sections)
103
- return strip_with_newline(render_ini_config(ini_sections))
103
+ return strip_with_newline(render_ini_sections(ini_sections))
104
104
 
105
105
  elif isinstance(ac, NginxDeployAppConfContent):
106
106
  nginx_items = NginxConfigItems.of(pcc(ac.items))
@@ -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(
@@ -6,7 +6,7 @@ import typing as ta
6
6
  from omlish.lite.check import check
7
7
  from omlish.lite.marshal import register_single_field_type_obj_marshaler
8
8
 
9
- from ....configs import IniConfigSectionSettingsMap
9
+ from omlish.formats.ini.sections import IniSectionSettingsMap
10
10
  from ..paths.specs import check_valid_deploy_spec_path
11
11
 
12
12
 
@@ -41,7 +41,7 @@ class JsonDeployAppConfContent(DeployAppConfContent):
41
41
  @register_single_field_type_obj_marshaler('sections')
42
42
  @dc.dataclass(frozen=True)
43
43
  class IniDeployAppConfContent(DeployAppConfContent):
44
- sections: IniConfigSectionSettingsMap
44
+ sections: IniSectionSettingsMap
45
45
 
46
46
 
47
47
  #
@@ -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
 
@@ -52,7 +52,7 @@ if sys.version_info < (3, 8):
52
52
  ########################################
53
53
 
54
54
 
55
- # ../../../../omdev/toml/parser.py
55
+ # ../../../../omlish/formats/toml/parser.py
56
56
  TomlParseFloat = ta.Callable[[str], ta.Any]
57
57
  TomlKey = ta.Tuple[str, ...]
58
58
  TomlPos = int # ta.TypeAlias
@@ -74,7 +74,6 @@ 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
78
77
 
79
78
  # ../../../threadworkers.py
80
79
  ThreadWorkerT = ta.TypeVar('ThreadWorkerT', bound='ThreadWorker')
@@ -84,7 +83,7 @@ SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull'] # ta.TypeAlia
84
83
 
85
84
 
86
85
  ########################################
87
- # ../../../../../omdev/toml/parser.py
86
+ # ../../../../../omlish/formats/toml/parser.py
88
87
  # SPDX-License-Identifier: MIT
89
88
  # SPDX-FileCopyrightText: 2021 Taneli Hukkinen
90
89
  # Licensed to PSF under a Contributor Agreement.
@@ -3371,30 +3370,6 @@ def build_config_named_children(
3371
3370
  return lst
3372
3371
 
3373
3372
 
3374
- ##
3375
-
3376
-
3377
- def render_ini_config(
3378
- settings_by_section: IniConfigSectionSettingsMap,
3379
- ) -> str:
3380
- out = io.StringIO()
3381
-
3382
- for i, (section, settings) in enumerate(settings_by_section.items()):
3383
- if i:
3384
- out.write('\n')
3385
-
3386
- out.write(f'[{section}]\n')
3387
-
3388
- for k, v in settings.items():
3389
- if isinstance(v, str):
3390
- out.write(f'{k}={v}\n')
3391
- else:
3392
- for vv in v:
3393
- out.write(f'{k}={vv}\n')
3394
-
3395
- return out.getvalue()
3396
-
3397
-
3398
3373
  ########################################
3399
3374
  # ../../../../journald/messages.py
3400
3375