ominfra 0.0.0.dev159__py3-none-any.whl → 0.0.0.dev161__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/manage/deploy/apps.py +3 -4
- ominfra/manage/deploy/commands.py +10 -1
- ominfra/manage/deploy/git.py +15 -8
- ominfra/manage/deploy/inject.py +2 -2
- ominfra/manage/deploy/paths.py +7 -36
- ominfra/manage/deploy/specs.py +16 -2
- ominfra/manage/deploy/tmp.py +9 -9
- ominfra/manage/deploy/venvs.py +2 -2
- ominfra/manage/targets/connection.py +1 -1
- ominfra/scripts/journald2aws.py +21 -9
- ominfra/scripts/manage.py +295 -289
- ominfra/scripts/supervisor.py +21 -9
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev161.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev161.dist-info}/RECORD +18 -19
- ominfra/manage/deploy/atomics.py +0 -207
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev161.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev161.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev161.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev161.dist-info}/top_level.txt +0 -0
ominfra/manage/deploy/apps.py
CHANGED
@@ -57,15 +57,14 @@ class DeployAppManager(DeployPathOwner):
|
|
57
57
|
async def prepare_app(
|
58
58
|
self,
|
59
59
|
spec: DeploySpec,
|
60
|
-
):
|
61
|
-
app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.rev, spec.key()))
|
60
|
+
) -> None:
|
61
|
+
app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.checkout.rev, spec.key()))
|
62
62
|
app_dir = os.path.join(self._dir(), spec.app, app_tag.tag)
|
63
63
|
|
64
64
|
#
|
65
65
|
|
66
66
|
await self._git.checkout(
|
67
|
-
spec.
|
68
|
-
spec.rev,
|
67
|
+
spec.checkout,
|
69
68
|
app_dir,
|
70
69
|
)
|
71
70
|
|
@@ -5,6 +5,8 @@ from omlish.lite.logs import log
|
|
5
5
|
|
6
6
|
from ..commands.base import Command
|
7
7
|
from ..commands.base import CommandExecutor
|
8
|
+
from .apps import DeployAppManager
|
9
|
+
from .specs import DeploySpec
|
8
10
|
|
9
11
|
|
10
12
|
##
|
@@ -12,13 +14,20 @@ from ..commands.base import CommandExecutor
|
|
12
14
|
|
13
15
|
@dc.dataclass(frozen=True)
|
14
16
|
class DeployCommand(Command['DeployCommand.Output']):
|
17
|
+
spec: DeploySpec
|
18
|
+
|
15
19
|
@dc.dataclass(frozen=True)
|
16
20
|
class Output(Command.Output):
|
17
21
|
pass
|
18
22
|
|
19
23
|
|
24
|
+
@dc.dataclass(frozen=True)
|
20
25
|
class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
|
26
|
+
_apps: DeployAppManager
|
27
|
+
|
21
28
|
async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
|
22
|
-
log.info('Deploying!')
|
29
|
+
log.info('Deploying! %r', cmd.spec)
|
30
|
+
|
31
|
+
await self._apps.prepare_app(cmd.spec)
|
23
32
|
|
24
33
|
return DeployCommand.Output()
|
ominfra/manage/deploy/git.py
CHANGED
@@ -15,9 +15,10 @@ 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
|
18
19
|
|
19
|
-
from .atomics import DeployAtomicPathSwapping
|
20
20
|
from .paths import SingleDirDeployPathOwner
|
21
|
+
from .specs import DeployGitCheckout
|
21
22
|
from .specs import DeployGitRepo
|
22
23
|
from .types import DeployHome
|
23
24
|
from .types import DeployRev
|
@@ -31,7 +32,7 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
31
32
|
self,
|
32
33
|
*,
|
33
34
|
deploy_home: ta.Optional[DeployHome] = None,
|
34
|
-
atomics:
|
35
|
+
atomics: AtomicPathSwapping,
|
35
36
|
) -> None:
|
36
37
|
super().__init__(
|
37
38
|
owned_dir='git',
|
@@ -69,12 +70,16 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
69
70
|
else:
|
70
71
|
return f'https://{self._repo.host}/{self._repo.path}'
|
71
72
|
|
73
|
+
#
|
74
|
+
|
72
75
|
async def _call(self, *cmd: str) -> None:
|
73
76
|
await asyncio_subprocesses.check_call(
|
74
77
|
*cmd,
|
75
78
|
cwd=self._dir,
|
76
79
|
)
|
77
80
|
|
81
|
+
#
|
82
|
+
|
78
83
|
@async_cached_nullary
|
79
84
|
async def init(self) -> None:
|
80
85
|
os.makedirs(self._dir, exist_ok=True)
|
@@ -88,7 +93,9 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
88
93
|
await self.init()
|
89
94
|
await self._call('git', 'fetch', '--depth=1', 'origin', rev)
|
90
95
|
|
91
|
-
|
96
|
+
#
|
97
|
+
|
98
|
+
async def checkout(self, checkout: DeployGitCheckout, dst_dir: str) -> None:
|
92
99
|
check.state(not os.path.exists(dst_dir))
|
93
100
|
with self._git._atomics.begin_atomic_path_swap( # noqa
|
94
101
|
'dir',
|
@@ -96,14 +103,14 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
96
103
|
auto_commit=True,
|
97
104
|
make_dirs=True,
|
98
105
|
) as dst_swap:
|
99
|
-
await self.fetch(rev)
|
106
|
+
await self.fetch(checkout.rev)
|
100
107
|
|
101
108
|
dst_call = functools.partial(asyncio_subprocesses.check_call, cwd=dst_swap.tmp_path)
|
102
109
|
await dst_call('git', 'init')
|
103
110
|
|
104
111
|
await dst_call('git', 'remote', 'add', 'local', self._dir)
|
105
|
-
await dst_call('git', 'fetch', '--depth=1', 'local', rev)
|
106
|
-
await dst_call('git', 'checkout', rev)
|
112
|
+
await dst_call('git', 'fetch', '--depth=1', 'local', checkout.rev)
|
113
|
+
await dst_call('git', 'checkout', checkout.rev, *(checkout.subtrees or []))
|
107
114
|
|
108
115
|
def get_repo_dir(self, repo: DeployGitRepo) -> RepoDir:
|
109
116
|
try:
|
@@ -112,5 +119,5 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
112
119
|
repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(self, repo)
|
113
120
|
return repo_dir
|
114
121
|
|
115
|
-
async def checkout(self,
|
116
|
-
await self.get_repo_dir(repo).checkout(
|
122
|
+
async def checkout(self, checkout: DeployGitCheckout, dst_dir: str) -> None:
|
123
|
+
await self.get_repo_dir(checkout.repo).checkout(checkout, dst_dir)
|
ominfra/manage/deploy/inject.py
CHANGED
@@ -5,10 +5,10 @@ import typing as ta
|
|
5
5
|
from omlish.lite.inject import InjectorBindingOrBindings
|
6
6
|
from omlish.lite.inject import InjectorBindings
|
7
7
|
from omlish.lite.inject import inj
|
8
|
+
from omlish.os.atomics import AtomicPathSwapping
|
8
9
|
|
9
10
|
from ..commands.inject import bind_command
|
10
11
|
from .apps import DeployAppManager
|
11
|
-
from .atomics import DeployAtomicPathSwapping
|
12
12
|
from .commands import DeployCommand
|
13
13
|
from .commands import DeployCommandExecutor
|
14
14
|
from .config import DeployConfig
|
@@ -34,7 +34,7 @@ def bind_deploy(
|
|
34
34
|
inj.bind(DeployGitManager, singleton=True),
|
35
35
|
|
36
36
|
inj.bind(DeployTmpManager, singleton=True),
|
37
|
-
inj.bind(
|
37
|
+
inj.bind(AtomicPathSwapping, to_key=DeployTmpManager),
|
38
38
|
|
39
39
|
inj.bind(DeployVenvManager, singleton=True),
|
40
40
|
|
ominfra/manage/deploy/paths.py
CHANGED
@@ -1,40 +1,11 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
2
|
"""
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
<appplaceholder>.env
|
10
|
-
/nginx
|
11
|
-
<appplaceholder>.conf
|
12
|
-
/supervisor
|
13
|
-
<appplaceholder>.conf
|
14
|
-
/venv
|
15
|
-
/<appplaceholder>
|
16
|
-
|
17
|
-
/tmp
|
18
|
-
|
19
|
-
?
|
20
|
-
/logs
|
21
|
-
/wrmsr--omlish--<placeholder>
|
22
|
-
|
23
|
-
placeholder = <name>--<rev>--<when>
|
24
|
-
|
25
|
-
==
|
26
|
-
|
27
|
-
for dn in [
|
28
|
-
'app',
|
29
|
-
'conf',
|
30
|
-
'conf/env',
|
31
|
-
'conf/nginx',
|
32
|
-
'conf/supervisor',
|
33
|
-
'venv',
|
34
|
-
]:
|
35
|
-
|
36
|
-
==
|
37
|
-
|
3
|
+
TODO:
|
4
|
+
- run/pidfile
|
5
|
+
- logs/...
|
6
|
+
- current symlink
|
7
|
+
- conf/{nginx,supervisor}
|
8
|
+
- env/?
|
38
9
|
"""
|
39
10
|
import abc
|
40
11
|
import dataclasses as dc
|
@@ -59,7 +30,7 @@ DEPLOY_PATH_PLACEHOLDER_SEPARATORS = '-.'
|
|
59
30
|
|
60
31
|
DEPLOY_PATH_PLACEHOLDERS: ta.FrozenSet[str] = frozenset([
|
61
32
|
'app',
|
62
|
-
'tag',
|
33
|
+
'tag',
|
63
34
|
])
|
64
35
|
|
65
36
|
|
ominfra/manage/deploy/specs.py
CHANGED
@@ -25,14 +25,28 @@ class DeployGitRepo:
|
|
25
25
|
check.not_in('.', check.non_empty_str(self.path))
|
26
26
|
|
27
27
|
|
28
|
+
@dc.dataclass(frozen=True)
|
29
|
+
class DeployGitCheckout:
|
30
|
+
repo: DeployGitRepo
|
31
|
+
rev: DeployRev
|
32
|
+
|
33
|
+
subtrees: ta.Optional[ta.Sequence[str]] = None
|
34
|
+
|
35
|
+
def __post_init__(self) -> None:
|
36
|
+
hash(self)
|
37
|
+
check.non_empty_str(self.rev)
|
38
|
+
if self.subtrees is not None:
|
39
|
+
for st in self.subtrees:
|
40
|
+
check.non_empty_str(st)
|
41
|
+
|
42
|
+
|
28
43
|
##
|
29
44
|
|
30
45
|
|
31
46
|
@dc.dataclass(frozen=True)
|
32
47
|
class DeploySpec:
|
33
48
|
app: DeployApp
|
34
|
-
|
35
|
-
rev: DeployRev
|
49
|
+
checkout: DeployGitCheckout
|
36
50
|
|
37
51
|
def __post_init__(self) -> None:
|
38
52
|
hash(self)
|
ominfra/manage/deploy/tmp.py
CHANGED
@@ -3,18 +3,18 @@ import typing as ta
|
|
3
3
|
|
4
4
|
from omlish.lite.cached import cached_nullary
|
5
5
|
from omlish.lite.check import check
|
6
|
+
from omlish.os.atomics import AtomicPathSwap
|
7
|
+
from omlish.os.atomics import AtomicPathSwapKind
|
8
|
+
from omlish.os.atomics import AtomicPathSwapping
|
9
|
+
from omlish.os.atomics import TempDirAtomicPathSwapping
|
6
10
|
|
7
|
-
from .atomics import DeployAtomicPathSwap
|
8
|
-
from .atomics import DeployAtomicPathSwapKind
|
9
|
-
from .atomics import DeployAtomicPathSwapping
|
10
|
-
from .atomics import TempDirDeployAtomicPathSwapping
|
11
11
|
from .paths import SingleDirDeployPathOwner
|
12
12
|
from .types import DeployHome
|
13
13
|
|
14
14
|
|
15
15
|
class DeployTmpManager(
|
16
16
|
SingleDirDeployPathOwner,
|
17
|
-
|
17
|
+
AtomicPathSwapping,
|
18
18
|
):
|
19
19
|
def __init__(
|
20
20
|
self,
|
@@ -27,18 +27,18 @@ class DeployTmpManager(
|
|
27
27
|
)
|
28
28
|
|
29
29
|
@cached_nullary
|
30
|
-
def _swapping(self) ->
|
31
|
-
return
|
30
|
+
def _swapping(self) -> AtomicPathSwapping:
|
31
|
+
return TempDirAtomicPathSwapping(
|
32
32
|
temp_dir=self._make_dir(),
|
33
33
|
root_dir=check.non_empty_str(self._deploy_home),
|
34
34
|
)
|
35
35
|
|
36
36
|
def begin_atomic_path_swap(
|
37
37
|
self,
|
38
|
-
kind:
|
38
|
+
kind: AtomicPathSwapKind,
|
39
39
|
dst_path: str,
|
40
40
|
**kwargs: ta.Any,
|
41
|
-
) ->
|
41
|
+
) -> AtomicPathSwap:
|
42
42
|
return self._swapping().begin_atomic_path_swap(
|
43
43
|
kind,
|
44
44
|
dst_path,
|
ominfra/manage/deploy/venvs.py
CHANGED
@@ -10,8 +10,8 @@ import typing as ta
|
|
10
10
|
from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
|
11
11
|
from omlish.lite.cached import cached_nullary
|
12
12
|
from omlish.lite.check import check
|
13
|
+
from omlish.os.atomics import AtomicPathSwapping
|
13
14
|
|
14
|
-
from .atomics import DeployAtomicPathSwapping
|
15
15
|
from .paths import DeployPath
|
16
16
|
from .paths import DeployPathOwner
|
17
17
|
from .types import DeployAppTag
|
@@ -23,7 +23,7 @@ class DeployVenvManager(DeployPathOwner):
|
|
23
23
|
self,
|
24
24
|
*,
|
25
25
|
deploy_home: ta.Optional[DeployHome] = None,
|
26
|
-
atomics:
|
26
|
+
atomics: AtomicPathSwapping,
|
27
27
|
) -> None:
|
28
28
|
super().__init__()
|
29
29
|
|
@@ -105,7 +105,7 @@ class DockerManageTargetConnector(ManageTargetConnector):
|
|
105
105
|
if dmt.image is not None:
|
106
106
|
sh_parts.extend(['run', '-i', dmt.image])
|
107
107
|
elif dmt.container_id is not None:
|
108
|
-
sh_parts.extend(['exec', dmt.container_id])
|
108
|
+
sh_parts.extend(['exec', '-i', dmt.container_id])
|
109
109
|
else:
|
110
110
|
raise ValueError(dmt)
|
111
111
|
|
ominfra/scripts/journald2aws.py
CHANGED
@@ -1487,6 +1487,10 @@ def is_new_type(spec: ta.Any) -> bool:
|
|
1487
1487
|
return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
|
1488
1488
|
|
1489
1489
|
|
1490
|
+
def get_new_type_supertype(spec: ta.Any) -> ta.Any:
|
1491
|
+
return spec.__supertype__
|
1492
|
+
|
1493
|
+
|
1490
1494
|
def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
|
1491
1495
|
seen = set()
|
1492
1496
|
todo = list(reversed(cls.__subclasses__()))
|
@@ -2450,9 +2454,7 @@ class aclosing(contextlib.AbstractAsyncContextManager): # noqa
|
|
2450
2454
|
"""
|
2451
2455
|
TODO:
|
2452
2456
|
- pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
|
2453
|
-
- namedtuple
|
2454
2457
|
- literals
|
2455
|
-
- newtypes?
|
2456
2458
|
"""
|
2457
2459
|
|
2458
2460
|
|
@@ -2462,7 +2464,7 @@ TODO:
|
|
2462
2464
|
@dc.dataclass(frozen=True)
|
2463
2465
|
class ObjMarshalOptions:
|
2464
2466
|
raw_bytes: bool = False
|
2465
|
-
|
2467
|
+
non_strict_fields: bool = False
|
2466
2468
|
|
2467
2469
|
|
2468
2470
|
class ObjMarshaler(abc.ABC):
|
@@ -2591,10 +2593,10 @@ class IterableObjMarshaler(ObjMarshaler):
|
|
2591
2593
|
|
2592
2594
|
|
2593
2595
|
@dc.dataclass(frozen=True)
|
2594
|
-
class
|
2596
|
+
class FieldsObjMarshaler(ObjMarshaler):
|
2595
2597
|
ty: type
|
2596
2598
|
fs: ta.Mapping[str, ObjMarshaler]
|
2597
|
-
|
2599
|
+
non_strict: bool = False
|
2598
2600
|
|
2599
2601
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
2600
2602
|
return {
|
@@ -2606,7 +2608,7 @@ class DataclassObjMarshaler(ObjMarshaler):
|
|
2606
2608
|
return self.ty(**{
|
2607
2609
|
k: self.fs[k].unmarshal(v, ctx)
|
2608
2610
|
for k, v in o.items()
|
2609
|
-
if not (self.
|
2611
|
+
if not (self.non_strict or ctx.options.non_strict_fields) or k in self.fs
|
2610
2612
|
})
|
2611
2613
|
|
2612
2614
|
|
@@ -2738,7 +2740,7 @@ class ObjMarshalerManager:
|
|
2738
2740
|
ty: ta.Any,
|
2739
2741
|
rec: ta.Callable[[ta.Any], ObjMarshaler],
|
2740
2742
|
*,
|
2741
|
-
|
2743
|
+
non_strict_fields: bool = False,
|
2742
2744
|
) -> ObjMarshaler:
|
2743
2745
|
if isinstance(ty, type):
|
2744
2746
|
if abc.ABC in ty.__bases__:
|
@@ -2760,12 +2762,22 @@ class ObjMarshalerManager:
|
|
2760
2762
|
return EnumObjMarshaler(ty)
|
2761
2763
|
|
2762
2764
|
if dc.is_dataclass(ty):
|
2763
|
-
return
|
2765
|
+
return FieldsObjMarshaler(
|
2764
2766
|
ty,
|
2765
2767
|
{f.name: rec(f.type) for f in dc.fields(ty)},
|
2766
|
-
|
2768
|
+
non_strict=non_strict_fields,
|
2769
|
+
)
|
2770
|
+
|
2771
|
+
if issubclass(ty, tuple) and hasattr(ty, '_fields'):
|
2772
|
+
return FieldsObjMarshaler(
|
2773
|
+
ty,
|
2774
|
+
{p.name: rec(p.annotation) for p in inspect.signature(ty).parameters.values()},
|
2775
|
+
non_strict=non_strict_fields,
|
2767
2776
|
)
|
2768
2777
|
|
2778
|
+
if is_new_type(ty):
|
2779
|
+
return rec(get_new_type_supertype(ty))
|
2780
|
+
|
2769
2781
|
if is_generic_alias(ty):
|
2770
2782
|
try:
|
2771
2783
|
mt = self._generic_mapping_types[ta.get_origin(ty)]
|