ominfra 0.0.0.dev172__py3-none-any.whl → 0.0.0.dev174__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 +48 -80
- ominfra/manage/deploy/conf.py +55 -50
- ominfra/manage/deploy/deploy.py +45 -1
- ominfra/manage/deploy/paths/paths.py +39 -45
- ominfra/manage/deploy/paths/types.py +8 -0
- ominfra/manage/deploy/specs.py +47 -13
- ominfra/manage/deploy/tags.py +225 -0
- ominfra/manage/deploy/types.py +0 -30
- ominfra/scripts/journald2aws.py +46 -0
- ominfra/scripts/manage.py +529 -191
- ominfra/scripts/supervisor.py +46 -0
- {ominfra-0.0.0.dev172.dist-info → ominfra-0.0.0.dev174.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev172.dist-info → ominfra-0.0.0.dev174.dist-info}/RECORD +17 -15
- {ominfra-0.0.0.dev172.dist-info → ominfra-0.0.0.dev174.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev172.dist-info → ominfra-0.0.0.dev174.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev172.dist-info → ominfra-0.0.0.dev174.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev172.dist-info → ominfra-0.0.0.dev174.dist-info}/top_level.txt +0 -0
ominfra/manage/deploy/specs.py
CHANGED
@@ -7,11 +7,16 @@ import typing as ta
|
|
7
7
|
from omlish.lite.cached import cached_nullary
|
8
8
|
from omlish.lite.check import check
|
9
9
|
|
10
|
-
from .
|
11
|
-
from .
|
10
|
+
from .tags import DeployApp
|
11
|
+
from .tags import DeployAppKey
|
12
|
+
from .tags import DeployKey
|
13
|
+
from .tags import KeyDeployTag # noqa
|
12
14
|
from .types import DeployRev
|
13
15
|
|
14
16
|
|
17
|
+
KeyDeployTagT = ta.TypeVar('KeyDeployTagT', bound='KeyDeployTag')
|
18
|
+
|
19
|
+
|
15
20
|
##
|
16
21
|
|
17
22
|
|
@@ -23,6 +28,16 @@ def check_valid_deploy_spec_path(s: str) -> str:
|
|
23
28
|
return s
|
24
29
|
|
25
30
|
|
31
|
+
class DeploySpecKeyed(ta.Generic[KeyDeployTagT]):
|
32
|
+
@cached_nullary
|
33
|
+
def _key_str(self) -> str:
|
34
|
+
return hashlib.sha256(repr(self).encode('utf-8')).hexdigest()[:8]
|
35
|
+
|
36
|
+
@abc.abstractmethod
|
37
|
+
def key(self) -> KeyDeployTagT:
|
38
|
+
raise NotImplementedError
|
39
|
+
|
40
|
+
|
26
41
|
##
|
27
42
|
|
28
43
|
|
@@ -68,7 +83,7 @@ class DeployVenvSpec:
|
|
68
83
|
|
69
84
|
|
70
85
|
@dc.dataclass(frozen=True)
|
71
|
-
class
|
86
|
+
class DeployAppConfFile:
|
72
87
|
path: str
|
73
88
|
body: str
|
74
89
|
|
@@ -80,7 +95,7 @@ class DeployConfFile:
|
|
80
95
|
|
81
96
|
|
82
97
|
@dc.dataclass(frozen=True)
|
83
|
-
class
|
98
|
+
class DeployAppConfLink(abc.ABC): # noqa
|
84
99
|
"""
|
85
100
|
May be either:
|
86
101
|
- @conf(.ext)* - links a single file in root of app conf dir to conf/@conf/@dst(.ext)*
|
@@ -96,11 +111,11 @@ class DeployConfLink(abc.ABC): # noqa
|
|
96
111
|
check.equal(self.src.count('/'), 1)
|
97
112
|
|
98
113
|
|
99
|
-
class
|
114
|
+
class CurrentOnlyDeployAppConfLink(DeployAppConfLink):
|
100
115
|
pass
|
101
116
|
|
102
117
|
|
103
|
-
class
|
118
|
+
class AllActiveDeployAppConfLink(DeployAppConfLink):
|
104
119
|
pass
|
105
120
|
|
106
121
|
|
@@ -108,10 +123,10 @@ class TagDeployConfLink(DeployConfLink):
|
|
108
123
|
|
109
124
|
|
110
125
|
@dc.dataclass(frozen=True)
|
111
|
-
class
|
112
|
-
files: ta.Optional[ta.Sequence[
|
126
|
+
class DeployAppConfSpec:
|
127
|
+
files: ta.Optional[ta.Sequence[DeployAppConfFile]] = None
|
113
128
|
|
114
|
-
links: ta.Optional[ta.Sequence[
|
129
|
+
links: ta.Optional[ta.Sequence[DeployAppConfLink]] = None
|
115
130
|
|
116
131
|
def __post_init__(self) -> None:
|
117
132
|
if self.files:
|
@@ -125,15 +140,34 @@ class DeployConfSpec:
|
|
125
140
|
|
126
141
|
|
127
142
|
@dc.dataclass(frozen=True)
|
128
|
-
class
|
143
|
+
class DeployAppSpec(DeploySpecKeyed[DeployAppKey]):
|
129
144
|
app: DeployApp
|
130
145
|
|
131
146
|
git: DeployGitSpec
|
132
147
|
|
133
148
|
venv: ta.Optional[DeployVenvSpec] = None
|
134
149
|
|
135
|
-
conf: ta.Optional[
|
150
|
+
conf: ta.Optional[DeployAppConfSpec] = None
|
136
151
|
|
137
|
-
@
|
152
|
+
# @ta.override
|
153
|
+
def key(self) -> DeployAppKey:
|
154
|
+
return DeployAppKey(self._key_str())
|
155
|
+
|
156
|
+
|
157
|
+
##
|
158
|
+
|
159
|
+
|
160
|
+
@dc.dataclass(frozen=True)
|
161
|
+
class DeploySpec(DeploySpecKeyed[DeployKey]):
|
162
|
+
apps: ta.Sequence[DeployAppSpec]
|
163
|
+
|
164
|
+
def __post_init__(self) -> None:
|
165
|
+
seen: ta.Set[DeployApp] = set()
|
166
|
+
for a in self.apps:
|
167
|
+
if a.app in seen:
|
168
|
+
raise KeyError(a.app)
|
169
|
+
seen.add(a.app)
|
170
|
+
|
171
|
+
# @ta.override
|
138
172
|
def key(self) -> DeployKey:
|
139
|
-
return DeployKey(
|
173
|
+
return DeployKey(self._key_str())
|
@@ -0,0 +1,225 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import abc
|
3
|
+
import dataclasses as dc
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
from omlish.lite.check import check
|
7
|
+
|
8
|
+
|
9
|
+
##
|
10
|
+
|
11
|
+
|
12
|
+
DEPLOY_TAG_SIGIL = '@'
|
13
|
+
|
14
|
+
DEPLOY_TAG_SEPARATOR = '--'
|
15
|
+
|
16
|
+
DEPLOY_TAG_DELIMITERS: ta.AbstractSet[str] = frozenset([
|
17
|
+
DEPLOY_TAG_SEPARATOR,
|
18
|
+
'.',
|
19
|
+
])
|
20
|
+
|
21
|
+
DEPLOY_TAG_ILLEGAL_STRS: ta.AbstractSet[str] = frozenset([
|
22
|
+
DEPLOY_TAG_SIGIL,
|
23
|
+
*DEPLOY_TAG_DELIMITERS,
|
24
|
+
'/',
|
25
|
+
])
|
26
|
+
|
27
|
+
|
28
|
+
##
|
29
|
+
|
30
|
+
|
31
|
+
@dc.dataclass(frozen=True)
|
32
|
+
class DeployTag(abc.ABC): # noqa
|
33
|
+
s: str
|
34
|
+
|
35
|
+
def __post_init__(self) -> None:
|
36
|
+
check.not_in(abc.ABC, type(self).__bases__)
|
37
|
+
check.non_empty_str(self.s)
|
38
|
+
for ch in DEPLOY_TAG_ILLEGAL_STRS:
|
39
|
+
check.state(ch not in self.s)
|
40
|
+
|
41
|
+
#
|
42
|
+
|
43
|
+
tag_name: ta.ClassVar[str]
|
44
|
+
tag_kwarg: ta.ClassVar[str]
|
45
|
+
|
46
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
47
|
+
super().__init_subclass__(**kwargs)
|
48
|
+
|
49
|
+
if abc.ABC in cls.__bases__:
|
50
|
+
return
|
51
|
+
|
52
|
+
for b in cls.__bases__:
|
53
|
+
if issubclass(b, DeployTag):
|
54
|
+
check.in_(abc.ABC, b.__bases__)
|
55
|
+
|
56
|
+
check.non_empty_str(tn := cls.tag_name)
|
57
|
+
check.equal(tn, tn.lower().strip())
|
58
|
+
check.not_in('_', tn)
|
59
|
+
|
60
|
+
check.state(not hasattr(cls, 'tag_kwarg'))
|
61
|
+
cls.tag_kwarg = tn.replace('-', '_')
|
62
|
+
|
63
|
+
|
64
|
+
##
|
65
|
+
|
66
|
+
|
67
|
+
_DEPLOY_TAGS: ta.Set[ta.Type[DeployTag]] = set()
|
68
|
+
DEPLOY_TAGS: ta.AbstractSet[ta.Type[DeployTag]] = _DEPLOY_TAGS
|
69
|
+
|
70
|
+
_DEPLOY_TAGS_BY_NAME: ta.Dict[str, ta.Type[DeployTag]] = {}
|
71
|
+
DEPLOY_TAGS_BY_NAME: ta.Mapping[str, ta.Type[DeployTag]] = _DEPLOY_TAGS_BY_NAME
|
72
|
+
|
73
|
+
_DEPLOY_TAGS_BY_KWARG: ta.Dict[str, ta.Type[DeployTag]] = {}
|
74
|
+
DEPLOY_TAGS_BY_KWARG: ta.Mapping[str, ta.Type[DeployTag]] = _DEPLOY_TAGS_BY_KWARG
|
75
|
+
|
76
|
+
|
77
|
+
def _register_deploy_tag(cls):
|
78
|
+
check.not_in(cls.tag_name, _DEPLOY_TAGS_BY_NAME)
|
79
|
+
check.not_in(cls.tag_kwarg, _DEPLOY_TAGS_BY_KWARG)
|
80
|
+
|
81
|
+
_DEPLOY_TAGS.add(cls)
|
82
|
+
_DEPLOY_TAGS_BY_NAME[cls.tag_name] = cls
|
83
|
+
_DEPLOY_TAGS_BY_KWARG[cls.tag_kwarg] = cls
|
84
|
+
|
85
|
+
return cls
|
86
|
+
|
87
|
+
|
88
|
+
##
|
89
|
+
|
90
|
+
|
91
|
+
@_register_deploy_tag
|
92
|
+
class DeployTime(DeployTag):
|
93
|
+
tag_name: ta.ClassVar[str] = 'time'
|
94
|
+
|
95
|
+
|
96
|
+
##
|
97
|
+
|
98
|
+
|
99
|
+
class NameDeployTag(DeployTag, abc.ABC): # noqa
|
100
|
+
pass
|
101
|
+
|
102
|
+
|
103
|
+
@_register_deploy_tag
|
104
|
+
class DeployApp(NameDeployTag):
|
105
|
+
tag_name: ta.ClassVar[str] = 'app'
|
106
|
+
|
107
|
+
|
108
|
+
@_register_deploy_tag
|
109
|
+
class DeployConf(NameDeployTag):
|
110
|
+
tag_name: ta.ClassVar[str] = 'conf'
|
111
|
+
|
112
|
+
|
113
|
+
##
|
114
|
+
|
115
|
+
|
116
|
+
class KeyDeployTag(DeployTag, abc.ABC): # noqa
|
117
|
+
pass
|
118
|
+
|
119
|
+
|
120
|
+
@_register_deploy_tag
|
121
|
+
class DeployKey(KeyDeployTag):
|
122
|
+
tag_name: ta.ClassVar[str] = 'deploy-key'
|
123
|
+
|
124
|
+
|
125
|
+
@_register_deploy_tag
|
126
|
+
class DeployAppKey(KeyDeployTag):
|
127
|
+
tag_name: ta.ClassVar[str] = 'app-key'
|
128
|
+
|
129
|
+
|
130
|
+
##
|
131
|
+
|
132
|
+
|
133
|
+
class RevDeployTag(DeployTag, abc.ABC): # noqa
|
134
|
+
pass
|
135
|
+
|
136
|
+
|
137
|
+
@_register_deploy_tag
|
138
|
+
class DeployAppRev(RevDeployTag):
|
139
|
+
tag_name: ta.ClassVar[str] = 'app-rev'
|
140
|
+
|
141
|
+
|
142
|
+
##
|
143
|
+
|
144
|
+
|
145
|
+
class DeployTagMap:
|
146
|
+
def __init__(
|
147
|
+
self,
|
148
|
+
*args: DeployTag,
|
149
|
+
**kwargs: str,
|
150
|
+
) -> None:
|
151
|
+
super().__init__()
|
152
|
+
|
153
|
+
dct: ta.Dict[ta.Type[DeployTag], DeployTag] = {}
|
154
|
+
|
155
|
+
for a in args:
|
156
|
+
c = type(check.isinstance(a, DeployTag))
|
157
|
+
check.not_in(c, dct)
|
158
|
+
dct[c] = a
|
159
|
+
|
160
|
+
for k, v in kwargs.items():
|
161
|
+
c = DEPLOY_TAGS_BY_KWARG[k]
|
162
|
+
check.not_in(c, dct)
|
163
|
+
dct[c] = c(v)
|
164
|
+
|
165
|
+
self._dct = dct
|
166
|
+
self._tup = tuple(sorted((type(t).tag_kwarg, t.s) for t in dct.values()))
|
167
|
+
|
168
|
+
#
|
169
|
+
|
170
|
+
def add(self, *args: ta.Any, **kwargs: ta.Any) -> 'DeployTagMap':
|
171
|
+
return DeployTagMap(
|
172
|
+
*self,
|
173
|
+
*args,
|
174
|
+
**kwargs,
|
175
|
+
)
|
176
|
+
|
177
|
+
def remove(self, *tags_or_names: ta.Union[ta.Type[DeployTag], str]) -> 'DeployTagMap':
|
178
|
+
dcs = {
|
179
|
+
check.issubclass(a, DeployTag) if isinstance(a, type) else DEPLOY_TAGS_BY_NAME[a]
|
180
|
+
for a in tags_or_names
|
181
|
+
}
|
182
|
+
|
183
|
+
return DeployTagMap(*[
|
184
|
+
t
|
185
|
+
for t in self._dct.values()
|
186
|
+
if t not in dcs
|
187
|
+
])
|
188
|
+
|
189
|
+
#
|
190
|
+
|
191
|
+
def __repr__(self) -> str:
|
192
|
+
return f'{self.__class__.__name__}({", ".join(f"{k}={v!r}" for k, v in self._tup)})'
|
193
|
+
|
194
|
+
def __hash__(self) -> int:
|
195
|
+
return hash(self._tup)
|
196
|
+
|
197
|
+
def __eq__(self, other: object) -> bool:
|
198
|
+
if isinstance(other, DeployTagMap):
|
199
|
+
return self._tup == other._tup
|
200
|
+
else:
|
201
|
+
return NotImplemented
|
202
|
+
|
203
|
+
#
|
204
|
+
|
205
|
+
def __len__(self) -> int:
|
206
|
+
return len(self._dct)
|
207
|
+
|
208
|
+
def __iter__(self) -> ta.Iterator[DeployTag]:
|
209
|
+
return iter(self._dct.values())
|
210
|
+
|
211
|
+
def __getitem__(self, key: ta.Union[ta.Type[DeployTag], str]) -> DeployTag:
|
212
|
+
if isinstance(key, str):
|
213
|
+
return self._dct[DEPLOY_TAGS_BY_NAME[key]]
|
214
|
+
elif isinstance(key, type):
|
215
|
+
return self._dct[key]
|
216
|
+
else:
|
217
|
+
raise TypeError(key)
|
218
|
+
|
219
|
+
def __contains__(self, key: ta.Union[ta.Type[DeployTag], str]) -> bool:
|
220
|
+
if isinstance(key, str):
|
221
|
+
return DEPLOY_TAGS_BY_NAME[key] in self._dct
|
222
|
+
elif isinstance(key, type):
|
223
|
+
return key in self._dct
|
224
|
+
else:
|
225
|
+
raise TypeError(key)
|
ominfra/manage/deploy/types.py
CHANGED
@@ -1,39 +1,9 @@
|
|
1
|
-
import dataclasses as dc
|
2
1
|
import typing as ta
|
3
2
|
|
4
|
-
from omlish.lite.check import check
|
5
|
-
|
6
|
-
|
7
|
-
DeployPathKind = ta.Literal['dir', 'file'] # ta.TypeAlias
|
8
|
-
DeployPathPlaceholder = ta.Literal['app', 'tag', 'conf'] # ta.TypeAlias
|
9
|
-
|
10
3
|
|
11
4
|
##
|
12
5
|
|
13
6
|
|
14
7
|
DeployHome = ta.NewType('DeployHome', str)
|
15
8
|
|
16
|
-
DeployApp = ta.NewType('DeployApp', str)
|
17
|
-
DeployTag = ta.NewType('DeployTag', str)
|
18
9
|
DeployRev = ta.NewType('DeployRev', str)
|
19
|
-
DeployKey = ta.NewType('DeployKey', str)
|
20
|
-
|
21
|
-
|
22
|
-
##
|
23
|
-
|
24
|
-
|
25
|
-
@dc.dataclass(frozen=True)
|
26
|
-
class DeployAppTag:
|
27
|
-
app: DeployApp
|
28
|
-
tag: DeployTag
|
29
|
-
|
30
|
-
def __post_init__(self) -> None:
|
31
|
-
for s in [self.app, self.tag]:
|
32
|
-
check.non_empty_str(s)
|
33
|
-
check.equal(s, s.strip())
|
34
|
-
|
35
|
-
def placeholders(self) -> ta.Mapping[DeployPathPlaceholder, str]:
|
36
|
-
return {
|
37
|
-
'app': self.app,
|
38
|
-
'tag': self.tag,
|
39
|
-
}
|
ominfra/scripts/journald2aws.py
CHANGED
@@ -1450,6 +1450,9 @@ log = logging.getLogger(__name__)
|
|
1450
1450
|
# ../../../../../omlish/lite/reflect.py
|
1451
1451
|
|
1452
1452
|
|
1453
|
+
##
|
1454
|
+
|
1455
|
+
|
1453
1456
|
_GENERIC_ALIAS_TYPES = (
|
1454
1457
|
ta._GenericAlias, # type: ignore # noqa
|
1455
1458
|
*([ta._SpecialGenericAlias] if hasattr(ta, '_SpecialGenericAlias') else []), # noqa
|
@@ -1467,6 +1470,9 @@ is_union_alias = functools.partial(is_generic_alias, origin=ta.Union)
|
|
1467
1470
|
is_callable_alias = functools.partial(is_generic_alias, origin=ta.Callable)
|
1468
1471
|
|
1469
1472
|
|
1473
|
+
##
|
1474
|
+
|
1475
|
+
|
1470
1476
|
def is_optional_alias(spec: ta.Any) -> bool:
|
1471
1477
|
return (
|
1472
1478
|
isinstance(spec, _GENERIC_ALIAS_TYPES) and # noqa
|
@@ -1481,6 +1487,9 @@ def get_optional_alias_arg(spec: ta.Any) -> ta.Any:
|
|
1481
1487
|
return it
|
1482
1488
|
|
1483
1489
|
|
1490
|
+
##
|
1491
|
+
|
1492
|
+
|
1484
1493
|
def is_new_type(spec: ta.Any) -> bool:
|
1485
1494
|
if isinstance(ta.NewType, type):
|
1486
1495
|
return isinstance(spec, ta.NewType)
|
@@ -1493,6 +1502,26 @@ def get_new_type_supertype(spec: ta.Any) -> ta.Any:
|
|
1493
1502
|
return spec.__supertype__
|
1494
1503
|
|
1495
1504
|
|
1505
|
+
##
|
1506
|
+
|
1507
|
+
|
1508
|
+
def is_literal_type(spec: ta.Any) -> bool:
|
1509
|
+
if hasattr(ta, '_LiteralGenericAlias'):
|
1510
|
+
return isinstance(spec, ta._LiteralGenericAlias) # noqa
|
1511
|
+
else:
|
1512
|
+
return (
|
1513
|
+
isinstance(spec, ta._GenericAlias) and # type: ignore # noqa
|
1514
|
+
spec.__origin__ is ta.Literal
|
1515
|
+
)
|
1516
|
+
|
1517
|
+
|
1518
|
+
def get_literal_type_args(spec: ta.Any) -> ta.Iterable[ta.Any]:
|
1519
|
+
return spec.__args__
|
1520
|
+
|
1521
|
+
|
1522
|
+
##
|
1523
|
+
|
1524
|
+
|
1496
1525
|
def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
|
1497
1526
|
seen = set()
|
1498
1527
|
todo = list(reversed(cls.__subclasses__()))
|
@@ -2600,6 +2629,18 @@ class OptionalObjMarshaler(ObjMarshaler):
|
|
2600
2629
|
return self.item.unmarshal(o, ctx)
|
2601
2630
|
|
2602
2631
|
|
2632
|
+
@dc.dataclass(frozen=True)
|
2633
|
+
class LiteralObjMarshaler(ObjMarshaler):
|
2634
|
+
item: ObjMarshaler
|
2635
|
+
vs: frozenset
|
2636
|
+
|
2637
|
+
def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
2638
|
+
return self.item.marshal(check.in_(o, self.vs), ctx)
|
2639
|
+
|
2640
|
+
def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
|
2641
|
+
return check.in_(self.item.unmarshal(o, ctx), self.vs)
|
2642
|
+
|
2643
|
+
|
2603
2644
|
@dc.dataclass(frozen=True)
|
2604
2645
|
class MappingObjMarshaler(ObjMarshaler):
|
2605
2646
|
ty: type
|
@@ -2811,6 +2852,11 @@ class ObjMarshalerManager:
|
|
2811
2852
|
if is_new_type(ty):
|
2812
2853
|
return rec(get_new_type_supertype(ty))
|
2813
2854
|
|
2855
|
+
if is_literal_type(ty):
|
2856
|
+
lvs = frozenset(get_literal_type_args(ty))
|
2857
|
+
lty = check.single(set(map(type, lvs)))
|
2858
|
+
return LiteralObjMarshaler(rec(lty), lvs)
|
2859
|
+
|
2814
2860
|
if is_generic_alias(ty):
|
2815
2861
|
try:
|
2816
2862
|
mt = self._generic_mapping_types[ta.get_origin(ty)]
|