ominfra 0.0.0.dev138__py3-none-any.whl → 0.0.0.dev140__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.
Files changed (47) hide show
  1. ominfra/manage/__init__.py +13 -0
  2. ominfra/manage/{new/commands → commands}/base.py +9 -7
  3. ominfra/manage/{new/commands → commands}/subprocess.py +20 -15
  4. ominfra/manage/main.py +175 -0
  5. ominfra/manage/payload.py +35 -0
  6. ominfra/manage/spawning.py +100 -0
  7. ominfra/pyremote.py +18 -8
  8. ominfra/scripts/journald2aws.py +7 -0
  9. ominfra/{manage/new/_manage.py → scripts/manage.py} +248 -153
  10. ominfra/scripts/supervisor.py +7 -0
  11. {ominfra-0.0.0.dev138.dist-info → ominfra-0.0.0.dev140.dist-info}/METADATA +3 -3
  12. {ominfra-0.0.0.dev138.dist-info → ominfra-0.0.0.dev140.dist-info}/RECORD +17 -44
  13. ominfra/manage/deploy/_executor.py +0 -1415
  14. ominfra/manage/deploy/configs.py +0 -19
  15. ominfra/manage/deploy/executor/__init__.py +0 -1
  16. ominfra/manage/deploy/executor/base.py +0 -115
  17. ominfra/manage/deploy/executor/concerns/__init__.py +0 -0
  18. ominfra/manage/deploy/executor/concerns/dirs.py +0 -28
  19. ominfra/manage/deploy/executor/concerns/nginx.py +0 -47
  20. ominfra/manage/deploy/executor/concerns/repo.py +0 -17
  21. ominfra/manage/deploy/executor/concerns/supervisor.py +0 -46
  22. ominfra/manage/deploy/executor/concerns/systemd.py +0 -88
  23. ominfra/manage/deploy/executor/concerns/user.py +0 -25
  24. ominfra/manage/deploy/executor/concerns/venv.py +0 -22
  25. ominfra/manage/deploy/executor/main.py +0 -119
  26. ominfra/manage/deploy/poly/__init__.py +0 -1
  27. ominfra/manage/deploy/poly/_main.py +0 -975
  28. ominfra/manage/deploy/poly/base.py +0 -178
  29. ominfra/manage/deploy/poly/configs.py +0 -38
  30. ominfra/manage/deploy/poly/deploy.py +0 -25
  31. ominfra/manage/deploy/poly/main.py +0 -18
  32. ominfra/manage/deploy/poly/nginx.py +0 -60
  33. ominfra/manage/deploy/poly/repo.py +0 -41
  34. ominfra/manage/deploy/poly/runtime.py +0 -39
  35. ominfra/manage/deploy/poly/site.py +0 -11
  36. ominfra/manage/deploy/poly/supervisor.py +0 -64
  37. ominfra/manage/deploy/poly/venv.py +0 -52
  38. ominfra/manage/deploy/remote.py +0 -91
  39. ominfra/manage/manage.py +0 -12
  40. ominfra/manage/new/__init__.py +0 -1
  41. ominfra/manage/new/commands/__init__.py +0 -0
  42. ominfra/manage/new/main.py +0 -234
  43. /ominfra/manage/{deploy → commands}/__init__.py +0 -0
  44. {ominfra-0.0.0.dev138.dist-info → ominfra-0.0.0.dev140.dist-info}/LICENSE +0 -0
  45. {ominfra-0.0.0.dev138.dist-info → ominfra-0.0.0.dev140.dist-info}/WHEEL +0 -0
  46. {ominfra-0.0.0.dev138.dist-info → ominfra-0.0.0.dev140.dist-info}/entry_points.txt +0 -0
  47. {ominfra-0.0.0.dev138.dist-info → ominfra-0.0.0.dev140.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,11 +0,0 @@
1
- from .base import Runtime
2
- from .base import Site
3
- from .base import SiteConcern
4
-
5
-
6
- class SiteImpl(Site):
7
- concern_cls = SiteConcern
8
-
9
- def run(self, runtime: Runtime) -> None:
10
- for c in self._concerns:
11
- c.run(runtime)
@@ -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
- )
@@ -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
@@ -1,12 +0,0 @@
1
- """
2
- Jobs:
3
- - globals
4
- - pkgs
5
- - pyenv
6
- - tailscale
7
- - docker
8
- - system nginx
9
- - system service manager - systemd / supervisor
10
- - users
11
- - firewall
12
- """
@@ -1 +0,0 @@
1
- # @omlish-lite
File without changes