ominfra 0.0.0.dev137__py3-none-any.whl → 0.0.0.dev139__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- ominfra/manage/__init__.py +13 -0
- ominfra/manage/{new/main.py → main.py} +68 -18
- ominfra/pyremote.py +196 -145
- ominfra/{manage/new/_manage.py → scripts/manage.py} +267 -170
- ominfra/scripts/supervisor.py +32 -31
- ominfra/supervisor/processimpl.py +32 -31
- {ominfra-0.0.0.dev137.dist-info → ominfra-0.0.0.dev139.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev137.dist-info → ominfra-0.0.0.dev139.dist-info}/RECORD +15 -44
- ominfra/manage/deploy/_executor.py +0 -1415
- ominfra/manage/deploy/configs.py +0 -19
- ominfra/manage/deploy/executor/__init__.py +0 -1
- ominfra/manage/deploy/executor/base.py +0 -115
- ominfra/manage/deploy/executor/concerns/__init__.py +0 -0
- ominfra/manage/deploy/executor/concerns/dirs.py +0 -28
- ominfra/manage/deploy/executor/concerns/nginx.py +0 -47
- ominfra/manage/deploy/executor/concerns/repo.py +0 -17
- ominfra/manage/deploy/executor/concerns/supervisor.py +0 -46
- ominfra/manage/deploy/executor/concerns/systemd.py +0 -88
- ominfra/manage/deploy/executor/concerns/user.py +0 -25
- ominfra/manage/deploy/executor/concerns/venv.py +0 -22
- ominfra/manage/deploy/executor/main.py +0 -119
- ominfra/manage/deploy/poly/__init__.py +0 -1
- ominfra/manage/deploy/poly/_main.py +0 -975
- ominfra/manage/deploy/poly/base.py +0 -178
- ominfra/manage/deploy/poly/configs.py +0 -38
- ominfra/manage/deploy/poly/deploy.py +0 -25
- ominfra/manage/deploy/poly/main.py +0 -18
- ominfra/manage/deploy/poly/nginx.py +0 -60
- ominfra/manage/deploy/poly/repo.py +0 -41
- ominfra/manage/deploy/poly/runtime.py +0 -39
- ominfra/manage/deploy/poly/site.py +0 -11
- ominfra/manage/deploy/poly/supervisor.py +0 -64
- ominfra/manage/deploy/poly/venv.py +0 -52
- ominfra/manage/deploy/remote.py +0 -91
- ominfra/manage/manage.py +0 -12
- ominfra/manage/new/__init__.py +0 -1
- ominfra/manage/new/commands/__init__.py +0 -0
- /ominfra/manage/{deploy → commands}/__init__.py +0 -0
- /ominfra/manage/{new/commands → commands}/base.py +0 -0
- /ominfra/manage/{new/commands → commands}/subprocess.py +0 -0
- {ominfra-0.0.0.dev137.dist-info → ominfra-0.0.0.dev139.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev137.dist-info → ominfra-0.0.0.dev139.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev137.dist-info → ominfra-0.0.0.dev139.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev137.dist-info → ominfra-0.0.0.dev139.dist-info}/top_level.txt +0 -0
@@ -1,178 +0,0 @@
|
|
1
|
-
# ruff: noqa: UP006 UP007
|
2
|
-
import abc
|
3
|
-
import dataclasses as dc
|
4
|
-
import typing as ta
|
5
|
-
|
6
|
-
from .configs import DeployConcernConfig # noqa
|
7
|
-
from .configs import DeployConfig
|
8
|
-
from .configs import SiteConcernConfig # noqa
|
9
|
-
from .configs import SiteConfig
|
10
|
-
|
11
|
-
|
12
|
-
T = ta.TypeVar('T')
|
13
|
-
|
14
|
-
ConcernT = ta.TypeVar('ConcernT')
|
15
|
-
ConfigT = ta.TypeVar('ConfigT')
|
16
|
-
|
17
|
-
SiteConcernT = ta.TypeVar('SiteConcernT', bound='SiteConcern')
|
18
|
-
SiteConcernConfigT = ta.TypeVar('SiteConcernConfigT', bound='SiteConcernConfig')
|
19
|
-
|
20
|
-
DeployConcernT = ta.TypeVar('DeployConcernT', bound='DeployConcern')
|
21
|
-
DeployConcernConfigT = ta.TypeVar('DeployConcernConfigT', bound='DeployConcernConfig')
|
22
|
-
|
23
|
-
|
24
|
-
##
|
25
|
-
|
26
|
-
|
27
|
-
@dc.dataclass(frozen=True)
|
28
|
-
class FsItem(abc.ABC):
|
29
|
-
path: str
|
30
|
-
|
31
|
-
@property
|
32
|
-
@abc.abstractmethod
|
33
|
-
def is_dir(self) -> bool:
|
34
|
-
raise NotImplementedError
|
35
|
-
|
36
|
-
|
37
|
-
@dc.dataclass(frozen=True)
|
38
|
-
class FsFile(FsItem):
|
39
|
-
@property
|
40
|
-
def is_dir(self) -> bool:
|
41
|
-
return False
|
42
|
-
|
43
|
-
|
44
|
-
@dc.dataclass(frozen=True)
|
45
|
-
class FsDir(FsItem):
|
46
|
-
@property
|
47
|
-
def is_dir(self) -> bool:
|
48
|
-
return True
|
49
|
-
|
50
|
-
|
51
|
-
##
|
52
|
-
|
53
|
-
|
54
|
-
class Runtime(abc.ABC):
|
55
|
-
class Stat(ta.NamedTuple):
|
56
|
-
path: str
|
57
|
-
is_dir: bool
|
58
|
-
|
59
|
-
@abc.abstractmethod
|
60
|
-
def stat(self, p: str) -> ta.Optional[Stat]:
|
61
|
-
raise NotImplementedError
|
62
|
-
|
63
|
-
@abc.abstractmethod
|
64
|
-
def make_dirs(self, p: str, exist_ok: bool = False) -> None:
|
65
|
-
raise NotImplementedError
|
66
|
-
|
67
|
-
@abc.abstractmethod
|
68
|
-
def write_file(self, p: str, c: ta.Union[str, bytes]) -> None:
|
69
|
-
raise NotImplementedError
|
70
|
-
|
71
|
-
@abc.abstractmethod
|
72
|
-
def sh(self, *ss: str) -> None:
|
73
|
-
raise NotImplementedError
|
74
|
-
|
75
|
-
|
76
|
-
##
|
77
|
-
|
78
|
-
|
79
|
-
class ConcernsContainer(abc.ABC, ta.Generic[ConcernT, ConfigT]):
|
80
|
-
concern_cls: ta.ClassVar[type]
|
81
|
-
|
82
|
-
def __init__(
|
83
|
-
self,
|
84
|
-
config: ConfigT,
|
85
|
-
) -> None:
|
86
|
-
super().__init__()
|
87
|
-
self._config = config
|
88
|
-
|
89
|
-
concern_cls_dct = self._concern_cls_by_config_cls()
|
90
|
-
self._concerns = [
|
91
|
-
concern_cls_dct[type(c)](c, self) # type: ignore
|
92
|
-
for c in config.concerns # type: ignore
|
93
|
-
]
|
94
|
-
self._concerns_by_cls: ta.Dict[ta.Type[ConcernT], ConcernT] = {}
|
95
|
-
for c in self._concerns:
|
96
|
-
if type(c) in self._concerns_by_cls:
|
97
|
-
raise TypeError(f'Duplicate concern type: {c}')
|
98
|
-
self._concerns_by_cls[type(c)] = c
|
99
|
-
|
100
|
-
@classmethod
|
101
|
-
def _concern_cls_by_config_cls(cls) -> ta.Mapping[type, ta.Type[ConcernT]]:
|
102
|
-
return { # noqa
|
103
|
-
c.Config: c # type: ignore
|
104
|
-
for c in cls.concern_cls.__subclasses__()
|
105
|
-
}
|
106
|
-
|
107
|
-
@property
|
108
|
-
def config(self) -> ConfigT:
|
109
|
-
return self._config
|
110
|
-
|
111
|
-
@property
|
112
|
-
def concerns(self) -> ta.List[ConcernT]:
|
113
|
-
return self._concerns
|
114
|
-
|
115
|
-
def concern(self, cls: ta.Type[T]) -> T:
|
116
|
-
return self._concerns_by_cls[cls] # type: ignore
|
117
|
-
|
118
|
-
|
119
|
-
##
|
120
|
-
|
121
|
-
|
122
|
-
class SiteConcern(abc.ABC, ta.Generic[SiteConcernConfigT]):
|
123
|
-
def __init__(self, config: SiteConcernConfigT, site: 'Site') -> None:
|
124
|
-
super().__init__()
|
125
|
-
self._config = config
|
126
|
-
self._site = site
|
127
|
-
|
128
|
-
@property
|
129
|
-
def config(self) -> SiteConcernConfigT:
|
130
|
-
return self._config
|
131
|
-
|
132
|
-
@abc.abstractmethod
|
133
|
-
def run(self, runtime: Runtime) -> None:
|
134
|
-
raise NotImplementedError
|
135
|
-
|
136
|
-
|
137
|
-
##
|
138
|
-
|
139
|
-
|
140
|
-
class Site(ConcernsContainer[SiteConcern, SiteConfig]):
|
141
|
-
@abc.abstractmethod
|
142
|
-
def run(self, runtime: Runtime) -> None:
|
143
|
-
raise NotImplementedError
|
144
|
-
|
145
|
-
|
146
|
-
##
|
147
|
-
|
148
|
-
|
149
|
-
class DeployConcern(abc.ABC, ta.Generic[DeployConcernConfigT]):
|
150
|
-
def __init__(self, config: DeployConcernConfigT, deploy: 'Deploy') -> None:
|
151
|
-
super().__init__()
|
152
|
-
self._config = config
|
153
|
-
self._deploy = deploy
|
154
|
-
|
155
|
-
@property
|
156
|
-
def config(self) -> DeployConcernConfigT:
|
157
|
-
return self._config
|
158
|
-
|
159
|
-
def fs_items(self) -> ta.Sequence[FsItem]:
|
160
|
-
return []
|
161
|
-
|
162
|
-
@abc.abstractmethod
|
163
|
-
def run(self, runtime: Runtime) -> None:
|
164
|
-
raise NotImplementedError
|
165
|
-
|
166
|
-
|
167
|
-
##
|
168
|
-
|
169
|
-
|
170
|
-
class Deploy(ConcernsContainer[DeployConcern, DeployConfig]):
|
171
|
-
@property
|
172
|
-
@abc.abstractmethod
|
173
|
-
def site(self) -> Site:
|
174
|
-
raise NotImplementedError
|
175
|
-
|
176
|
-
@abc.abstractmethod
|
177
|
-
def run(self, runtime: Runtime) -> None:
|
178
|
-
raise NotImplementedError
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# ruff: noqa: UP006
|
2
|
-
import abc
|
3
|
-
import dataclasses as dc
|
4
|
-
import typing as ta
|
5
|
-
|
6
|
-
|
7
|
-
##
|
8
|
-
|
9
|
-
|
10
|
-
@dc.dataclass(frozen=True)
|
11
|
-
class SiteConcernConfig(abc.ABC): # noqa
|
12
|
-
pass
|
13
|
-
|
14
|
-
|
15
|
-
@dc.dataclass(frozen=True)
|
16
|
-
class SiteConfig:
|
17
|
-
user = 'omlish'
|
18
|
-
|
19
|
-
root_dir: str = '~/deploy'
|
20
|
-
|
21
|
-
concerns: ta.List[SiteConcernConfig] = dc.field(default_factory=list)
|
22
|
-
|
23
|
-
|
24
|
-
##
|
25
|
-
|
26
|
-
|
27
|
-
@dc.dataclass(frozen=True)
|
28
|
-
class DeployConcernConfig(abc.ABC): # noqa
|
29
|
-
pass
|
30
|
-
|
31
|
-
|
32
|
-
@dc.dataclass(frozen=True)
|
33
|
-
class DeployConfig:
|
34
|
-
site: SiteConfig
|
35
|
-
|
36
|
-
name: str
|
37
|
-
|
38
|
-
concerns: ta.List[DeployConcernConfig] = dc.field(default_factory=list)
|
@@ -1,25 +0,0 @@
|
|
1
|
-
from .base import Deploy
|
2
|
-
from .base import DeployConcern
|
3
|
-
from .base import Runtime
|
4
|
-
from .base import Site
|
5
|
-
from .configs import DeployConfig
|
6
|
-
|
7
|
-
|
8
|
-
class DeployImpl(Deploy):
|
9
|
-
concern_cls = DeployConcern
|
10
|
-
|
11
|
-
def __init__(
|
12
|
-
self,
|
13
|
-
config: DeployConfig,
|
14
|
-
site: Site,
|
15
|
-
) -> None:
|
16
|
-
super().__init__(config)
|
17
|
-
self._site = site
|
18
|
-
|
19
|
-
@property
|
20
|
-
def site(self) -> Site:
|
21
|
-
return self._site
|
22
|
-
|
23
|
-
def run(self, runtime: Runtime) -> None:
|
24
|
-
for c in self._concerns:
|
25
|
-
c.run(runtime)
|
@@ -1,18 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# @omlish-amalg ./_main.py
|
3
|
-
from .deploy import DeployImpl # noqa
|
4
|
-
from .nginx import NginxDeployConcern # noqa
|
5
|
-
from .nginx import NginxSiteConcern # noqa
|
6
|
-
from .repo import RepoDeployConcern # noqa
|
7
|
-
from .runtime import RuntimeImpl # noqa
|
8
|
-
from .site import SiteImpl # noqa
|
9
|
-
from .supervisor import SupervisorDeployConcern # noqa
|
10
|
-
from .venv import VenvDeployConcern # noqa
|
11
|
-
|
12
|
-
|
13
|
-
def _main() -> None:
|
14
|
-
pass
|
15
|
-
|
16
|
-
|
17
|
-
if __name__ == '__main__':
|
18
|
-
_main()
|
@@ -1,60 +0,0 @@
|
|
1
|
-
import dataclasses as dc
|
2
|
-
import os.path
|
3
|
-
import textwrap
|
4
|
-
import typing as ta
|
5
|
-
|
6
|
-
from omlish.lite.cached import cached_nullary
|
7
|
-
|
8
|
-
from .base import DeployConcern
|
9
|
-
from .base import FsFile
|
10
|
-
from .base import FsItem
|
11
|
-
from .base import Runtime
|
12
|
-
from .base import SiteConcern
|
13
|
-
from .configs import DeployConcernConfig
|
14
|
-
from .configs import SiteConcernConfig
|
15
|
-
|
16
|
-
|
17
|
-
class NginxSiteConcern(SiteConcern['NginxSiteConcern.Config']):
|
18
|
-
@dc.dataclass(frozen=True)
|
19
|
-
class Config(SiteConcernConfig):
|
20
|
-
global_conf_file: str = '/etc/nginx/sites-enabled/omlish.conf'
|
21
|
-
|
22
|
-
@cached_nullary
|
23
|
-
def confs_dir(self) -> str:
|
24
|
-
return os.path.join(self._site.config.root_dir, 'conf', 'nginx')
|
25
|
-
|
26
|
-
def run(self, runtime: Runtime) -> None:
|
27
|
-
if runtime.stat(self._config.global_conf_file) is None:
|
28
|
-
runtime.write_file(
|
29
|
-
self._config.global_conf_file,
|
30
|
-
f'include {self.confs_dir()}/*.conf;\n',
|
31
|
-
)
|
32
|
-
|
33
|
-
|
34
|
-
class NginxDeployConcern(DeployConcern['NginxDeployConcern.Config']):
|
35
|
-
@dc.dataclass(frozen=True)
|
36
|
-
class Config(DeployConcernConfig):
|
37
|
-
listen_port: int = 80
|
38
|
-
proxy_port: int = 8000
|
39
|
-
|
40
|
-
@cached_nullary
|
41
|
-
def conf_file(self) -> str:
|
42
|
-
return os.path.join(self._deploy.site.concern(NginxSiteConcern).confs_dir(), self._deploy.config.name + '.conf')
|
43
|
-
|
44
|
-
@cached_nullary
|
45
|
-
def fs_items(self) -> ta.Sequence[FsItem]:
|
46
|
-
return [FsFile(self.conf_file())]
|
47
|
-
|
48
|
-
def run(self, runtime: Runtime) -> None:
|
49
|
-
runtime.make_dirs(os.path.dirname(self.conf_file()))
|
50
|
-
|
51
|
-
conf = textwrap.dedent(f"""
|
52
|
-
server {{
|
53
|
-
listen {self._config.listen_port};
|
54
|
-
location / {{
|
55
|
-
proxy_pass http://127.0.0.1:{self._config.proxy_port}/;
|
56
|
-
}}
|
57
|
-
}}
|
58
|
-
""")
|
59
|
-
|
60
|
-
runtime.write_file(self.conf_file(), conf)
|
@@ -1,41 +0,0 @@
|
|
1
|
-
import dataclasses as dc
|
2
|
-
import os.path
|
3
|
-
import typing as ta
|
4
|
-
|
5
|
-
from omlish.lite.cached import cached_nullary
|
6
|
-
|
7
|
-
from .base import DeployConcern
|
8
|
-
from .base import FsDir
|
9
|
-
from .base import FsItem
|
10
|
-
from .base import Runtime
|
11
|
-
from .configs import DeployConcernConfig
|
12
|
-
|
13
|
-
|
14
|
-
class RepoDeployConcern(DeployConcern['RepoDeployConcern.Config']):
|
15
|
-
@dc.dataclass(frozen=True)
|
16
|
-
class Config(DeployConcernConfig):
|
17
|
-
url: str
|
18
|
-
revision: str = 'master'
|
19
|
-
init_submodules: bool = False
|
20
|
-
|
21
|
-
@cached_nullary
|
22
|
-
def repo_dir(self) -> str:
|
23
|
-
return os.path.join(self._deploy.site.config.root_dir, 'repos', self._deploy.config.name)
|
24
|
-
|
25
|
-
@cached_nullary
|
26
|
-
def fs_items(self) -> ta.Sequence[FsItem]:
|
27
|
-
return [FsDir(self.repo_dir())]
|
28
|
-
|
29
|
-
def run(self, runtime: Runtime) -> None:
|
30
|
-
runtime.make_dirs(self.repo_dir())
|
31
|
-
|
32
|
-
runtime.sh(
|
33
|
-
f'cd {self.repo_dir()}',
|
34
|
-
'git init',
|
35
|
-
f'git remote add origin {self._config.url}',
|
36
|
-
f'git fetch --depth 1 origin {self._config.revision}',
|
37
|
-
'git checkout FETCH_HEAD',
|
38
|
-
*([
|
39
|
-
'git submodule update --init',
|
40
|
-
] if self._config.init_submodules else []),
|
41
|
-
)
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# ruff: noqa: UP007
|
2
|
-
import os.path
|
3
|
-
import stat
|
4
|
-
import typing as ta
|
5
|
-
|
6
|
-
from omlish.lite.logs import log
|
7
|
-
from omlish.lite.subprocesses import subprocess_check_call
|
8
|
-
|
9
|
-
from .base import Runtime
|
10
|
-
|
11
|
-
|
12
|
-
class RuntimeImpl(Runtime):
|
13
|
-
def __init__(self) -> None:
|
14
|
-
super().__init__()
|
15
|
-
|
16
|
-
def stat(self, p: str) -> ta.Optional[Runtime.Stat]:
|
17
|
-
try:
|
18
|
-
st = os.stat(p)
|
19
|
-
except FileNotFoundError:
|
20
|
-
return None
|
21
|
-
else:
|
22
|
-
return Runtime.Stat(
|
23
|
-
path=p,
|
24
|
-
is_dir=bool(st.st_mode & stat.S_IFDIR),
|
25
|
-
)
|
26
|
-
|
27
|
-
def make_dirs(self, p: str, exist_ok: bool = False) -> None:
|
28
|
-
os.makedirs(p, exist_ok=exist_ok)
|
29
|
-
|
30
|
-
def write_file(self, p: str, c: ta.Union[str, bytes]) -> None:
|
31
|
-
if os.path.exists(p):
|
32
|
-
raise RuntimeError(f'Path exists: {p}')
|
33
|
-
with open(p, 'w' if isinstance(c, str) else 'wb') as f:
|
34
|
-
f.write(c)
|
35
|
-
|
36
|
-
def sh(self, *ss: str) -> None:
|
37
|
-
s = ' && '.join(ss)
|
38
|
-
log.info('Executing: %s', s)
|
39
|
-
subprocess_check_call(s, shell=True)
|
@@ -1,64 +0,0 @@
|
|
1
|
-
import dataclasses as dc
|
2
|
-
import os.path
|
3
|
-
import textwrap
|
4
|
-
import typing as ta
|
5
|
-
|
6
|
-
from omlish.lite.cached import cached_nullary
|
7
|
-
|
8
|
-
from .base import DeployConcern
|
9
|
-
from .base import FsFile
|
10
|
-
from .base import FsItem
|
11
|
-
from .base import Runtime
|
12
|
-
from .configs import DeployConcernConfig
|
13
|
-
from .repo import RepoDeployConcern
|
14
|
-
from .venv import VenvDeployConcern
|
15
|
-
|
16
|
-
|
17
|
-
# class SupervisorSiteConcern(SiteConcern['SupervisorSiteConcern.Config']):
|
18
|
-
# @dc.dataclass(frozen=True)
|
19
|
-
# class Config(DeployConcern.Config):
|
20
|
-
# global_conf_file: str = '/etc/supervisor/conf.d/supervisord.conf'
|
21
|
-
#
|
22
|
-
# def run(self) -> None:
|
23
|
-
# sup_conf_dir = os.path.join(self._d.home_dir(), 'conf/supervisor')
|
24
|
-
# with open(self._d.host_cfg.global_supervisor_conf_file_path) as f:
|
25
|
-
# glo_sup_conf = f.read()
|
26
|
-
# if sup_conf_dir not in glo_sup_conf:
|
27
|
-
# log.info('Updating global supervisor conf at %s', self._d.host_cfg.global_supervisor_conf_file_path) # noqa
|
28
|
-
# glo_sup_conf += textwrap.dedent(f"""
|
29
|
-
# [include]
|
30
|
-
# files = {self._d.home_dir()}/conf/supervisor/*.conf
|
31
|
-
# """)
|
32
|
-
# with open(self._d.host_cfg.global_supervisor_conf_file_path, 'w') as f:
|
33
|
-
# f.write(glo_sup_conf)
|
34
|
-
|
35
|
-
|
36
|
-
class SupervisorDeployConcern(DeployConcern['SupervisorDeployConcern.Config']):
|
37
|
-
@dc.dataclass(frozen=True)
|
38
|
-
class Config(DeployConcernConfig):
|
39
|
-
entrypoint: str
|
40
|
-
|
41
|
-
@cached_nullary
|
42
|
-
def conf_file(self) -> str:
|
43
|
-
return os.path.join(self._deploy.site.config.root_dir, 'conf', 'supervisor', self._deploy.config.name + '.conf')
|
44
|
-
|
45
|
-
@cached_nullary
|
46
|
-
def fs_items(self) -> ta.Sequence[FsItem]:
|
47
|
-
return [FsFile(self.conf_file())]
|
48
|
-
|
49
|
-
def run(self, runtime: Runtime) -> None:
|
50
|
-
runtime.make_dirs(os.path.dirname(self.conf_file()))
|
51
|
-
|
52
|
-
rd = self._deploy.concern(RepoDeployConcern).repo_dir()
|
53
|
-
vx = self._deploy.concern(VenvDeployConcern).exe()
|
54
|
-
|
55
|
-
conf = textwrap.dedent(f"""
|
56
|
-
[program:{self._deploy.config.name}]
|
57
|
-
command={vx} -m {self._config.entrypoint}
|
58
|
-
directory={rd}
|
59
|
-
user={self._deploy.site.config.user}
|
60
|
-
autostart=true
|
61
|
-
autorestart=true
|
62
|
-
""")
|
63
|
-
|
64
|
-
runtime.write_file(self.conf_file(), conf)
|
@@ -1,52 +0,0 @@
|
|
1
|
-
import dataclasses as dc
|
2
|
-
import os.path
|
3
|
-
import typing as ta
|
4
|
-
|
5
|
-
from omlish.lite.cached import cached_nullary
|
6
|
-
|
7
|
-
from .base import DeployConcern
|
8
|
-
from .base import FsDir
|
9
|
-
from .base import FsItem
|
10
|
-
from .base import Runtime
|
11
|
-
from .configs import DeployConcernConfig
|
12
|
-
from .repo import RepoDeployConcern
|
13
|
-
|
14
|
-
|
15
|
-
class VenvDeployConcern(DeployConcern['VenvDeployConcern.Config']):
|
16
|
-
@dc.dataclass(frozen=True)
|
17
|
-
class Config(DeployConcernConfig):
|
18
|
-
interp_version: str
|
19
|
-
requirements_txt: str = 'requirements.txt'
|
20
|
-
|
21
|
-
@cached_nullary
|
22
|
-
def venv_dir(self) -> str:
|
23
|
-
return os.path.join(self._deploy.site.config.root_dir, 'venvs', self._deploy.config.name)
|
24
|
-
|
25
|
-
@cached_nullary
|
26
|
-
def fs_items(self) -> ta.Sequence[FsItem]:
|
27
|
-
return [FsDir(self.venv_dir())]
|
28
|
-
|
29
|
-
@cached_nullary
|
30
|
-
def exe(self) -> str:
|
31
|
-
return os.path.join(self.venv_dir(), 'bin', 'python')
|
32
|
-
|
33
|
-
def run(self, runtime: Runtime) -> None:
|
34
|
-
runtime.make_dirs(self.venv_dir())
|
35
|
-
|
36
|
-
rd = self._deploy.concern(RepoDeployConcern).repo_dir()
|
37
|
-
|
38
|
-
l, r = os.path.split(self.venv_dir())
|
39
|
-
|
40
|
-
# FIXME: lol
|
41
|
-
py_exe = 'python3'
|
42
|
-
|
43
|
-
runtime.sh(
|
44
|
-
f'cd {l}',
|
45
|
-
f'{py_exe} -mvenv {r}',
|
46
|
-
|
47
|
-
# https://stackoverflow.com/questions/77364550/attributeerror-module-pkgutil-has-no-attribute-impimporter-did-you-mean
|
48
|
-
f'{self.exe()} -m ensurepip',
|
49
|
-
f'{self.exe()} -mpip install --upgrade setuptools pip',
|
50
|
-
|
51
|
-
f'{self.exe()} -mpip install -r {rd}/{self._config.requirements_txt}', # noqa
|
52
|
-
)
|
ominfra/manage/deploy/remote.py
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
See:
|
3
|
-
- piku, obviously
|
4
|
-
- https://github.com/mitogen-hq/mitogen/
|
5
|
-
|
6
|
-
git init
|
7
|
-
git remote add local ~/src/wrmsr/omlish/.git
|
8
|
-
git fetch --depth=1 local master
|
9
|
-
git remote add origin https://github.com/wrmsr/omlish
|
10
|
-
git fetch --depth=1 origin master
|
11
|
-
git checkout origin/master
|
12
|
-
|
13
|
-
{base_path}/{deploys}/
|
14
|
-
current ->
|
15
|
-
previous ->
|
16
|
-
20240522T120000_{rev}
|
17
|
-
"""
|
18
|
-
import asyncio
|
19
|
-
import itertools
|
20
|
-
import os.path
|
21
|
-
import shlex
|
22
|
-
import tempfile
|
23
|
-
|
24
|
-
from omlish import check
|
25
|
-
|
26
|
-
from ... import cmds
|
27
|
-
|
28
|
-
|
29
|
-
def render_script(*cs: list[str] | tuple[str, ...]) -> str:
|
30
|
-
return ' '.join(itertools.chain.from_iterable(
|
31
|
-
[
|
32
|
-
*(['&&'] if i > 0 else []),
|
33
|
-
shlex.join(check.not_isinstance(l, str)),
|
34
|
-
]
|
35
|
-
for i, l in enumerate(cs)
|
36
|
-
))
|
37
|
-
|
38
|
-
|
39
|
-
async def do_remote_deploy(
|
40
|
-
cr: cmds.CommandRunner,
|
41
|
-
rev: str = 'master',
|
42
|
-
*,
|
43
|
-
local_repo_path: str | None = None,
|
44
|
-
skip_submodules: bool = False,
|
45
|
-
) -> None:
|
46
|
-
clone_script = [
|
47
|
-
['git', 'init'],
|
48
|
-
|
49
|
-
*([
|
50
|
-
['git', 'remote', 'add', 'local', local_repo_path],
|
51
|
-
['git', 'fetch', '--depth=1', 'local', rev],
|
52
|
-
] if local_repo_path is not None else ()),
|
53
|
-
|
54
|
-
['git', 'remote', 'add', 'origin', 'https://github.com/wrmsr/omlish'],
|
55
|
-
['git', 'fetch', '--depth=1', 'origin', rev],
|
56
|
-
['git', 'checkout', f'origin/{rev}'],
|
57
|
-
|
58
|
-
*([['git', 'submodule', 'update', '--init']] if not skip_submodules else ()),
|
59
|
-
|
60
|
-
['make', 'venv-deploy'],
|
61
|
-
]
|
62
|
-
|
63
|
-
res = await cr.run_command(cr.Command([
|
64
|
-
'sh', '-c', render_script(
|
65
|
-
['mkdir', 'omlish'],
|
66
|
-
['cd', 'omlish'],
|
67
|
-
*clone_script,
|
68
|
-
),
|
69
|
-
]))
|
70
|
-
res.check()
|
71
|
-
|
72
|
-
|
73
|
-
async def _a_main():
|
74
|
-
cwd = tempfile.mkdtemp()
|
75
|
-
print(cwd)
|
76
|
-
|
77
|
-
bootstrap_git_path = os.path.join(os.getcwd(), '.git')
|
78
|
-
check.state(os.path.isdir(bootstrap_git_path))
|
79
|
-
|
80
|
-
cr: cmds.CommandRunner = cmds.LocalCommandRunner(cmds.LocalCommandRunner.Config(
|
81
|
-
cwd=cwd,
|
82
|
-
))
|
83
|
-
|
84
|
-
await do_remote_deploy(
|
85
|
-
cr,
|
86
|
-
local_repo_path=os.path.expanduser('~/src/wrmsr/omlish/.git'),
|
87
|
-
)
|
88
|
-
|
89
|
-
|
90
|
-
if __name__ == '__main__':
|
91
|
-
asyncio.run(_a_main())
|
ominfra/manage/manage.py
DELETED
ominfra/manage/new/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# @omlish-lite
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|