ominfra 0.0.0.dev142__py3-none-any.whl → 0.0.0.dev144__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/__init__.py +10 -0
- ominfra/manage/__main__.py +4 -0
- ominfra/manage/bootstrap.py +11 -0
- ominfra/manage/bootstrap_.py +18 -0
- ominfra/manage/commands/base.py +133 -1
- ominfra/manage/commands/execution.py +23 -0
- ominfra/manage/commands/inject.py +122 -0
- ominfra/manage/commands/marshal.py +26 -0
- ominfra/manage/config.py +10 -0
- ominfra/manage/deploy/__init__.py +0 -0
- ominfra/manage/deploy/command.py +23 -0
- ominfra/manage/deploy/inject.py +19 -0
- ominfra/manage/inject.py +58 -0
- ominfra/manage/main.py +64 -90
- ominfra/manage/marshal.py +12 -0
- ominfra/manage/remote/__init__.py +0 -0
- ominfra/manage/{protocol.py → remote/channel.py} +9 -2
- ominfra/manage/remote/config.py +12 -0
- ominfra/manage/remote/execution.py +193 -0
- ominfra/manage/remote/inject.py +29 -0
- ominfra/manage/{payload.py → remote/payload.py} +7 -1
- ominfra/manage/{spawning.py → remote/spawning.py} +29 -29
- ominfra/pyremote.py +40 -3
- ominfra/scripts/journald2aws.py +98 -50
- ominfra/scripts/manage.py +2025 -295
- ominfra/scripts/supervisor.py +99 -50
- ominfra/supervisor/inject.py +2 -1
- {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/RECORD +33 -17
- {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev142.dist-info → ominfra-0.0.0.dev144.dist-info}/top_level.txt +0 -0
ominfra/manage/__init__.py
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
from omlish.lite.inject import Injector
|
2
|
+
from omlish.lite.inject import inj
|
3
|
+
from omlish.lite.logs import configure_standard_logging
|
4
|
+
|
5
|
+
from .bootstrap import MainBootstrap
|
6
|
+
from .inject import bind_main
|
7
|
+
|
8
|
+
|
9
|
+
def main_bootstrap(bs: MainBootstrap) -> Injector:
|
10
|
+
if (log_level := bs.main_config.log_level) is not None:
|
11
|
+
configure_standard_logging(log_level)
|
12
|
+
|
13
|
+
injector = inj.create_injector(bind_main( # noqa
|
14
|
+
main_config=bs.main_config,
|
15
|
+
remote_config=bs.remote_config,
|
16
|
+
))
|
17
|
+
|
18
|
+
return injector
|
ominfra/manage/commands/base.py
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
2
|
import abc
|
3
3
|
import dataclasses as dc
|
4
|
+
import logging
|
5
|
+
import traceback
|
4
6
|
import typing as ta
|
5
7
|
|
8
|
+
from omlish.lite.check import check_isinstance
|
9
|
+
from omlish.lite.strings import snake_case
|
10
|
+
|
6
11
|
|
7
12
|
CommandT = ta.TypeVar('CommandT', bound='Command')
|
8
13
|
CommandOutputT = ta.TypeVar('CommandOutputT', bound='Command.Output')
|
@@ -17,11 +22,138 @@ class Command(abc.ABC, ta.Generic[CommandOutputT]):
|
|
17
22
|
class Output(abc.ABC): # noqa
|
18
23
|
pass
|
19
24
|
|
25
|
+
@ta.final
|
26
|
+
def execute(self, executor: 'CommandExecutor') -> CommandOutputT:
|
27
|
+
return check_isinstance(executor.execute(self), self.Output) # type: ignore[return-value]
|
28
|
+
|
20
29
|
|
21
30
|
##
|
22
31
|
|
23
32
|
|
33
|
+
@dc.dataclass(frozen=True)
|
34
|
+
class CommandException:
|
35
|
+
name: str
|
36
|
+
repr: str
|
37
|
+
|
38
|
+
traceback: ta.Optional[str] = None
|
39
|
+
|
40
|
+
exc: ta.Optional[ta.Any] = None # Exception
|
41
|
+
|
42
|
+
cmd: ta.Optional[Command] = None
|
43
|
+
|
44
|
+
@classmethod
|
45
|
+
def of(
|
46
|
+
cls,
|
47
|
+
exc: Exception,
|
48
|
+
*,
|
49
|
+
omit_exc_object: bool = False,
|
50
|
+
|
51
|
+
cmd: ta.Optional[Command] = None,
|
52
|
+
) -> 'CommandException':
|
53
|
+
return CommandException(
|
54
|
+
name=type(exc).__qualname__,
|
55
|
+
repr=repr(exc),
|
56
|
+
|
57
|
+
traceback=(
|
58
|
+
''.join(traceback.format_tb(exc.__traceback__))
|
59
|
+
if getattr(exc, '__traceback__', None) is not None else None
|
60
|
+
),
|
61
|
+
|
62
|
+
exc=None if omit_exc_object else exc,
|
63
|
+
|
64
|
+
cmd=cmd,
|
65
|
+
)
|
66
|
+
|
67
|
+
|
68
|
+
class CommandOutputOrException(abc.ABC, ta.Generic[CommandOutputT]):
|
69
|
+
@property
|
70
|
+
@abc.abstractmethod
|
71
|
+
def output(self) -> ta.Optional[CommandOutputT]:
|
72
|
+
raise NotImplementedError
|
73
|
+
|
74
|
+
@property
|
75
|
+
@abc.abstractmethod
|
76
|
+
def exception(self) -> ta.Optional[CommandException]:
|
77
|
+
raise NotImplementedError
|
78
|
+
|
79
|
+
|
80
|
+
@dc.dataclass(frozen=True)
|
81
|
+
class CommandOutputOrExceptionData(CommandOutputOrException):
|
82
|
+
output: ta.Optional[Command.Output] = None
|
83
|
+
exception: ta.Optional[CommandException] = None
|
84
|
+
|
85
|
+
|
24
86
|
class CommandExecutor(abc.ABC, ta.Generic[CommandT, CommandOutputT]):
|
25
87
|
@abc.abstractmethod
|
26
|
-
def execute(self,
|
88
|
+
def execute(self, cmd: CommandT) -> CommandOutputT:
|
27
89
|
raise NotImplementedError
|
90
|
+
|
91
|
+
def try_execute(
|
92
|
+
self,
|
93
|
+
cmd: CommandT,
|
94
|
+
*,
|
95
|
+
log: ta.Optional[logging.Logger] = None,
|
96
|
+
omit_exc_object: bool = False,
|
97
|
+
) -> CommandOutputOrException[CommandOutputT]:
|
98
|
+
try:
|
99
|
+
o = self.execute(cmd)
|
100
|
+
|
101
|
+
except Exception as e: # noqa
|
102
|
+
if log is not None:
|
103
|
+
log.exception('Exception executing command: %r', type(cmd))
|
104
|
+
|
105
|
+
return CommandOutputOrExceptionData(exception=CommandException.of(
|
106
|
+
e,
|
107
|
+
omit_exc_object=omit_exc_object,
|
108
|
+
cmd=cmd,
|
109
|
+
))
|
110
|
+
|
111
|
+
else:
|
112
|
+
return CommandOutputOrExceptionData(output=o)
|
113
|
+
|
114
|
+
|
115
|
+
##
|
116
|
+
|
117
|
+
|
118
|
+
@dc.dataclass(frozen=True)
|
119
|
+
class CommandRegistration:
|
120
|
+
command_cls: ta.Type[Command]
|
121
|
+
|
122
|
+
name: ta.Optional[str] = None
|
123
|
+
|
124
|
+
@property
|
125
|
+
def name_or_default(self) -> str:
|
126
|
+
if not (cls_name := self.command_cls.__name__).endswith('Command'):
|
127
|
+
raise NameError(cls_name)
|
128
|
+
return snake_case(cls_name[:-len('Command')])
|
129
|
+
|
130
|
+
|
131
|
+
CommandRegistrations = ta.NewType('CommandRegistrations', ta.Sequence[CommandRegistration])
|
132
|
+
|
133
|
+
|
134
|
+
##
|
135
|
+
|
136
|
+
|
137
|
+
@dc.dataclass(frozen=True)
|
138
|
+
class CommandExecutorRegistration:
|
139
|
+
command_cls: ta.Type[Command]
|
140
|
+
executor_cls: ta.Type[CommandExecutor]
|
141
|
+
|
142
|
+
|
143
|
+
CommandExecutorRegistrations = ta.NewType('CommandExecutorRegistrations', ta.Sequence[CommandExecutorRegistration])
|
144
|
+
|
145
|
+
|
146
|
+
##
|
147
|
+
|
148
|
+
|
149
|
+
CommandNameMap = ta.NewType('CommandNameMap', ta.Mapping[str, ta.Type[Command]])
|
150
|
+
|
151
|
+
|
152
|
+
def build_command_name_map(crs: CommandRegistrations) -> CommandNameMap:
|
153
|
+
dct: ta.Dict[str, ta.Type[Command]] = {}
|
154
|
+
cr: CommandRegistration
|
155
|
+
for cr in crs:
|
156
|
+
if (name := cr.name_or_default) in dct:
|
157
|
+
raise NameError(name)
|
158
|
+
dct[name] = cr.command_cls
|
159
|
+
return CommandNameMap(dct)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from .base import Command
|
5
|
+
from .base import CommandExecutor
|
6
|
+
|
7
|
+
|
8
|
+
CommandExecutorMap = ta.NewType('CommandExecutorMap', ta.Mapping[ta.Type[Command], CommandExecutor])
|
9
|
+
|
10
|
+
|
11
|
+
class CommandExecutionService(CommandExecutor):
|
12
|
+
def __init__(
|
13
|
+
self,
|
14
|
+
*,
|
15
|
+
command_executors: CommandExecutorMap,
|
16
|
+
) -> None:
|
17
|
+
super().__init__()
|
18
|
+
|
19
|
+
self._command_executors = command_executors
|
20
|
+
|
21
|
+
def execute(self, cmd: Command) -> Command.Output:
|
22
|
+
ce: CommandExecutor = self._command_executors[type(cmd)]
|
23
|
+
return ce.execute(cmd)
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import dataclasses as dc
|
3
|
+
import functools
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
from omlish.lite.inject import Injector
|
7
|
+
from omlish.lite.inject import InjectorBindingOrBindings
|
8
|
+
from omlish.lite.inject import InjectorBindings
|
9
|
+
from omlish.lite.inject import inj
|
10
|
+
|
11
|
+
from ..config import MainConfig
|
12
|
+
from ..marshal import ObjMarshalerInstaller
|
13
|
+
from .base import Command
|
14
|
+
from .base import CommandExecutor
|
15
|
+
from .base import CommandExecutorRegistration
|
16
|
+
from .base import CommandExecutorRegistrations
|
17
|
+
from .base import CommandNameMap
|
18
|
+
from .base import CommandRegistration
|
19
|
+
from .base import CommandRegistrations
|
20
|
+
from .base import build_command_name_map
|
21
|
+
from .execution import CommandExecutionService
|
22
|
+
from .execution import CommandExecutorMap
|
23
|
+
from .marshal import install_command_marshaling
|
24
|
+
from .subprocess import SubprocessCommand
|
25
|
+
from .subprocess import SubprocessCommandExecutor
|
26
|
+
|
27
|
+
|
28
|
+
##
|
29
|
+
|
30
|
+
|
31
|
+
def bind_command(
|
32
|
+
command_cls: ta.Type[Command],
|
33
|
+
executor_cls: ta.Optional[ta.Type[CommandExecutor]],
|
34
|
+
) -> InjectorBindings:
|
35
|
+
lst: ta.List[InjectorBindingOrBindings] = [
|
36
|
+
inj.bind(CommandRegistration(command_cls), array=True),
|
37
|
+
]
|
38
|
+
|
39
|
+
if executor_cls is not None:
|
40
|
+
lst.extend([
|
41
|
+
inj.bind(executor_cls, singleton=True),
|
42
|
+
inj.bind(CommandExecutorRegistration(command_cls, executor_cls), array=True),
|
43
|
+
])
|
44
|
+
|
45
|
+
return inj.as_bindings(*lst)
|
46
|
+
|
47
|
+
|
48
|
+
##
|
49
|
+
|
50
|
+
|
51
|
+
@dc.dataclass(frozen=True)
|
52
|
+
class _FactoryCommandExecutor(CommandExecutor):
|
53
|
+
factory: ta.Callable[[], CommandExecutor]
|
54
|
+
|
55
|
+
def execute(self, i: Command) -> Command.Output:
|
56
|
+
return self.factory().execute(i)
|
57
|
+
|
58
|
+
|
59
|
+
##
|
60
|
+
|
61
|
+
|
62
|
+
def bind_commands(
|
63
|
+
*,
|
64
|
+
main_config: MainConfig,
|
65
|
+
) -> InjectorBindings:
|
66
|
+
lst: ta.List[InjectorBindingOrBindings] = [
|
67
|
+
inj.bind_array(CommandRegistration),
|
68
|
+
inj.bind_array_type(CommandRegistration, CommandRegistrations),
|
69
|
+
|
70
|
+
inj.bind_array(CommandExecutorRegistration),
|
71
|
+
inj.bind_array_type(CommandExecutorRegistration, CommandExecutorRegistrations),
|
72
|
+
|
73
|
+
inj.bind(build_command_name_map, singleton=True),
|
74
|
+
]
|
75
|
+
|
76
|
+
#
|
77
|
+
|
78
|
+
def provide_obj_marshaler_installer(cmds: CommandNameMap) -> ObjMarshalerInstaller:
|
79
|
+
return ObjMarshalerInstaller(functools.partial(install_command_marshaling, cmds))
|
80
|
+
|
81
|
+
lst.append(inj.bind(provide_obj_marshaler_installer, array=True))
|
82
|
+
|
83
|
+
#
|
84
|
+
|
85
|
+
def provide_command_executor_map(
|
86
|
+
injector: Injector,
|
87
|
+
crs: CommandExecutorRegistrations,
|
88
|
+
) -> CommandExecutorMap:
|
89
|
+
dct: ta.Dict[ta.Type[Command], CommandExecutor] = {}
|
90
|
+
|
91
|
+
cr: CommandExecutorRegistration
|
92
|
+
for cr in crs:
|
93
|
+
if cr.command_cls in dct:
|
94
|
+
raise KeyError(cr.command_cls)
|
95
|
+
|
96
|
+
factory = functools.partial(injector.provide, cr.executor_cls)
|
97
|
+
if main_config.debug:
|
98
|
+
ce = factory()
|
99
|
+
else:
|
100
|
+
ce = _FactoryCommandExecutor(factory)
|
101
|
+
|
102
|
+
dct[cr.command_cls] = ce
|
103
|
+
|
104
|
+
return CommandExecutorMap(dct)
|
105
|
+
|
106
|
+
lst.extend([
|
107
|
+
inj.bind(provide_command_executor_map, singleton=True),
|
108
|
+
|
109
|
+
inj.bind(CommandExecutionService, singleton=True, eager=main_config.debug),
|
110
|
+
inj.bind(CommandExecutor, to_key=CommandExecutionService),
|
111
|
+
])
|
112
|
+
|
113
|
+
#
|
114
|
+
|
115
|
+
for command_cls, executor_cls in [
|
116
|
+
(SubprocessCommand, SubprocessCommandExecutor),
|
117
|
+
]:
|
118
|
+
lst.append(bind_command(command_cls, executor_cls))
|
119
|
+
|
120
|
+
#
|
121
|
+
|
122
|
+
return inj.as_bindings(*lst)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from omlish.lite.marshal import ObjMarshalerManager
|
2
|
+
from omlish.lite.marshal import PolymorphicObjMarshaler
|
3
|
+
|
4
|
+
from .base import Command
|
5
|
+
from .base import CommandNameMap
|
6
|
+
|
7
|
+
|
8
|
+
def install_command_marshaling(
|
9
|
+
cmds: CommandNameMap,
|
10
|
+
msh: ObjMarshalerManager,
|
11
|
+
) -> None:
|
12
|
+
for fn in [
|
13
|
+
lambda c: c,
|
14
|
+
lambda c: c.Output,
|
15
|
+
]:
|
16
|
+
msh.register_opj_marshaler(
|
17
|
+
fn(Command),
|
18
|
+
PolymorphicObjMarshaler.of([
|
19
|
+
PolymorphicObjMarshaler.Impl(
|
20
|
+
fn(cmd),
|
21
|
+
name,
|
22
|
+
msh.get_obj_marshaler(fn(cmd)),
|
23
|
+
)
|
24
|
+
for name, cmd in cmds.items()
|
25
|
+
]),
|
26
|
+
)
|
ominfra/manage/config.py
ADDED
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import dataclasses as dc
|
3
|
+
|
4
|
+
from ..commands.base import Command
|
5
|
+
from ..commands.base import CommandExecutor
|
6
|
+
|
7
|
+
|
8
|
+
##
|
9
|
+
|
10
|
+
|
11
|
+
@dc.dataclass(frozen=True)
|
12
|
+
class DeployCommand(Command['DeployCommand.Output']):
|
13
|
+
@dc.dataclass(frozen=True)
|
14
|
+
class Output(Command.Output):
|
15
|
+
pass
|
16
|
+
|
17
|
+
|
18
|
+
##
|
19
|
+
|
20
|
+
|
21
|
+
class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
|
22
|
+
def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
|
23
|
+
return DeployCommand.Output()
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from omlish.lite.inject import InjectorBindingOrBindings
|
5
|
+
from omlish.lite.inject import InjectorBindings
|
6
|
+
from omlish.lite.inject import inj
|
7
|
+
|
8
|
+
from ..commands.inject import bind_command
|
9
|
+
from .command import DeployCommand
|
10
|
+
from .command import DeployCommandExecutor
|
11
|
+
|
12
|
+
|
13
|
+
def bind_deploy(
|
14
|
+
) -> InjectorBindings:
|
15
|
+
lst: ta.List[InjectorBindingOrBindings] = [
|
16
|
+
bind_command(DeployCommand, DeployCommandExecutor),
|
17
|
+
]
|
18
|
+
|
19
|
+
return inj.as_bindings(*lst)
|
ominfra/manage/inject.py
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from omlish.lite.inject import InjectorBindingOrBindings
|
5
|
+
from omlish.lite.inject import InjectorBindings
|
6
|
+
from omlish.lite.inject import inj
|
7
|
+
from omlish.lite.marshal import ObjMarshalerManager
|
8
|
+
|
9
|
+
from .commands.inject import bind_commands
|
10
|
+
from .config import MainConfig
|
11
|
+
from .deploy.inject import bind_deploy
|
12
|
+
from .marshal import ObjMarshalerInstaller
|
13
|
+
from .marshal import ObjMarshalerInstallers
|
14
|
+
from .remote.config import RemoteConfig
|
15
|
+
from .remote.inject import bind_remote
|
16
|
+
|
17
|
+
|
18
|
+
##
|
19
|
+
|
20
|
+
|
21
|
+
def bind_main(
|
22
|
+
*,
|
23
|
+
main_config: MainConfig,
|
24
|
+
remote_config: RemoteConfig,
|
25
|
+
) -> InjectorBindings:
|
26
|
+
lst: ta.List[InjectorBindingOrBindings] = [
|
27
|
+
inj.bind(main_config),
|
28
|
+
|
29
|
+
bind_commands(
|
30
|
+
main_config=main_config,
|
31
|
+
),
|
32
|
+
|
33
|
+
bind_remote(
|
34
|
+
remote_config=remote_config,
|
35
|
+
),
|
36
|
+
|
37
|
+
bind_deploy(),
|
38
|
+
]
|
39
|
+
|
40
|
+
#
|
41
|
+
|
42
|
+
def build_obj_marshaler_manager(insts: ObjMarshalerInstallers) -> ObjMarshalerManager:
|
43
|
+
msh = ObjMarshalerManager()
|
44
|
+
inst: ObjMarshalerInstaller
|
45
|
+
for inst in insts:
|
46
|
+
inst.fn(msh)
|
47
|
+
return msh
|
48
|
+
|
49
|
+
lst.extend([
|
50
|
+
inj.bind(build_obj_marshaler_manager, singleton=True),
|
51
|
+
|
52
|
+
inj.bind_array(ObjMarshalerInstaller),
|
53
|
+
inj.bind_array_type(ObjMarshalerInstaller, ObjMarshalerInstallers),
|
54
|
+
])
|
55
|
+
|
56
|
+
#
|
57
|
+
|
58
|
+
return inj.as_bindings(*lst)
|
ominfra/manage/main.py
CHANGED
@@ -5,72 +5,24 @@
|
|
5
5
|
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 contextlib
|
9
|
+
import typing as ta
|
10
|
+
|
11
|
+
from omlish.lite.logs import log # noqa
|
9
12
|
from omlish.lite.marshal import ObjMarshalerManager
|
10
|
-
from omlish.lite.marshal import
|
13
|
+
from omlish.lite.marshal import ObjMarshalOptions
|
14
|
+
from omlish.lite.pycharm import PycharmRemoteDebug
|
11
15
|
|
12
|
-
from
|
13
|
-
from
|
14
|
-
from ..pyremote import pyremote_bootstrap_finalize
|
15
|
-
from ..pyremote import pyremote_build_bootstrap_cmd
|
16
|
+
from .bootstrap import MainBootstrap
|
17
|
+
from .bootstrap_ import main_bootstrap
|
16
18
|
from .commands.base import Command
|
19
|
+
from .commands.base import CommandExecutor
|
17
20
|
from .commands.subprocess import SubprocessCommand
|
18
|
-
from .
|
19
|
-
from .
|
20
|
-
from .
|
21
|
-
from .
|
22
|
-
|
23
|
-
|
24
|
-
##
|
25
|
-
|
26
|
-
|
27
|
-
_COMMAND_TYPES = {
|
28
|
-
'subprocess': SubprocessCommand,
|
29
|
-
}
|
30
|
-
|
31
|
-
|
32
|
-
##
|
33
|
-
|
34
|
-
|
35
|
-
def register_command_marshaling(msh: ObjMarshalerManager) -> None:
|
36
|
-
for fn in [
|
37
|
-
lambda c: c,
|
38
|
-
lambda c: c.Output,
|
39
|
-
]:
|
40
|
-
msh.register_opj_marshaler(
|
41
|
-
fn(Command),
|
42
|
-
PolymorphicObjMarshaler.of([
|
43
|
-
PolymorphicObjMarshaler.Impl(
|
44
|
-
fn(cty),
|
45
|
-
k,
|
46
|
-
msh.get_obj_marshaler(fn(cty)),
|
47
|
-
)
|
48
|
-
for k, cty in _COMMAND_TYPES.items()
|
49
|
-
]),
|
50
|
-
)
|
51
|
-
|
52
|
-
|
53
|
-
register_command_marshaling(OBJ_MARSHALER_MANAGER)
|
54
|
-
|
55
|
-
|
56
|
-
##
|
57
|
-
|
58
|
-
|
59
|
-
def _remote_main() -> None:
|
60
|
-
rt = pyremote_bootstrap_finalize() # noqa
|
61
|
-
chan = Channel(rt.input, rt.output)
|
62
|
-
|
63
|
-
while True:
|
64
|
-
i = chan.recv_obj(Command)
|
65
|
-
if i is None:
|
66
|
-
break
|
67
|
-
|
68
|
-
if isinstance(i, SubprocessCommand):
|
69
|
-
o = SubprocessCommandExecutor().execute(i) # noqa
|
70
|
-
else:
|
71
|
-
raise TypeError(i)
|
72
|
-
|
73
|
-
chan.send_obj(o, Command.Output)
|
21
|
+
from .config import MainConfig
|
22
|
+
from .deploy.command import DeployCommand
|
23
|
+
from .remote.config import RemoteConfig
|
24
|
+
from .remote.execution import RemoteExecution
|
25
|
+
from .remote.spawning import RemoteSpawning
|
74
26
|
|
75
27
|
|
76
28
|
##
|
@@ -87,50 +39,72 @@ def _main() -> None:
|
|
87
39
|
parser.add_argument('-q', '--shell-quote', action='store_true')
|
88
40
|
parser.add_argument('--python', default='python3')
|
89
41
|
|
42
|
+
parser.add_argument('--pycharm-debug-port', type=int)
|
43
|
+
parser.add_argument('--pycharm-debug-host')
|
44
|
+
parser.add_argument('--pycharm-debug-version')
|
45
|
+
|
90
46
|
parser.add_argument('--debug', action='store_true')
|
91
47
|
|
48
|
+
parser.add_argument('--local', action='store_true')
|
49
|
+
|
50
|
+
parser.add_argument('command', nargs='+')
|
51
|
+
|
92
52
|
args = parser.parse_args()
|
93
53
|
|
94
54
|
#
|
95
55
|
|
96
|
-
|
56
|
+
bs = MainBootstrap(
|
57
|
+
main_config=MainConfig(
|
58
|
+
log_level='DEBUG' if args.debug else 'INFO',
|
97
59
|
|
98
|
-
|
99
|
-
|
100
|
-
payload_src,
|
101
|
-
'_remote_main()',
|
102
|
-
])
|
60
|
+
debug=bool(args.debug),
|
61
|
+
),
|
103
62
|
|
104
|
-
|
63
|
+
remote_config=RemoteConfig(
|
64
|
+
payload_file=args._payload_file, # noqa
|
105
65
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
66
|
+
pycharm_remote_debug=PycharmRemoteDebug(
|
67
|
+
port=args.pycharm_debug_port,
|
68
|
+
host=args.pycharm_debug_host,
|
69
|
+
install_version=args.pycharm_debug_version,
|
70
|
+
) if args.pycharm_debug_port is not None else None,
|
71
|
+
),
|
111
72
|
)
|
112
73
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
PyremoteBootstrapOptions(
|
117
|
-
debug=args.debug,
|
118
|
-
),
|
119
|
-
).run(proc.stdout, proc.stdin)
|
74
|
+
injector = main_bootstrap(
|
75
|
+
bs,
|
76
|
+
)
|
120
77
|
|
121
|
-
|
78
|
+
#
|
79
|
+
|
80
|
+
cmds: ta.List[Command] = []
|
81
|
+
for c in args.command:
|
82
|
+
if c == 'deploy':
|
83
|
+
cmds.append(DeployCommand())
|
84
|
+
else:
|
85
|
+
cmds.append(SubprocessCommand([c]))
|
86
|
+
|
87
|
+
#
|
88
|
+
|
89
|
+
with contextlib.ExitStack() as es:
|
90
|
+
ce: CommandExecutor
|
122
91
|
|
123
|
-
|
92
|
+
if args.local:
|
93
|
+
ce = injector[CommandExecutor]
|
94
|
+
|
95
|
+
else:
|
96
|
+
tgt = RemoteSpawning.Target(
|
97
|
+
shell=args.shell,
|
98
|
+
shell_quote=args.shell_quote,
|
99
|
+
python=args.python,
|
100
|
+
)
|
124
101
|
|
125
|
-
|
126
|
-
SubprocessCommand(['python3', '-'], input=b'print(1)\n'),
|
127
|
-
SubprocessCommand(['uname']),
|
128
|
-
]:
|
129
|
-
chan.send_obj(ci, Command)
|
102
|
+
ce = es.enter_context(injector[RemoteExecution].connect(tgt, bs)) # noqa
|
130
103
|
|
131
|
-
|
104
|
+
for cmd in cmds:
|
105
|
+
r = ce.try_execute(cmd)
|
132
106
|
|
133
|
-
print(
|
107
|
+
print(injector[ObjMarshalerManager].marshal_obj(r, opts=ObjMarshalOptions(raw_bytes=True)))
|
134
108
|
|
135
109
|
|
136
110
|
if __name__ == '__main__':
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from omlish.lite.marshal import ObjMarshalerManager
|
5
|
+
|
6
|
+
|
7
|
+
@dc.dataclass(frozen=True)
|
8
|
+
class ObjMarshalerInstaller:
|
9
|
+
fn: ta.Callable[[ObjMarshalerManager], None]
|
10
|
+
|
11
|
+
|
12
|
+
ObjMarshalerInstallers = ta.NewType('ObjMarshalerInstallers', ta.Sequence[ObjMarshalerInstaller])
|
File without changes
|