ominfra 0.0.0.dev159__py3-none-any.whl → 0.0.0.dev160__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 +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
|