ominfra 0.0.0.dev176__py3-none-any.whl → 0.0.0.dev178__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.
@@ -20,16 +20,12 @@ class DeployAppManager(DeployPathOwner):
20
20
  def __init__(
21
21
  self,
22
22
  *,
23
- deploy_home: ta.Optional[DeployHome] = None,
24
-
25
23
  conf: DeployConfManager,
26
24
  git: DeployGitManager,
27
25
  venvs: DeployVenvManager,
28
26
  ) -> None:
29
27
  super().__init__()
30
28
 
31
- self._deploy_home = deploy_home
32
-
33
29
  self._conf = conf
34
30
  self._git = git
35
31
  self._venvs = venvs
@@ -70,12 +66,13 @@ class DeployAppManager(DeployPathOwner):
70
66
  async def prepare_app(
71
67
  self,
72
68
  spec: DeployAppSpec,
69
+ home: DeployHome,
73
70
  tags: DeployTagMap,
74
71
  ) -> None:
75
- deploy_home = check.non_empty_str(self._deploy_home)
72
+ check.non_empty_str(home)
76
73
 
77
74
  def build_path(pth: DeployPath) -> str:
78
- return os.path.join(deploy_home, pth.render(tags))
75
+ return os.path.join(home, pth.render(tags))
79
76
 
80
77
  app_dir = build_path(self._APP_DIR)
81
78
  deploy_dir = build_path(self._DEPLOY_DIR)
@@ -85,7 +82,7 @@ class DeployAppManager(DeployPathOwner):
85
82
 
86
83
  os.makedirs(deploy_dir, exist_ok=True)
87
84
 
88
- deploying_link = os.path.join(deploy_home, 'deploys/deploying')
85
+ deploying_link = os.path.join(home, 'deploys/deploying')
89
86
  if os.path.exists(deploying_link):
90
87
  os.unlink(deploying_link)
