ominfra 0.0.0.dev154__py3-none-any.whl → 0.0.0.dev155__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- ominfra/manage/bootstrap.py +4 -0
- ominfra/manage/bootstrap_.py +5 -0
- ominfra/manage/commands/inject.py +8 -11
- ominfra/manage/commands/{execution.py → local.py} +1 -5
- ominfra/manage/commands/ping.py +23 -0
- ominfra/manage/commands/types.py +8 -0
- ominfra/manage/deploy/apps.py +72 -0
- ominfra/manage/deploy/config.py +8 -0
- ominfra/manage/deploy/git.py +136 -0
- ominfra/manage/deploy/inject.py +21 -0
- ominfra/manage/deploy/paths.py +81 -28
- ominfra/manage/deploy/types.py +13 -0
- ominfra/manage/deploy/venvs.py +66 -0
- ominfra/manage/inject.py +20 -4
- ominfra/manage/main.py +15 -27
- ominfra/manage/remote/_main.py +1 -1
- ominfra/manage/remote/config.py +0 -2
- ominfra/manage/remote/connection.py +7 -24
- ominfra/manage/remote/execution.py +1 -1
- ominfra/manage/remote/inject.py +3 -14
- ominfra/manage/system/commands.py +22 -2
- ominfra/manage/system/config.py +3 -1
- ominfra/manage/system/inject.py +16 -6
- ominfra/manage/system/packages.py +33 -7
- ominfra/manage/system/platforms.py +72 -0
- ominfra/manage/targets/__init__.py +0 -0
- ominfra/manage/targets/connection.py +150 -0
- ominfra/manage/targets/inject.py +42 -0
- ominfra/manage/targets/targets.py +87 -0
- ominfra/scripts/journald2aws.py +24 -7
- ominfra/scripts/manage.py +1880 -438
- ominfra/scripts/supervisor.py +187 -25
- ominfra/supervisor/configs.py +163 -18
- {ominfra-0.0.0.dev154.dist-info → ominfra-0.0.0.dev155.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev154.dist-info → ominfra-0.0.0.dev155.dist-info}/RECORD +40 -29
- ominfra/manage/system/types.py +0 -5
- /ominfra/manage/{commands → deploy}/interp.py +0 -0
- {ominfra-0.0.0.dev154.dist-info → ominfra-0.0.0.dev155.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev154.dist-info → ominfra-0.0.0.dev155.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev154.dist-info → ominfra-0.0.0.dev155.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev154.dist-info → ominfra-0.0.0.dev155.dist-info}/top_level.txt +0 -0
ominfra/manage/inject.py
CHANGED
@@ -6,8 +6,10 @@ from omlish.lite.inject import InjectorBindings
|
|
6
6
|
from omlish.lite.inject import inj
|
7
7
|
from omlish.lite.marshal import ObjMarshalerManager
|
8
8
|
|
9
|
+
from .bootstrap import MainBootstrap
|
9
10
|
from .commands.inject import bind_commands
|
10
11
|
from .config import MainConfig
|
12
|
+
from .deploy.config import DeployConfig
|
11
13
|
from .deploy.inject import bind_deploy
|
12
14
|
from .marshal import ObjMarshalerInstaller
|
13
15
|
from .marshal import ObjMarshalerInstallers
|
@@ -15,6 +17,7 @@ from .remote.config import RemoteConfig
|
|
15
17
|
from .remote.inject import bind_remote
|
16
18
|
from .system.config import SystemConfig
|
17
19
|
from .system.inject import bind_system
|
20
|
+
from .targets.inject import bind_targets
|
18
21
|
|
19
22
|
|
20
23
|
##
|
@@ -22,9 +25,13 @@ from .system.inject import bind_system
|
|
22
25
|
|
23
26
|
def bind_main(
|
24
27
|
*,
|
25
|
-
main_config: MainConfig,
|
26
|
-
|
27
|
-
|
28
|
+
main_config: MainConfig = MainConfig(),
|
29
|
+
|
30
|
+
deploy_config: DeployConfig = DeployConfig(),
|
31
|
+
remote_config: RemoteConfig = RemoteConfig(),
|
32
|
+
system_config: SystemConfig = SystemConfig(),
|
33
|
+
|
34
|
+
main_bootstrap: ta.Optional[MainBootstrap] = None,
|
28
35
|
) -> InjectorBindings:
|
29
36
|
lst: ta.List[InjectorBindingOrBindings] = [
|
30
37
|
inj.bind(main_config),
|
@@ -33,7 +40,9 @@ def bind_main(
|
|
33
40
|
main_config=main_config,
|
34
41
|
),
|
35
42
|
|
36
|
-
bind_deploy(
|
43
|
+
bind_deploy(
|
44
|
+
deploy_config=deploy_config,
|
45
|
+
),
|
37
46
|
|
38
47
|
bind_remote(
|
39
48
|
remote_config=remote_config,
|
@@ -42,10 +51,17 @@ def bind_main(
|
|
42
51
|
bind_system(
|
43
52
|
system_config=system_config,
|
44
53
|
),
|
54
|
+
|
55
|
+
bind_targets(),
|
45
56
|
]
|
46
57
|
|
47
58
|
#
|
48
59
|
|
60
|
+
if main_bootstrap is not None:
|
61
|
+
lst.append(inj.bind(main_bootstrap))
|
62
|
+
|
63
|
+
#
|
64
|
+
|
49
65
|
def build_obj_marshaler_manager(insts: ObjMarshalerInstallers) -> ObjMarshalerManager:
|
50
66
|
msh = ObjMarshalerManager()
|
51
67
|
inst: ObjMarshalerInstaller
|
ominfra/manage/main.py
CHANGED
@@ -6,7 +6,6 @@ manage.py -s 'docker run -i python:3.12'
|
|
6
6
|
manage.py -s 'ssh -i /foo/bar.pem foo@bar.baz' -q --python=python3.8
|
7
7
|
"""
|
8
8
|
import asyncio
|
9
|
-
import contextlib
|
10
9
|
import json
|
11
10
|
import sys
|
12
11
|
import typing as ta
|
@@ -22,22 +21,17 @@ from omlish.lite.pycharm import PycharmRemoteDebug
|
|
22
21
|
from .bootstrap import MainBootstrap
|
23
22
|
from .bootstrap_ import main_bootstrap
|
24
23
|
from .commands.base import Command
|
25
|
-
from .commands.base import CommandExecutor
|
26
|
-
from .commands.execution import LocalCommandExecutor
|
27
24
|
from .config import MainConfig
|
25
|
+
from .deploy.config import DeployConfig
|
28
26
|
from .remote.config import RemoteConfig
|
29
|
-
from .
|
30
|
-
from .
|
27
|
+
from .targets.connection import ManageTargetConnector
|
28
|
+
from .targets.targets import ManageTarget
|
31
29
|
|
32
30
|
|
33
31
|
class MainCli(ArgparseCli):
|
34
32
|
@argparse_command(
|
35
33
|
argparse_arg('--_payload-file'),
|
36
34
|
|
37
|
-
argparse_arg('-s', '--shell'),
|
38
|
-
argparse_arg('-q', '--shell-quote', action='store_true'),
|
39
|
-
argparse_arg('--python', default='python3'),
|
40
|
-
|
41
35
|
argparse_arg('--pycharm-debug-port', type=int),
|
42
36
|
argparse_arg('--pycharm-debug-host'),
|
43
37
|
argparse_arg('--pycharm-debug-version'),
|
@@ -46,8 +40,9 @@ class MainCli(ArgparseCli):
|
|
46
40
|
|
47
41
|
argparse_arg('--debug', action='store_true'),
|
48
42
|
|
49
|
-
argparse_arg('--
|
43
|
+
argparse_arg('--deploy-home'),
|
50
44
|
|
45
|
+
argparse_arg('target'),
|
51
46
|
argparse_arg('command', nargs='+'),
|
52
47
|
)
|
53
48
|
async def run(self) -> None:
|
@@ -58,6 +53,10 @@ class MainCli(ArgparseCli):
|
|
58
53
|
debug=bool(self.args.debug),
|
59
54
|
),
|
60
55
|
|
56
|
+
deploy_config=DeployConfig(
|
57
|
+
deploy_home=self.args.deploy_home,
|
58
|
+
),
|
59
|
+
|
61
60
|
remote_config=RemoteConfig(
|
62
61
|
payload_file=self.args._payload_file, # noqa
|
63
62
|
|
@@ -68,8 +67,6 @@ class MainCli(ArgparseCli):
|
|
68
67
|
) if self.args.pycharm_debug_port is not None else None,
|
69
68
|
|
70
69
|
timebomb_delay_s=self.args.remote_timebomb_delay_s,
|
71
|
-
|
72
|
-
use_in_process_remote_executor=True,
|
73
70
|
),
|
74
71
|
)
|
75
72
|
|
@@ -83,6 +80,11 @@ class MainCli(ArgparseCli):
|
|
83
80
|
|
84
81
|
msh = injector[ObjMarshalerManager]
|
85
82
|
|
83
|
+
ts = self.args.target
|
84
|
+
if not ts.startswith('{'):
|
85
|
+
ts = json.dumps({ts: {}})
|
86
|
+
tgt: ManageTarget = msh.unmarshal_obj(json.loads(ts), ManageTarget)
|
87
|
+
|
86
88
|
cmds: ta.List[Command] = []
|
87
89
|
cmd: Command
|
88
90
|
for c in self.args.command:
|
@@ -93,21 +95,7 @@ class MainCli(ArgparseCli):
|
|
93
95
|
|
94
96
|
#
|
95
97
|
|
96
|
-
async with
|
97
|
-
ce: CommandExecutor
|
98
|
-
|
99
|
-
if self.args.local:
|
100
|
-
ce = injector[LocalCommandExecutor]
|
101
|
-
|
102
|
-
else:
|
103
|
-
tgt = RemoteSpawning.Target(
|
104
|
-
shell=self.args.shell,
|
105
|
-
shell_quote=self.args.shell_quote,
|
106
|
-
python=self.args.python,
|
107
|
-
)
|
108
|
-
|
109
|
-
ce = await es.enter_async_context(injector[RemoteExecutionConnector].connect(tgt, bs)) # noqa
|
110
|
-
|
98
|
+
async with injector[ManageTargetConnector].connect(tgt) as ce:
|
111
99
|
async def run_command(cmd: Command) -> None:
|
112
100
|
res = await ce.try_execute(
|
113
101
|
cmd,
|
ominfra/manage/remote/_main.py
CHANGED
@@ -20,7 +20,7 @@ from omlish.os.deathsig import set_process_deathsig
|
|
20
20
|
|
21
21
|
from ...pyremote import pyremote_bootstrap_finalize
|
22
22
|
from ..bootstrap import MainBootstrap
|
23
|
-
from ..commands.
|
23
|
+
from ..commands.local import LocalCommandExecutor
|
24
24
|
from .channel import RemoteChannel
|
25
25
|
from .channel import RemoteChannelImpl
|
26
26
|
from .execution import _RemoteCommandHandler
|
ominfra/manage/remote/config.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
|
-
import abc
|
3
2
|
import asyncio
|
4
3
|
import contextlib
|
5
4
|
import typing as ta
|
6
5
|
|
7
6
|
from omlish.asyncs.asyncio.channels import asyncio_create_bytes_channel
|
8
7
|
from omlish.lite.cached import cached_nullary
|
8
|
+
from omlish.lite.contextmanagers import aclosing
|
9
9
|
from omlish.lite.marshal import ObjMarshalerManager
|
10
10
|
|
11
11
|
from ...pyremote import PyremoteBootstrapDriver
|
12
12
|
from ...pyremote import PyremoteBootstrapOptions
|
13
13
|
from ...pyremote import pyremote_build_bootstrap_cmd
|
14
14
|
from ..bootstrap import MainBootstrap
|
15
|
-
from ..commands.
|
15
|
+
from ..commands.local import LocalCommandExecutor
|
16
16
|
from ._main import _remote_execution_main # noqa
|
17
17
|
from .channel import RemoteChannelImpl
|
18
18
|
from .execution import RemoteCommandExecutor
|
@@ -25,20 +25,7 @@ from .spawning import RemoteSpawning
|
|
25
25
|
##
|
26
26
|
|
27
27
|
|
28
|
-
class
|
29
|
-
@abc.abstractmethod
|
30
|
-
def connect(
|
31
|
-
self,
|
32
|
-
tgt: RemoteSpawning.Target,
|
33
|
-
bs: MainBootstrap,
|
34
|
-
) -> ta.AsyncContextManager[RemoteCommandExecutor]:
|
35
|
-
raise NotImplementedError
|
36
|
-
|
37
|
-
|
38
|
-
##
|
39
|
-
|
40
|
-
|
41
|
-
class PyremoteRemoteExecutionConnector(RemoteExecutionConnector):
|
28
|
+
class PyremoteRemoteExecutionConnector:
|
42
29
|
def __init__(
|
43
30
|
self,
|
44
31
|
*,
|
@@ -104,7 +91,7 @@ class PyremoteRemoteExecutionConnector(RemoteExecutionConnector):
|
|
104
91
|
await chan.send_obj(bs)
|
105
92
|
|
106
93
|
rce: RemoteCommandExecutor
|
107
|
-
async with
|
94
|
+
async with aclosing(RemoteCommandExecutor(chan)) as rce:
|
108
95
|
await rce.start()
|
109
96
|
|
110
97
|
yield rce
|
@@ -113,7 +100,7 @@ class PyremoteRemoteExecutionConnector(RemoteExecutionConnector):
|
|
113
100
|
##
|
114
101
|
|
115
102
|
|
116
|
-
class InProcessRemoteExecutionConnector
|
103
|
+
class InProcessRemoteExecutionConnector:
|
117
104
|
def __init__(
|
118
105
|
self,
|
119
106
|
*,
|
@@ -126,11 +113,7 @@ class InProcessRemoteExecutionConnector(RemoteExecutionConnector):
|
|
126
113
|
self._local_executor = local_executor
|
127
114
|
|
128
115
|
@contextlib.asynccontextmanager
|
129
|
-
async def connect(
|
130
|
-
self,
|
131
|
-
tgt: RemoteSpawning.Target,
|
132
|
-
bs: MainBootstrap,
|
133
|
-
) -> ta.AsyncGenerator[RemoteCommandExecutor, None]:
|
116
|
+
async def connect(self) -> ta.AsyncGenerator[RemoteCommandExecutor, None]:
|
134
117
|
r0, w0 = asyncio_create_bytes_channel()
|
135
118
|
r1, w1 = asyncio_create_bytes_channel()
|
136
119
|
|
@@ -144,7 +127,7 @@ class InProcessRemoteExecutionConnector(RemoteExecutionConnector):
|
|
144
127
|
rch_task = asyncio.create_task(rch.run()) # noqa
|
145
128
|
try:
|
146
129
|
rce: RemoteCommandExecutor
|
147
|
-
async with
|
130
|
+
async with aclosing(RemoteCommandExecutor(local_chan)) as rce:
|
148
131
|
await rce.start()
|
149
132
|
|
150
133
|
yield rce
|
@@ -394,7 +394,7 @@ class RemoteCommandExecutor(CommandExecutor):
|
|
394
394
|
self,
|
395
395
|
cmd: Command,
|
396
396
|
*,
|
397
|
-
log: ta.Optional[logging.Logger] = None,
|
397
|
+
log: ta.Optional[logging.Logger] = None, # noqa
|
398
398
|
omit_exc_object: bool = False,
|
399
399
|
) -> CommandOutputOrException:
|
400
400
|
try:
|
ominfra/manage/remote/inject.py
CHANGED
@@ -8,7 +8,6 @@ from omlish.lite.inject import inj
|
|
8
8
|
from .config import RemoteConfig
|
9
9
|
from .connection import InProcessRemoteExecutionConnector
|
10
10
|
from .connection import PyremoteRemoteExecutionConnector
|
11
|
-
from .connection import RemoteExecutionConnector
|
12
11
|
from .payload import RemoteExecutionPayloadFile
|
13
12
|
from .spawning import RemoteSpawning
|
14
13
|
from .spawning import SubprocessRemoteSpawning
|
@@ -23,20 +22,10 @@ def bind_remote(
|
|
23
22
|
|
24
23
|
inj.bind(SubprocessRemoteSpawning, singleton=True),
|
25
24
|
inj.bind(RemoteSpawning, to_key=SubprocessRemoteSpawning),
|
26
|
-
]
|
27
|
-
|
28
|
-
#
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
inj.bind(RemoteExecutionConnector, to_key=InProcessRemoteExecutionConnector),
|
34
|
-
])
|
35
|
-
else:
|
36
|
-
lst.extend([
|
37
|
-
inj.bind(PyremoteRemoteExecutionConnector, singleton=True),
|
38
|
-
inj.bind(RemoteExecutionConnector, to_key=PyremoteRemoteExecutionConnector),
|
39
|
-
])
|
26
|
+
inj.bind(PyremoteRemoteExecutionConnector, singleton=True),
|
27
|
+
inj.bind(InProcessRemoteExecutionConnector, singleton=True),
|
28
|
+
]
|
40
29
|
|
41
30
|
#
|
42
31
|
|
@@ -1,10 +1,14 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
2
|
import dataclasses as dc
|
3
|
+
import typing as ta
|
3
4
|
|
5
|
+
from omlish.lite.check import check
|
4
6
|
from omlish.lite.logs import log
|
5
7
|
|
6
8
|
from ..commands.base import Command
|
7
9
|
from ..commands.base import CommandExecutor
|
10
|
+
from .packages import SystemPackage
|
11
|
+
from .packages import SystemPackageManager
|
8
12
|
|
9
13
|
|
10
14
|
##
|
@@ -12,13 +16,29 @@ from ..commands.base import CommandExecutor
|
|
12
16
|
|
13
17
|
@dc.dataclass(frozen=True)
|
14
18
|
class CheckSystemPackageCommand(Command['CheckSystemPackageCommand.Output']):
|
19
|
+
pkgs: ta.Sequence[str] = ()
|
20
|
+
|
21
|
+
def __post_init__(self) -> None:
|
22
|
+
check.not_isinstance(self.pkgs, str)
|
23
|
+
|
15
24
|
@dc.dataclass(frozen=True)
|
16
25
|
class Output(Command.Output):
|
17
|
-
|
26
|
+
pkgs: ta.Sequence[SystemPackage]
|
18
27
|
|
19
28
|
|
20
29
|
class CheckSystemPackageCommandExecutor(CommandExecutor[CheckSystemPackageCommand, CheckSystemPackageCommand.Output]):
|
30
|
+
def __init__(
|
31
|
+
self,
|
32
|
+
*,
|
33
|
+
mgr: SystemPackageManager,
|
34
|
+
) -> None:
|
35
|
+
super().__init__()
|
36
|
+
|
37
|
+
self._mgr = mgr
|
38
|
+
|
21
39
|
async def execute(self, cmd: CheckSystemPackageCommand) -> CheckSystemPackageCommand.Output:
|
22
40
|
log.info('Checking system package!')
|
23
41
|
|
24
|
-
|
42
|
+
ret = await self._mgr.query(*cmd.pkgs)
|
43
|
+
|
44
|
+
return CheckSystemPackageCommand.Output(list(ret.values()))
|
ominfra/manage/system/config.py
CHANGED
ominfra/manage/system/inject.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
|
-
import sys
|
3
2
|
import typing as ta
|
4
3
|
|
5
4
|
from omlish.lite.inject import InjectorBindingOrBindings
|
@@ -13,7 +12,12 @@ from .config import SystemConfig
|
|
13
12
|
from .packages import AptSystemPackageManager
|
14
13
|
from .packages import BrewSystemPackageManager
|
15
14
|
from .packages import SystemPackageManager
|
16
|
-
from .
|
15
|
+
from .packages import YumSystemPackageManager
|
16
|
+
from .platforms import AmazonLinuxPlatform
|
17
|
+
from .platforms import DarwinPlatform
|
18
|
+
from .platforms import LinuxPlatform
|
19
|
+
from .platforms import Platform
|
20
|
+
from .platforms import detect_system_platform
|
17
21
|
|
18
22
|
|
19
23
|
def bind_system(
|
@@ -26,18 +30,24 @@ def bind_system(
|
|
26
30
|
|
27
31
|
#
|
28
32
|
|
29
|
-
platform = system_config.platform or
|
30
|
-
lst.append(inj.bind(platform, key=
|
33
|
+
platform = system_config.platform or detect_system_platform()
|
34
|
+
lst.append(inj.bind(platform, key=Platform))
|
31
35
|
|
32
36
|
#
|
33
37
|
|
34
|
-
if platform
|
38
|
+
if isinstance(platform, AmazonLinuxPlatform):
|
39
|
+
lst.extend([
|
40
|
+
inj.bind(YumSystemPackageManager, singleton=True),
|
41
|
+
inj.bind(SystemPackageManager, to_key=YumSystemPackageManager),
|
42
|
+
])
|
43
|
+
|
44
|
+
elif isinstance(platform, LinuxPlatform):
|
35
45
|
lst.extend([
|
36
46
|
inj.bind(AptSystemPackageManager, singleton=True),
|
37
47
|
inj.bind(SystemPackageManager, to_key=AptSystemPackageManager),
|
38
48
|
])
|
39
49
|
|
40
|
-
elif platform
|
50
|
+
elif isinstance(platform, DarwinPlatform):
|
41
51
|
lst.extend([
|
42
52
|
inj.bind(BrewSystemPackageManager, singleton=True),
|
43
53
|
inj.bind(SystemPackageManager, to_key=BrewSystemPackageManager),
|
@@ -79,28 +79,54 @@ class AptSystemPackageManager(SystemPackageManager):
|
|
79
79
|
}
|
80
80
|
|
81
81
|
async def update(self) -> None:
|
82
|
-
await asyncio_subprocess_check_call('apt', 'update', env={**os.environ, **self._APT_ENV})
|
82
|
+
await asyncio_subprocess_check_call('sudo', 'apt', 'update', env={**os.environ, **self._APT_ENV})
|
83
83
|
|
84
84
|
async def upgrade(self) -> None:
|
85
|
-
await asyncio_subprocess_check_call('apt', 'upgrade', '-y', env={**os.environ, **self._APT_ENV})
|
85
|
+
await asyncio_subprocess_check_call('sudo', 'apt', 'upgrade', '-y', env={**os.environ, **self._APT_ENV})
|
86
86
|
|
87
87
|
async def install(self, *packages: SystemPackageOrStr) -> None:
|
88
88
|
pns = [p.name if isinstance(p, SystemPackage) else p for p in packages] # FIXME: versions
|
89
|
-
await asyncio_subprocess_check_call('apt', 'install', '-y', *pns, env={**os.environ, **self._APT_ENV})
|
89
|
+
await asyncio_subprocess_check_call('sudo', 'apt', 'install', '-y', *pns, env={**os.environ, **self._APT_ENV})
|
90
90
|
|
91
91
|
async def query(self, *packages: SystemPackageOrStr) -> ta.Mapping[str, SystemPackage]:
|
92
92
|
pns = [p.name if isinstance(p, SystemPackage) else p for p in packages]
|
93
|
-
|
94
|
-
|
95
|
-
*cmd,
|
93
|
+
out = await asyncio_subprocess_run(
|
94
|
+
'dpkg-query', '-W', '-f=${Package}=${Version}\n', *pns,
|
96
95
|
capture_output=True,
|
97
96
|
check=False,
|
98
97
|
)
|
99
98
|
d: ta.Dict[str, SystemPackage] = {}
|
100
|
-
for l in check.not_none(stdout).decode('utf-8').strip().splitlines():
|
99
|
+
for l in check.not_none(out.stdout).decode('utf-8').strip().splitlines():
|
101
100
|
n, v = l.split('=', 1)
|
102
101
|
d[n] = SystemPackage(
|
103
102
|
name=n,
|
104
103
|
version=v,
|
105
104
|
)
|
106
105
|
return d
|
106
|
+
|
107
|
+
|
108
|
+
class YumSystemPackageManager(SystemPackageManager):
|
109
|
+
async def update(self) -> None:
|
110
|
+
await asyncio_subprocess_check_call('sudo', 'yum', 'check-update')
|
111
|
+
|
112
|
+
async def upgrade(self) -> None:
|
113
|
+
await asyncio_subprocess_check_call('sudo', 'yum', 'update')
|
114
|
+
|
115
|
+
async def install(self, *packages: SystemPackageOrStr) -> None:
|
116
|
+
pns = [p.name if isinstance(p, SystemPackage) else p for p in packages] # FIXME: versions
|
117
|
+
await asyncio_subprocess_check_call('sudo', 'yum', 'install', *pns)
|
118
|
+
|
119
|
+
async def query(self, *packages: SystemPackageOrStr) -> ta.Mapping[str, SystemPackage]:
|
120
|
+
pns = [p.name if isinstance(p, SystemPackage) else p for p in packages]
|
121
|
+
d: ta.Dict[str, SystemPackage] = {}
|
122
|
+
for pn in pns:
|
123
|
+
out = await asyncio_subprocess_run(
|
124
|
+
'rpm', '-q', pn,
|
125
|
+
capture_output=True,
|
126
|
+
)
|
127
|
+
if not out.proc.returncode:
|
128
|
+
d[pn] = SystemPackage(
|
129
|
+
pn,
|
130
|
+
check.not_none(out.stdout).decode().strip(),
|
131
|
+
)
|
132
|
+
return d
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import abc
|
2
|
+
import dataclasses as dc
|
3
|
+
import sys
|
4
|
+
|
5
|
+
from omlish.lite.cached import cached_nullary
|
6
|
+
from omlish.lite.logs import log
|
7
|
+
from omlish.os.linux import LinuxOsRelease
|
8
|
+
|
9
|
+
|
10
|
+
##
|
11
|
+
|
12
|
+
|
13
|
+
@dc.dataclass(frozen=True)
|
14
|
+
class Platform(abc.ABC): # noqa
|
15
|
+
pass
|
16
|
+
|
17
|
+
|
18
|
+
class LinuxPlatform(Platform, abc.ABC):
|
19
|
+
pass
|
20
|
+
|
21
|
+
|
22
|
+
class UbuntuPlatform(LinuxPlatform):
|
23
|
+
pass
|
24
|
+
|
25
|
+
|
26
|
+
class AmazonLinuxPlatform(LinuxPlatform):
|
27
|
+
pass
|
28
|
+
|
29
|
+
|
30
|
+
class GenericLinuxPlatform(LinuxPlatform):
|
31
|
+
pass
|
32
|
+
|
33
|
+
|
34
|
+
class DarwinPlatform(Platform):
|
35
|
+
pass
|
36
|
+
|
37
|
+
|
38
|
+
class UnknownPlatform(Platform):
|
39
|
+
pass
|
40
|
+
|
41
|
+
|
42
|
+
##
|
43
|
+
|
44
|
+
|
45
|
+
def _detect_system_platform() -> Platform:
|
46
|
+
plat = sys.platform
|
47
|
+
|
48
|
+
if plat == 'linux':
|
49
|
+
if (osr := LinuxOsRelease.read()) is None:
|
50
|
+
return GenericLinuxPlatform()
|
51
|
+
|
52
|
+
if osr.id == 'amzn':
|
53
|
+
return AmazonLinuxPlatform()
|
54
|
+
|
55
|
+
elif osr.id == 'ubuntu':
|
56
|
+
return UbuntuPlatform()
|
57
|
+
|
58
|
+
else:
|
59
|
+
return GenericLinuxPlatform()
|
60
|
+
|
61
|
+
elif plat == 'darwin':
|
62
|
+
return DarwinPlatform()
|
63
|
+
|
64
|
+
else:
|
65
|
+
return UnknownPlatform()
|
66
|
+
|
67
|
+
|
68
|
+
@cached_nullary
|
69
|
+
def detect_system_platform() -> Platform:
|
70
|
+
platform = _detect_system_platform()
|
71
|
+
log.info('Detected platform: %r', platform)
|
72
|
+
return platform
|
File without changes
|