ominfra 0.0.0.dev171__py3-none-any.whl → 0.0.0.dev173__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/manage/targets/bestpython.sh +6 -9
- ominfra/scripts/manage.py +489 -200
- {ominfra-0.0.0.dev171.dist-info → ominfra-0.0.0.dev173.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev171.dist-info → ominfra-0.0.0.dev173.dist-info}/RECORD +16 -14
- {ominfra-0.0.0.dev171.dist-info → ominfra-0.0.0.dev173.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev171.dist-info → ominfra-0.0.0.dev173.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev171.dist-info → ominfra-0.0.0.dev173.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev171.dist-info → ominfra-0.0.0.dev173.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
|
-
}
|
@@ -1,15 +1,12 @@
|
|
1
1
|
bv=""
|
2
2
|
bx=""
|
3
3
|
|
4
|
-
for
|
5
|
-
x="python$
|
6
|
-
v=$($x -c "import sys; print(sys.version_info[:])" 2>/dev/null)
|
7
|
-
if [ $? -eq 0 ]; then
|
8
|
-
|
9
|
-
|
10
|
-
bv=$cv
|
11
|
-
bx=$x
|
12
|
-
fi
|
4
|
+
for v in "" 3 3.{8..13}; do
|
5
|
+
x="python$v"
|
6
|
+
v=$($x -c "import sys; print((\"%02d\" * 3) % sys.version_info[:3])" 2>/dev/null)
|
7
|
+
if [ $? -eq 0 ] && ([ -z "$bv" ] || [ "$v" \> "$bv" ]); then
|
8
|
+
bv=$v
|
9
|
+
bx=$x
|
13
10
|
fi
|
14
11
|
done
|
15
12
|
|