91
88
  relative_symlink(
@@ -132,7 +129,7 @@ class DeployAppManager(DeployPathOwner):
132
129
  # else:
133
130
  # os.makedirs(os.path.join(dst, os.path.relpath(dp2, src)))
134
131
 
135
- current_link = os.path.join(deploy_home, 'deploys/current')
132
+ current_link = os.path.join(home, 'deploys/current')
136
133
 
137
134
  # if os.path.exists(current_link):
138
135
  # mirror_symlinks(
@@ -149,6 +146,7 @@ class DeployAppManager(DeployPathOwner):
149
146
  app_git_dir = os.path.join(app_dir, 'git')
150
147
  await self._git.checkout(
151
148
  spec.git,
149
+ home,
152
150
  app_git_dir,
153
151
  )
154
152
 
@@ -158,6 +156,7 @@ class DeployAppManager(DeployPathOwner):
158
156
  app_venv_dir = os.path.join(app_dir, 'venv')
159
157
  await self._venvs.setup_venv(
160
158
  spec.venv,
159
+ home,
161
160
  app_git_dir,
162
161
  app_venv_dir,
163
162
  )
@@ -5,7 +5,7 @@ from omlish.lite.logs import log
5
5
 
6
6
  from ..commands.base import Command
7
7
  from ..commands.base import CommandExecutor
8
- from .deploy import DeployManager
8
+ from .driver import DeployDriverFactory
9
9
  from .specs import DeploySpec
10
10
 
11
11
 
@@ -23,11 +23,12 @@ class DeployCommand(Command['DeployCommand.Output']):
23
23
 
24
24
  @dc.dataclass(frozen=True)
25
25
  class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
26
- _deploy: DeployManager
26
+ _driver_factory: DeployDriverFactory
27
27
 
28
28
  async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
29
29
  log.info('Deploying! %r', cmd.spec)
30
30
 
31
- await self._deploy.run_deploy(cmd.spec)
31
+ with self._driver_factory(cmd.spec) as driver:
32
+ await driver.drive_deploy()
32
33
 
33
34
  return DeployCommand.Output()
@@ -31,21 +31,9 @@ from .tags import DEPLOY_TAG_SEPARATOR
31
31
  from .tags import DeployApp
32
32
  from .tags import DeployConf
33
33
  from .tags import DeployTagMap
34
- from .types import DeployHome
35
34
 
36
35
 
37
36
  class DeployConfManager:
38
- def __init__(
39
- self,
40
- *,
41
- deploy_home: ta.Optional[DeployHome] = None,
42
- ) -> None:
43
- super().__init__()
44
-
45
- self._deploy_home = deploy_home
46
-
47
- #
48
-
49
37
  async def _write_app_conf_file(
50
38
  self,
51
39
  acf: DeployAppConfFile,
@@ -1,6 +1,5 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  import dataclasses as dc
3
- import typing as ta
4
3
 
5
4
 
6
5
  ##
@@ -8,4 +7,4 @@ import typing as ta
8
7
 
9
8
  @dc.dataclass(frozen=True)
10
9
  class DeployConfig:
11
- deploy_home: ta.Optional[str] = None
10
+ pass
@@ -4,11 +4,6 @@ import typing as ta
4
4
 
5
5
  from omlish.lite.typing import Func0
6
6
 
7
- from .apps import DeployAppManager
8
- from .paths.manager import DeployPathsManager
9
- from .specs import DeploySpec
10
- from .tags import DeployAppRev
11
- from .tags import DeployTagMap
12
7
  from .tags import DeployTime
13
8
 
14
9
 
@@ -22,16 +17,11 @@ class DeployManager:
22
17
  def __init__(
23
18
  self,
24
19
  *,
25
- apps: DeployAppManager,
26
- paths: DeployPathsManager,
27
20
 
28
21
  utc_clock: ta.Optional[DeployManagerUtcClock] = None,
29
22
  ):
30
23
  super().__init__()
31
24
 
32
- self._apps = apps
33
- self._paths = paths
34
-
35
25
  self._utc_clock = utc_clock
36
26
 
37
27
  def _utc_now(self) -> datetime.datetime:
@@ -40,32 +30,5 @@ class DeployManager:
40
30
  else:
41
31
  return datetime.datetime.now(tz=datetime.timezone.utc) # noqa
42
32
 
43
- def _make_deploy_time(self) -> DeployTime:
33
+ def make_deploy_time(self) -> DeployTime:
44
34
  return DeployTime(self._utc_now().strftime(DEPLOY_TAG_DATETIME_FMT))
45
-
46
- async def run_deploy(
47
- self,
48
- spec: DeploySpec,
49
- ) -> None:
50
- self._paths.validate_deploy_paths()
51
-
52
- #
53
-
54
- deploy_tags = DeployTagMap(
55
- self._make_deploy_time(),
56
- spec.key(),
57
- )
58
-
59
- #
60
-
61
- for app in spec.apps:
62
- app_tags = deploy_tags.add(
63
- app.app,
64
- app.key(),
65
- DeployAppRev(app.git.rev),
66
- )
67
-
68
- await self._apps.prepare_app(
69
- app,
70
- app_tags,
71
- )
@@ -0,0 +1,71 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import os.path
3
+ import typing as ta
4
+
5
+ from omlish.lite.check import check
6
+ from omlish.lite.typing import Func1
7
+
8
+ from .apps import DeployAppManager
9
+ from .deploy import DeployManager
10
+ from .paths.manager import DeployPathsManager
11
+ from .specs import DeploySpec
12
+ from .tags import DeployAppRev
13
+ from .tags import DeployTagMap
14
+ from .types import DeployHome
15
+
16
+
17
+ class DeployDriverFactory(Func1[DeploySpec, ta.ContextManager['DeployDriver']]):
18
+ pass
19
+
20
+
21
+ class DeployDriver:
22
+ def __init__(
23
+ self,
24
+ *,
25
+ spec: DeploySpec,
26
+
27
+ deploys: DeployManager,
28
+ paths: DeployPathsManager,
29
+ apps: DeployAppManager,
30
+ ) -> None:
31
+ super().__init__()
32
+
33
+ self._spec = spec
34
+
35
+ self._deploys = deploys
36
+ self._paths = paths
37
+ self._apps = apps
38
+
39
+ async def drive_deploy(self) -> None:
40
+ self._paths.validate_deploy_paths()
41
+
42
+ #
43
+
44
+ hs = check.non_empty_str(self._spec.home)
45
+ hs = os.path.expanduser(hs)
46
+ hs = os.path.realpath(hs)
47
+ hs = os.path.abspath(hs)
48
+
49
+ home = DeployHome(hs)
50
+
51
+ #
52
+
53
+ deploy_tags = DeployTagMap(
54
+ self._deploys.make_deploy_time(),
55
+ self._spec.key(),
56
+ )
57
+
58
+ #
59
+
60
+ for app in self._spec.apps:
61
+ app_tags = deploy_tags.add(
62
+ app.app,
63
+ app.key(),
64
+ DeployAppRev(app.git.rev),
65
+ )
66
+
67
+ await self._apps.prepare_app(
68
+ app,
69
+ home,
70
+ app_tags,
71
+ )
@@ -15,11 +15,11 @@ import typing as ta
15
15
  from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
16
16
  from omlish.lite.cached import async_cached_nullary
17
17
  from omlish.lite.check import check
18
- from omlish.os.atomics import AtomicPathSwapping
19
18
 
20
19
  from .paths.owners import SingleDirDeployPathOwner
21
20
  from .specs import DeployGitRepo
22
21
  from .specs import DeployGitSpec
22
+ from .tmp import DeployHomeAtomics
23
23
  from .types import DeployHome
24
24
  from .types import DeployRev
25
25
 
@@ -31,12 +31,10 @@ class DeployGitManager(SingleDirDeployPathOwner):
31
31
  def __init__(
32
32
  self,
33
33
  *,
34
- deploy_home: ta.Optional[DeployHome] = None,
35
- atomics: AtomicPathSwapping,
34
+ atomics: DeployHomeAtomics,
36
35
  ) -> None:
37
36
  super().__init__(
38
37
  owned_dir='git',
39
- deploy_home=deploy_home,
40
38
  )
41
39
 
42
40
  self._atomics = atomics
@@ -48,13 +46,15 @@ class DeployGitManager(SingleDirDeployPathOwner):
48
46
  self,
49
47
  git: 'DeployGitManager',
50
48
  repo: DeployGitRepo,
49
+ home: DeployHome,
51
50
  ) -> None:
52
51
  super().__init__()
53
52
 
54
53
  self._git = git
55
54
  self._repo = repo
55
+ self._home = home
56
56
  self._dir = os.path.join(
57
- self._git._make_dir(), # noqa
57
+ self._git._make_dir(home), # noqa
58
58
  check.non_empty_str(repo.host),
59
59
  check.non_empty_str(repo.path),
60
60
  )
@@ -97,7 +97,7 @@ class DeployGitManager(SingleDirDeployPathOwner):
97
97
 
98
98
  async def checkout(self, spec: DeployGitSpec, dst_dir: str) -> None:
99
99
  check.state(not os.path.exists(dst_dir))
100
- with self._git._atomics.begin_atomic_path_swap( # noqa
100
+ with self._git._atomics(self._home).begin_atomic_path_swap( # noqa
101
101
  'dir',
102
102
  dst_dir,
103
103
  auto_commit=True,
@@ -112,16 +112,31 @@ class DeployGitManager(SingleDirDeployPathOwner):
112
112
  await dst_call('git', 'fetch', '--depth=1', 'local', spec.rev)
113
113
  await dst_call('git', 'checkout', spec.rev, *(spec.subtrees or []))
114
114
 
115
- def get_repo_dir(self, repo: DeployGitRepo) -> RepoDir:
115
+ def get_repo_dir(
116
+ self,
117
+ repo: DeployGitRepo,
118
+ home: DeployHome,
119
+ ) -> RepoDir:
116
120
  try:
117
121
  return self._repo_dirs[repo]
118
122
  except KeyError:
119
- repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(self, repo)
123
+ repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(
124
+ self,
125
+ repo,
126
+ home,
127
+ )
120
128
  return repo_dir
121
129
 
122
130
  async def checkout(
123
131
  self,
124
132
  spec: DeployGitSpec,
133
+ home: DeployHome,
125
134
  dst_dir: str,
126
135
  ) -> None:
127
- await self.get_repo_dir(spec.repo).checkout(spec, dst_dir)
136
+ await self.get_repo_dir(
137
+ spec.repo,
138
+ home,
139
+ ).checkout(
140
+ spec,
141
+ dst_dir,
142
+ )
@@ -1,11 +1,12 @@
1
1
  # ruff: noqa: UP006 UP007
2
- import os.path
2
+ import contextlib
3
3
  import typing as ta
4
4
 
5
+ from omlish.lite.inject import ContextvarInjectorScope
6
+ from omlish.lite.inject import Injector
5
7
  from omlish.lite.inject import InjectorBindingOrBindings
6
8
  from omlish.lite.inject import InjectorBindings
7
9
  from omlish.lite.inject import inj
8
- from omlish.os.atomics import AtomicPathSwapping
9
10
 
10
11
  from ..commands.inject import bind_command
11
12
  from .apps import DeployAppManager
@@ -14,16 +15,23 @@ from .commands import DeployCommandExecutor
14
15
  from .conf import DeployConfManager
15
16
  from .config import DeployConfig
16
17
  from .deploy import DeployManager
18
+ from .driver import DeployDriver
19
+ from .driver import DeployDriverFactory
17
20
  from .git import DeployGitManager
18
21
  from .interp import InterpCommand
19
22
  from .interp import InterpCommandExecutor
20
23
  from .paths.inject import bind_deploy_paths
21
24
  from .paths.owners import DeployPathOwner
25
+ from .specs import DeploySpec
26
+ from .tmp import DeployHomeAtomics
22
27
  from .tmp import DeployTmpManager
23
- from .types import DeployHome
24
28
  from .venvs import DeployVenvManager
25
29
 
26
30
 
31
+ class DeployInjectorScope(ContextvarInjectorScope):
32
+ pass
33
+
34
+
27
35
  def bind_deploy(
28
36
  *,
29
37
  deploy_config: DeployConfig,
@@ -55,13 +63,37 @@ def bind_deploy(
55
63
  bind_manager(DeployManager),
56
64
 
57
65
  bind_manager(DeployTmpManager),
58
- inj.bind(AtomicPathSwapping, to_key=DeployTmpManager),
59
66
 
60
67
  bind_manager(DeployVenvManager),
61
68
  ])
62
69
 
63
70
  #
64
71
 
72
+ def provide_deploy_home_atomics(tmp: DeployTmpManager) -> DeployHomeAtomics:
73
+ return DeployHomeAtomics(tmp.get_swapping)
74
+ lst.append(inj.bind(provide_deploy_home_atomics, singleton=True))
75
+
76
+ #
77
+
78
+ def provide_deploy_driver_factory(injector: Injector, sc: DeployInjectorScope) -> DeployDriverFactory:
79
+ @contextlib.contextmanager
80
+ def factory(spec: DeploySpec) -> ta.Iterator[DeployDriver]:
81
+ with sc.enter({
82
+ inj.as_key(DeploySpec): spec,
83
+ }):
84
+ yield injector[DeployDriver]
85
+ return DeployDriverFactory(factory)
86
+ lst.append(inj.bind(provide_deploy_driver_factory, singleton=True))
87
+
88
+ lst.extend([
89
+ inj.bind_scope(DeployInjectorScope),
90
+ inj.bind_scope_seed(DeploySpec, DeployInjectorScope),
91
+
92
+ inj.bind(DeployDriver, in_=DeployInjectorScope),
93
+ ])
94
+
95
+ #
96
+
65
97
  lst.extend([
66
98
  bind_command(DeployCommand, DeployCommandExecutor),
67
99
  bind_command(InterpCommand, InterpCommandExecutor),
@@ -69,8 +101,4 @@ def bind_deploy(
69
101
 
70
102
  #
71
103
 
72
- if (dh := deploy_config.deploy_home) is not None:
73
- dh = os.path.abspath(os.path.expanduser(dh))
74
- lst.append(inj.bind(dh, key=DeployHome))
75
-
76
104
  return inj.as_bindings(*lst)
@@ -3,7 +3,6 @@ import typing as ta
3
3
 
4
4
  from omlish.lite.cached import cached_nullary
5
5
 
6
- from ..types import DeployHome
7
6
  from .owners import DeployPathOwner
8
7
  from .owners import DeployPathOwners
9
8
  from .paths import DeployPath
@@ -14,12 +13,10 @@ class DeployPathsManager:
14
13
  def __init__(
15
14
  self,
16
15
  *,
17
- deploy_home: ta.Optional[DeployHome],
18
16
  deploy_path_owners: DeployPathOwners,
19
17
  ) -> None:
20
18
  super().__init__()
21
19
 
22
- self._deploy_home = deploy_home
23
20
  self._deploy_path_owners = deploy_path_owners
24
21
 
25
22
  @cached_nullary
@@ -3,7 +3,6 @@ import abc
3
3
  import os.path
4
4
  import typing as ta
5
5
 
6
- from omlish.lite.cached import cached_nullary
7
6
  from omlish.lite.check import check
8
7
 
9
8
  from ..types import DeployHome
@@ -24,7 +23,6 @@ class SingleDirDeployPathOwner(DeployPathOwner, abc.ABC):
24
23
  self,
25
24
  *args: ta.Any,
26
25
  owned_dir: str,
27
- deploy_home: ta.Optional[DeployHome],
28
26
  **kwargs: ta.Any,
29
27
  ) -> None:
30
28
  super().__init__(*args, **kwargs)
@@ -32,17 +30,13 @@ class SingleDirDeployPathOwner(DeployPathOwner, abc.ABC):
32
30
  check.not_in('/', owned_dir)
33
31
  self._owned_dir: str = check.non_empty_str(owned_dir)
34
32
 
35
- self._deploy_home = deploy_home
36
-
37
33
  self._owned_deploy_paths = frozenset([DeployPath.parse(self._owned_dir + '/')])
38
34
 
39
- @cached_nullary
40
- def _dir(self) -> str:
41
- return os.path.join(check.non_empty_str(self._deploy_home), self._owned_dir)
35
+ def _dir(self, home: DeployHome) -> str:
36
+ return os.path.join(check.non_empty_str(home), self._owned_dir)
42
37
 
43
- @cached_nullary
44
- def _make_dir(self) -> str:
45
- if not os.path.isdir(d := self._dir()):
38
+ def _make_dir(self, home: DeployHome) -> str:
39
+ if not os.path.isdir(d := self._dir(home)):
46
40
  os.makedirs(d, exist_ok=True)
47
41
  return d
48
42
 
@@ -11,6 +11,7 @@ from .tags import DeployApp
11
11
  from .tags import DeployAppKey
12
12
  from .tags import DeployKey
13
13
  from .tags import KeyDeployTag # noqa
14
+ from .types import DeployHome
14
15
  from .types import DeployRev
15
16
 
16
17
 
@@ -153,9 +154,13 @@ class DeployAppSpec(DeploySpecKeyed[DeployAppKey]):
153
154
 
154
155
  @dc.dataclass(frozen=True)
155
156
  class DeploySpec(DeploySpecKeyed[DeployKey]):
157
+ home: DeployHome
158
+
156
159
  apps: ta.Sequence[DeployAppSpec]
157
160
 
158
161
  def __post_init__(self) -> None:
162
+ check.non_empty_str(self.home)
163
+
159
164
  seen: ta.Set[DeployApp] = set()
160
165
  for a in self.apps:
161
166
  if a.app in seen:
@@ -1,10 +1,6 @@
1
1
  # ruff: noqa: UP006 UP007
2
- import typing as ta
3
-
4
- from omlish.lite.cached import cached_nullary
5
2
  from omlish.lite.check import check
6
- from omlish.os.atomics import AtomicPathSwap
7
- from omlish.os.atomics import AtomicPathSwapKind
3
+ from omlish.lite.typing import Func1
8
4
  from omlish.os.atomics import AtomicPathSwapping
9
5
  from omlish.os.atomics import TempDirAtomicPathSwapping
10
6
 
@@ -12,35 +8,20 @@ from .paths.owners import SingleDirDeployPathOwner
12
8
  from .types import DeployHome
13
9
 
14
10
 
11
+ class DeployHomeAtomics(Func1[DeployHome, AtomicPathSwapping]):
12
+ pass
13
+
14
+
15
15
  class DeployTmpManager(
16
16
  SingleDirDeployPathOwner,
17
- AtomicPathSwapping,
18
17
  ):
19
- def __init__(
20
- self,
21
- *,
22
- deploy_home: ta.Optional[DeployHome] = None,
23
- ) -> None:
18
+ def __init__(self) -> None:
24
19
  super().__init__(
25
20
  owned_dir='tmp',
26
- deploy_home=deploy_home,
27
21
  )
28
22
 
29
- @cached_nullary
30
- def _swapping(self) -> AtomicPathSwapping:
23
+ def get_swapping(self, home: DeployHome) -> AtomicPathSwapping:
31
24
  return TempDirAtomicPathSwapping(
32
- temp_dir=self._make_dir(),
33
- root_dir=check.non_empty_str(self._deploy_home),
34
- )
35
-
36
- def begin_atomic_path_swap(
37
- self,
38
- kind: AtomicPathSwapKind,
39
- dst_path: str,
40
- **kwargs: ta.Any,
41
- ) -> AtomicPathSwap:
42
- return self._swapping().begin_atomic_path_swap(
43
- kind,
44
- dst_path,
45
- **kwargs,
25
+ temp_dir=self._make_dir(home),
26
+ root_dir=check.non_empty_str(home),
46
27
  )
@@ -10,24 +10,16 @@ from omdev.interp.resolvers import DEFAULT_INTERP_RESOLVER
10
10
  from omdev.interp.types import InterpSpecifier
11
11
  from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
12
12
  from omlish.lite.check import check
13
- from omlish.os.atomics import AtomicPathSwapping
14
13
 
15
14
  from .specs import DeployVenvSpec
15
+ from .types import DeployHome
16
16
 
17
17
 
18
18
  class DeployVenvManager:
19
- def __init__(
20
- self,
21
- *,
22
- atomics: AtomicPathSwapping,
23
- ) -> None:
24
- super().__init__()
25
-
26
- self._atomics = atomics
27
-
28
19
  async def setup_venv(
29
20
  self,
30
21
  spec: DeployVenvSpec,
22
+ home: DeployHome,
31
23
  git_dir: str,
32
24
  venv_dir: str,
33
25
  ) -> None:
ominfra/manage/main.py CHANGED
@@ -35,8 +35,6 @@ from .targets.targets import ManageTarget
35
35
 
36
36
  @dc.dataclass(frozen=True)
37
37
  class ManageConfig:
38
- deploy_home: ta.Optional[str] = None
39
-
40
38
  targets: ta.Optional[ta.Mapping[str, ManageTarget]] = None
41
39
 
42
40
 
@@ -68,8 +66,6 @@ class MainCli(ArgparseCli):
68
66
 
69
67
  argparse_arg('--debug', action='store_true'),
70
68
 
71
- argparse_arg('--deploy-home'),
72
-
73
69
  argparse_arg('target'),
74
70
  argparse_arg('-f', '--command-file', action='append'),
75
71
  argparse_arg('command', nargs='*'),
@@ -82,9 +78,7 @@ class MainCli(ArgparseCli):
82
78
  debug=bool(self.args.debug),
83
79
  ),
84
80
 
85
- deploy_config=DeployConfig(
86
- deploy_home=self.args.deploy_home or self.config().deploy_home,
87
- ),
81
+ deploy_config=DeployConfig(),
88
82
 
89
83
  remote_config=RemoteConfig(
90
84
  payload_file=self.args._payload_file, # noqa