ominfra 0.0.0.dev176__py3-none-any.whl → 0.0.0.dev178__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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