ominfra 0.0.0.dev159__py3-none-any.whl → 0.0.0.dev160__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- ominfra/manage/deploy/apps.py +3 -4
- ominfra/manage/deploy/commands.py +10 -1
- ominfra/manage/deploy/git.py +13 -6
- ominfra/manage/deploy/paths.py +7 -36
- ominfra/manage/deploy/specs.py +16 -2
- ominfra/scripts/journald2aws.py +21 -9
- ominfra/scripts/manage.py +87 -78
- ominfra/scripts/supervisor.py +21 -9
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev160.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev160.dist-info}/RECORD +14 -14
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev160.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev160.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev160.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev159.dist-info → ominfra-0.0.0.dev160.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
@@ -18,6 +18,7 @@ from omlish.lite.check import check
|
|
18
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
|
@@ -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/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/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)]
|
ominfra/scripts/manage.py
CHANGED
@@ -2692,6 +2692,10 @@ def is_new_type(spec: ta.Any) -> bool:
|
|
2692
2692
|
return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
|
2693
2693
|
|
2694
2694
|
|
2695
|
+
def get_new_type_supertype(spec: ta.Any) -> ta.Any:
|
2696
|
+
return spec.__supertype__
|
2697
|
+
|
2698
|
+
|
2695
2699
|
def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
|
2696
2700
|
seen = set()
|
2697
2701
|
todo = list(reversed(cls.__subclasses__()))
|
@@ -4261,41 +4265,12 @@ class TempDirDeployAtomicPathSwapping(DeployAtomicPathSwapping):
|
|
4261
4265
|
########################################
|
4262
4266
|
# ../deploy/paths.py
|
4263
4267
|
"""
|
4264
|
-
|
4265
|
-
|
4266
|
-
|
4267
|
-
|
4268
|
-
|
4269
|
-
|
4270
|
-
<appplaceholder>.env
|
4271
|
-
/nginx
|
4272
|
-
<appplaceholder>.conf
|
4273
|
-
/supervisor
|
4274
|
-
<appplaceholder>.conf
|
4275
|
-
/venv
|
4276
|
-
/<appplaceholder>
|
4277
|
-
|
4278
|
-
/tmp
|
4279
|
-
|
4280
|
-
?
|
4281
|
-
/logs
|
4282
|
-
/wrmsr--omlish--<placeholder>
|
4283
|
-
|
4284
|
-
placeholder = <name>--<rev>--<when>
|
4285
|
-
|
4286
|
-
==
|
4287
|
-
|
4288
|
-
for dn in [
|
4289
|
-
'app',
|
4290
|
-
'conf',
|
4291
|
-
'conf/env',
|
4292
|
-
'conf/nginx',
|
4293
|
-
'conf/supervisor',
|
4294
|
-
'venv',
|
4295
|
-
]:
|
4296
|
-
|
4297
|
-
==
|
4298
|
-
|
4268
|
+
TODO:
|
4269
|
+
- run/pidfile
|
4270
|
+
- logs/...
|
4271
|
+
- current symlink
|
4272
|
+
- conf/{nginx,supervisor}
|
4273
|
+
- env/?
|
4299
4274
|
"""
|
4300
4275
|
|
4301
4276
|
|
@@ -4307,7 +4282,7 @@ DEPLOY_PATH_PLACEHOLDER_SEPARATORS = '-.'
|
|
4307
4282
|
|
4308
4283
|
DEPLOY_PATH_PLACEHOLDERS: ta.FrozenSet[str] = frozenset([
|
4309
4284
|
'app',
|
4310
|
-
'tag',
|
4285
|
+
'tag',
|
4311
4286
|
])
|
4312
4287
|
|
4313
4288
|
|
@@ -4534,14 +4509,28 @@ class DeployGitRepo:
|
|
4534
4509
|
check.not_in('.', check.non_empty_str(self.path))
|
4535
4510
|
|
4536
4511
|
|
4512
|
+
@dc.dataclass(frozen=True)
|
4513
|
+
class DeployGitCheckout:
|
4514
|
+
repo: DeployGitRepo
|
4515
|
+
rev: DeployRev
|
4516
|
+
|
4517
|
+
subtrees: ta.Optional[ta.Sequence[str]] = None
|
4518
|
+
|
4519
|
+
def __post_init__(self) -> None:
|
4520
|
+
hash(self)
|
4521
|
+
check.non_empty_str(self.rev)
|
4522
|
+
if self.subtrees is not None:
|
4523
|
+
for st in self.subtrees:
|
4524
|
+
check.non_empty_str(st)
|
4525
|
+
|
4526
|
+
|
4537
4527
|
##
|
4538
4528
|
|
4539
4529
|
|
4540
4530
|
@dc.dataclass(frozen=True)
|
4541
4531
|
class DeploySpec:
|
4542
4532
|
app: DeployApp
|
4543
|
-
|
4544
|
-
rev: DeployRev
|
4533
|
+
checkout: DeployGitCheckout
|
4545
4534
|
|
4546
4535
|
def __post_init__(self) -> None:
|
4547
4536
|
hash(self)
|
@@ -6008,9 +5997,7 @@ inj = Injection
|
|
6008
5997
|
"""
|
6009
5998
|
TODO:
|
6010
5999
|
- pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
|
6011
|
-
- namedtuple
|
6012
6000
|
- literals
|
6013
|
-
- newtypes?
|
6014
6001
|
"""
|
6015
6002
|
|
6016
6003
|
|
@@ -6020,7 +6007,7 @@ TODO:
|
|
6020
6007
|
@dc.dataclass(frozen=True)
|
6021
6008
|
class ObjMarshalOptions:
|
6022
6009
|
raw_bytes: bool = False
|
6023
|
-
|
6010
|
+
non_strict_fields: bool = False
|
6024
6011
|
|
6025
6012
|
|
6026
6013
|
class ObjMarshaler(abc.ABC):
|
@@ -6149,10 +6136,10 @@ class IterableObjMarshaler(ObjMarshaler):
|
|
6149
6136
|
|
6150
6137
|
|
6151
6138
|
@dc.dataclass(frozen=True)
|
6152
|
-
class
|
6139
|
+
class FieldsObjMarshaler(ObjMarshaler):
|
6153
6140
|
ty: type
|
6154
6141
|
fs: ta.Mapping[str, ObjMarshaler]
|
6155
|
-
|
6142
|
+
non_strict: bool = False
|
6156
6143
|
|
6157
6144
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
6158
6145
|
return {
|
@@ -6164,7 +6151,7 @@ class DataclassObjMarshaler(ObjMarshaler):
|
|
6164
6151
|
return self.ty(**{
|
6165
6152
|
k: self.fs[k].unmarshal(v, ctx)
|
6166
6153
|
for k, v in o.items()
|
6167
|
-
if not (self.
|
6154
|
+
if not (self.non_strict or ctx.options.non_strict_fields) or k in self.fs
|
6168
6155
|
})
|
6169
6156
|
|
6170
6157
|
|
@@ -6296,7 +6283,7 @@ class ObjMarshalerManager:
|
|
6296
6283
|
ty: ta.Any,
|
6297
6284
|
rec: ta.Callable[[ta.Any], ObjMarshaler],
|
6298
6285
|
*,
|
6299
|
-
|
6286
|
+
non_strict_fields: bool = False,
|
6300
6287
|
) -> ObjMarshaler:
|
6301
6288
|
if isinstance(ty, type):
|
6302
6289
|
if abc.ABC in ty.__bases__:
|
@@ -6318,12 +6305,22 @@ class ObjMarshalerManager:
|
|
6318
6305
|
return EnumObjMarshaler(ty)
|
6319
6306
|
|
6320
6307
|
if dc.is_dataclass(ty):
|
6321
|
-
return
|
6308
|
+
return FieldsObjMarshaler(
|
6322
6309
|
ty,
|
6323
6310
|
{f.name: rec(f.type) for f in dc.fields(ty)},
|
6324
|
-
|
6311
|
+
non_strict=non_strict_fields,
|
6312
|
+
)
|
6313
|
+
|
6314
|
+
if issubclass(ty, tuple) and hasattr(ty, '_fields'):
|
6315
|
+
return FieldsObjMarshaler(
|
6316
|
+
ty,
|
6317
|
+
{p.name: rec(p.annotation) for p in inspect.signature(ty).parameters.values()},
|
6318
|
+
non_strict=non_strict_fields,
|
6325
6319
|
)
|
6326
6320
|
|
6321
|
+
if is_new_type(ty):
|
6322
|
+
return rec(get_new_type_supertype(ty))
|
6323
|
+
|
6327
6324
|
if is_generic_alias(ty):
|
6328
6325
|
try:
|
6329
6326
|
mt = self._generic_mapping_types[ta.get_origin(ty)]
|
@@ -6749,27 +6746,6 @@ class PingCommandExecutor(CommandExecutor[PingCommand, PingCommand.Output]):
|
|
6749
6746
|
CommandExecutorMap = ta.NewType('CommandExecutorMap', ta.Mapping[ta.Type[Command], CommandExecutor])
|
6750
6747
|
|
6751
6748
|
|
6752
|
-
########################################
|
6753
|
-
# ../deploy/commands.py
|
6754
|
-
|
6755
|
-
|
6756
|
-
##
|
6757
|
-
|
6758
|
-
|
6759
|
-
@dc.dataclass(frozen=True)
|
6760
|
-
class DeployCommand(Command['DeployCommand.Output']):
|
6761
|
-
@dc.dataclass(frozen=True)
|
6762
|
-
class Output(Command.Output):
|
6763
|
-
pass
|
6764
|
-
|
6765
|
-
|
6766
|
-
class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
|
6767
|
-
async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
|
6768
|
-
log.info('Deploying!')
|
6769
|
-
|
6770
|
-
return DeployCommand.Output()
|
6771
|
-
|
6772
|
-
|
6773
6749
|
########################################
|
6774
6750
|
# ../deploy/tmp.py
|
6775
6751
|
|
@@ -8237,12 +8213,16 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
8237
8213
|
else:
|
8238
8214
|
return f'https://{self._repo.host}/{self._repo.path}'
|
8239
8215
|
|
8216
|
+
#
|
8217
|
+
|
8240
8218
|
async def _call(self, *cmd: str) -> None:
|
8241
8219
|
await asyncio_subprocesses.check_call(
|
8242
8220
|
*cmd,
|
8243
8221
|
cwd=self._dir,
|
8244
8222
|
)
|
8245
8223
|
|
8224
|
+
#
|
8225
|
+
|
8246
8226
|
@async_cached_nullary
|
8247
8227
|
async def init(self) -> None:
|
8248
8228
|
os.makedirs(self._dir, exist_ok=True)
|
@@ -8256,7 +8236,9 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
8256
8236
|
await self.init()
|
8257
8237
|
await self._call('git', 'fetch', '--depth=1', 'origin', rev)
|
8258
8238
|
|
8259
|
-
|
8239
|
+
#
|
8240
|
+
|
8241
|
+
async def checkout(self, checkout: DeployGitCheckout, dst_dir: str) -> None:
|
8260
8242
|
check.state(not os.path.exists(dst_dir))
|
8261
8243
|
with self._git._atomics.begin_atomic_path_swap( # noqa
|
8262
8244
|
'dir',
|
@@ -8264,14 +8246,14 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
8264
8246
|
auto_commit=True,
|
8265
8247
|
make_dirs=True,
|
8266
8248
|
) as dst_swap:
|
8267
|
-
await self.fetch(rev)
|
8249
|
+
await self.fetch(checkout.rev)
|
8268
8250
|
|
8269
8251
|
dst_call = functools.partial(asyncio_subprocesses.check_call, cwd=dst_swap.tmp_path)
|
8270
8252
|
await dst_call('git', 'init')
|
8271
8253
|
|
8272
8254
|
await dst_call('git', 'remote', 'add', 'local', self._dir)
|
8273
|
-
await dst_call('git', 'fetch', '--depth=1', 'local', rev)
|
8274
|
-
await dst_call('git', 'checkout', rev)
|
8255
|
+
await dst_call('git', 'fetch', '--depth=1', 'local', checkout.rev)
|
8256
|
+
await dst_call('git', 'checkout', checkout.rev, *(checkout.subtrees or []))
|
8275
8257
|
|
8276
8258
|
def get_repo_dir(self, repo: DeployGitRepo) -> RepoDir:
|
8277
8259
|
try:
|
@@ -8280,8 +8262,8 @@ class DeployGitManager(SingleDirDeployPathOwner):
|
|
8280
8262
|
repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(self, repo)
|
8281
8263
|
return repo_dir
|
8282
8264
|
|
8283
|
-
async def checkout(self,
|
8284
|
-
await self.get_repo_dir(repo).checkout(
|
8265
|
+
async def checkout(self, checkout: DeployGitCheckout, dst_dir: str) -> None:
|
8266
|
+
await self.get_repo_dir(checkout.repo).checkout(checkout, dst_dir)
|
8285
8267
|
|
8286
8268
|
|
8287
8269
|
########################################
|
@@ -8919,15 +8901,14 @@ class DeployAppManager(DeployPathOwner):
|
|
8919
8901
|
async def prepare_app(
|
8920
8902
|
self,
|
8921
8903
|
spec: DeploySpec,
|
8922
|
-
):
|
8923
|
-
app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.rev, spec.key()))
|
8904
|
+
) -> None:
|
8905
|
+
app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.checkout.rev, spec.key()))
|
8924
8906
|
app_dir = os.path.join(self._dir(), spec.app, app_tag.tag)
|
8925
8907
|
|
8926
8908
|
#
|
8927
8909
|
|
8928
8910
|
await self._git.checkout(
|
8929
|
-
spec.
|
8930
|
-
spec.rev,
|
8911
|
+
spec.checkout,
|
8931
8912
|
app_dir,
|
8932
8913
|
)
|
8933
8914
|
|
@@ -9650,6 +9631,34 @@ class SystemInterpProvider(InterpProvider):
|
|
9650
9631
|
raise KeyError(version)
|
9651
9632
|
|
9652
9633
|
|
9634
|
+
########################################
|
9635
|
+
# ../deploy/commands.py
|
9636
|
+
|
9637
|
+
|
9638
|
+
##
|
9639
|
+
|
9640
|
+
|
9641
|
+
@dc.dataclass(frozen=True)
|
9642
|
+
class DeployCommand(Command['DeployCommand.Output']):
|
9643
|
+
spec: DeploySpec
|
9644
|
+
|
9645
|
+
@dc.dataclass(frozen=True)
|
9646
|
+
class Output(Command.Output):
|
9647
|
+
pass
|
9648
|
+
|
9649
|
+
|
9650
|
+
@dc.dataclass(frozen=True)
|
9651
|
+
class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
|
9652
|
+
_apps: DeployAppManager
|
9653
|
+
|
9654
|
+
async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
|
9655
|
+
log.info('Deploying! %r', cmd.spec)
|
9656
|
+
|
9657
|
+
await self._apps.prepare_app(cmd.spec)
|
9658
|
+
|
9659
|
+
return DeployCommand.Output()
|
9660
|
+
|
9661
|
+
|
9653
9662
|
########################################
|
9654
9663
|
# ../remote/inject.py
|
9655
9664
|
|
ominfra/scripts/supervisor.py
CHANGED
@@ -2296,6 +2296,10 @@ def is_new_type(spec: ta.Any) -> bool:
|
|
2296
2296
|
return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
|
2297
2297
|
|
2298
2298
|
|
2299
|
+
def get_new_type_supertype(spec: ta.Any) -> ta.Any:
|
2300
|
+
return spec.__supertype__
|
2301
|
+
|
2302
|
+
|
2299
2303
|
def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
|
2300
2304
|
seen = set()
|
2301
2305
|
todo = list(reversed(cls.__subclasses__()))
|
@@ -4854,9 +4858,7 @@ inj = Injection
|
|
4854
4858
|
"""
|
4855
4859
|
TODO:
|
4856
4860
|
- pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
|
4857
|
-
- namedtuple
|
4858
4861
|
- literals
|
4859
|
-
- newtypes?
|
4860
4862
|
"""
|
4861
4863
|
|
4862
4864
|
|
@@ -4866,7 +4868,7 @@ TODO:
|
|
4866
4868
|
@dc.dataclass(frozen=True)
|
4867
4869
|
class ObjMarshalOptions:
|
4868
4870
|
raw_bytes: bool = False
|
4869
|
-
|
4871
|
+
non_strict_fields: bool = False
|
4870
4872
|
|
4871
4873
|
|
4872
4874
|
class ObjMarshaler(abc.ABC):
|
@@ -4995,10 +4997,10 @@ class IterableObjMarshaler(ObjMarshaler):
|
|
4995
4997
|
|
4996
4998
|
|
4997
4999
|
@dc.dataclass(frozen=True)
|
4998
|
-
class
|
5000
|
+
class FieldsObjMarshaler(ObjMarshaler):
|
4999
5001
|
ty: type
|
5000
5002
|
fs: ta.Mapping[str, ObjMarshaler]
|
5001
|
-
|
5003
|
+
non_strict: bool = False
|
5002
5004
|
|
5003
5005
|
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
5004
5006
|
return {
|
@@ -5010,7 +5012,7 @@ class DataclassObjMarshaler(ObjMarshaler):
|
|
5010
5012
|
return self.ty(**{
|
5011
5013
|
k: self.fs[k].unmarshal(v, ctx)
|
5012
5014
|
for k, v in o.items()
|
5013
|
-
if not (self.
|
5015
|
+
if not (self.non_strict or ctx.options.non_strict_fields) or k in self.fs
|
5014
5016
|
})
|
5015
5017
|
|
5016
5018
|
|
@@ -5142,7 +5144,7 @@ class ObjMarshalerManager:
|
|
5142
5144
|
ty: ta.Any,
|
5143
5145
|
rec: ta.Callable[[ta.Any], ObjMarshaler],
|
5144
5146
|
*,
|
5145
|
-
|
5147
|
+
non_strict_fields: bool = False,
|
5146
5148
|
) -> ObjMarshaler:
|
5147
5149
|
if isinstance(ty, type):
|
5148
5150
|
if abc.ABC in ty.__bases__:
|
@@ -5164,12 +5166,22 @@ class ObjMarshalerManager:
|
|
5164
5166
|
return EnumObjMarshaler(ty)
|
5165
5167
|
|
5166
5168
|
if dc.is_dataclass(ty):
|
5167
|
-
return
|
5169
|
+
return FieldsObjMarshaler(
|
5168
5170
|
ty,
|
5169
5171
|
{f.name: rec(f.type) for f in dc.fields(ty)},
|
5170
|
-
|
5172
|
+
non_strict=non_strict_fields,
|
5173
|
+
)
|
5174
|
+
|
5175
|
+
if issubclass(ty, tuple) and hasattr(ty, '_fields'):
|
5176
|
+
return FieldsObjMarshaler(
|
5177
|
+
ty,
|
5178
|
+
{p.name: rec(p.annotation) for p in inspect.signature(ty).parameters.values()},
|
5179
|
+
non_strict=non_strict_fields,
|
5171
5180
|
)
|
5172
5181
|
|
5182
|
+
if is_new_type(ty):
|
5183
|
+
return rec(get_new_type_supertype(ty))
|
5184
|
+
|
5173
5185
|
if is_generic_alias(ty):
|
5174
5186
|
try:
|
5175
5187
|
mt = self._generic_mapping_types[ta.get_origin(ty)]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ominfra
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev160
|
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.
|
16
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omdev==0.0.0.dev160
|
16
|
+
Requires-Dist: omlish==0.0.0.dev160
|
17
17
|
Provides-Extra: all
|
18
18
|
Requires-Dist: paramiko~=3.5; extra == "all"
|
19
19
|
Requires-Dist: asyncssh~=2.18; extra == "all"
|
@@ -44,15 +44,15 @@ ominfra/manage/commands/ping.py,sha256=DVZFzL1Z_f-Bq53vxMrL3xOi0iK_nMonJE4KvQf9w
|
|
44
44
|
ominfra/manage/commands/subprocess.py,sha256=yHGMbAI-xKe_9BUs5IZ3Yav8qRE-I9aGnBtTwW15Pnw,2440
|
45
45
|
ominfra/manage/commands/types.py,sha256=XFZPeqeIBAaIIQF3pdPbGxLlb-LCrz6WtlDWO2q_vz0,210
|
46
46
|
ominfra/manage/deploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
|
-
ominfra/manage/deploy/apps.py,sha256=
|
47
|
+
ominfra/manage/deploy/apps.py,sha256=lXcbyX8_wrvvwKtIMM9P_Mh7xL8yj6z9_PFTl_0u-0U,1887
|
48
48
|
ominfra/manage/deploy/atomics.py,sha256=j9_L2LXls2dR1I4rQw3msIa2D90JwEO9Mb8KBGOKmyU,5180
|
49
|
-
ominfra/manage/deploy/commands.py,sha256=
|
49
|
+
ominfra/manage/deploy/commands.py,sha256=N9qVntnRgJ_IneI7rEQB2Za0oU7gouPfm-sl2MCwW1E,764
|
50
50
|
ominfra/manage/deploy/config.py,sha256=aR6ubMEWqkTI55XtcG1Cczn6YhCVN6eSL8DT5EHQJN0,166
|
51
|
-
ominfra/manage/deploy/git.py,sha256=
|
51
|
+
ominfra/manage/deploy/git.py,sha256=T-ad5HtavIsZG3Y1lNimYXvrvklWfm2kZBcV1DLlI-A,3750
|
52
52
|
ominfra/manage/deploy/inject.py,sha256=JBc96rxOL7Q6P78yZP4WHp08i2AHvV0JHbRpUzbFblw,1444
|
53
53
|
ominfra/manage/deploy/interp.py,sha256=OKkenH8YKEW_mEDR6X7_ZLxK9a1Ox6KHSwFPTHT6OzA,1029
|
54
|
-
ominfra/manage/deploy/paths.py,sha256=
|
55
|
-
ominfra/manage/deploy/specs.py,sha256=
|
54
|
+
ominfra/manage/deploy/paths.py,sha256=tK8zZFWOHDRdTN5AlTe-3MpgZqovhWrljGosQmeEYvo,6839
|
55
|
+
ominfra/manage/deploy/specs.py,sha256=Yq3WiLNJcodUBEsJfP18gPGB3X2ABI1g8YLlsUvJOXg,1230
|
56
56
|
ominfra/manage/deploy/tmp.py,sha256=Wg29UMsWL_A8anFsE-XyvkTNsMfH26Nr8BvJxgKNxMo,1248
|
57
57
|
ominfra/manage/deploy/types.py,sha256=o95wqvTGNRq8Cxx7VpqeX-9x1tI8k8BpqPFvJZkJYBA,305
|
58
58
|
ominfra/manage/deploy/venvs.py,sha256=A1nqFo1Zhxg-Sw3Uyxe6hck4ZEh3bBq8GIjnJPvNLd8,2232
|
@@ -76,9 +76,9 @@ ominfra/manage/targets/connection.py,sha256=j2QrVS-QFOZJ47TqwaMt8MSPg0whokysGePa
|
|
76
76
|
ominfra/manage/targets/inject.py,sha256=P4597xWM-V3I_gCt2O71OLhYQkkXtuJvkYRsIbhhMcE,1561
|
77
77
|
ominfra/manage/targets/targets.py,sha256=CFl8Uirgn3gfowO1Fn-LBK-6qYqEMFJ9snPUl0gCRuM,1753
|
78
78
|
ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
79
|
-
ominfra/scripts/journald2aws.py,sha256=
|
80
|
-
ominfra/scripts/manage.py,sha256=
|
81
|
-
ominfra/scripts/supervisor.py,sha256=
|
79
|
+
ominfra/scripts/journald2aws.py,sha256=EC8tSKW3hztBV_Kr_ykK72AmcvnWivUxcz6Sfg3M_hI,155085
|
80
|
+
ominfra/scripts/manage.py,sha256=mrjtcbAYVv3RkhEV_tcdPra5lZTJG27k0qgAZsye9zk,293936
|
81
|
+
ominfra/scripts/supervisor.py,sha256=npGYEWSZfY7E24mdkJ3HrL_ax6AcqjHfqh-7nZ_sX0U,273987
|
82
82
|
ominfra/supervisor/LICENSE.txt,sha256=yvqaMNsDhWxziHa9ien6qCW1SkZv-DQlAg96XjfSee8,1746
|
83
83
|
ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
84
84
|
ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
|
@@ -120,9 +120,9 @@ ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
|
|
120
120
|
ominfra/tailscale/cli.py,sha256=h6akQJMl0KuWLHS7Ur6WcBZ2JwF0DJQhsPTnFBdGyNk,3571
|
121
121
|
ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
122
122
|
ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
|
123
|
-
ominfra-0.0.0.
|
124
|
-
ominfra-0.0.0.
|
125
|
-
ominfra-0.0.0.
|
126
|
-
ominfra-0.0.0.
|
127
|
-
ominfra-0.0.0.
|
128
|
-
ominfra-0.0.0.
|
123
|
+
ominfra-0.0.0.dev160.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
124
|
+
ominfra-0.0.0.dev160.dist-info/METADATA,sha256=eS2Inhifb3u6Dusi7KHOATGGlcALPwhc363rDTOzVz0,731
|
125
|
+
ominfra-0.0.0.dev160.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
126
|
+
ominfra-0.0.0.dev160.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
|
127
|
+
ominfra-0.0.0.dev160.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
|
128
|
+
ominfra-0.0.0.dev160.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|