ominfra 0.0.0.dev153__py3-none-any.whl → 0.0.0.dev155__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 (41) hide show
  1. ominfra/manage/bootstrap.py +4 -0
  2. ominfra/manage/bootstrap_.py +5 -0
  3. ominfra/manage/commands/inject.py +8 -11
  4. ominfra/manage/commands/{execution.py → local.py} +1 -5
  5. ominfra/manage/commands/ping.py +23 -0
  6. ominfra/manage/commands/types.py +8 -0
  7. ominfra/manage/deploy/apps.py +72 -0
  8. ominfra/manage/deploy/config.py +8 -0
  9. ominfra/manage/deploy/git.py +136 -0
  10. ominfra/manage/deploy/inject.py +21 -0
  11. ominfra/manage/deploy/paths.py +81 -28
  12. ominfra/manage/deploy/types.py +13 -0
  13. ominfra/manage/deploy/venvs.py +66 -0
  14. ominfra/manage/inject.py +20 -4
  15. ominfra/manage/main.py +15 -27
  16. ominfra/manage/remote/_main.py +1 -1
  17. ominfra/manage/remote/config.py +0 -2
  18. ominfra/manage/remote/connection.py +7 -24
  19. ominfra/manage/remote/execution.py +1 -1
  20. ominfra/manage/remote/inject.py +3 -14
  21. ominfra/manage/system/commands.py +22 -2
  22. ominfra/manage/system/config.py +3 -1
  23. ominfra/manage/system/inject.py +16 -6
  24. ominfra/manage/system/packages.py +33 -7
  25. ominfra/manage/system/platforms.py +72 -0
  26. ominfra/manage/targets/__init__.py +0 -0
  27. ominfra/manage/targets/connection.py +150 -0
  28. ominfra/manage/targets/inject.py +42 -0
  29. ominfra/manage/targets/targets.py +87 -0
  30. ominfra/scripts/journald2aws.py +24 -7
  31. ominfra/scripts/manage.py +1880 -438
  32. ominfra/scripts/supervisor.py +187 -25
  33. ominfra/supervisor/configs.py +163 -18
  34. {ominfra-0.0.0.dev153.dist-info → ominfra-0.0.0.dev155.dist-info}/METADATA +3 -3
  35. {ominfra-0.0.0.dev153.dist-info → ominfra-0.0.0.dev155.dist-info}/RECORD +40 -29
  36. ominfra/manage/system/types.py +0 -5
  37. /ominfra/manage/{commands → deploy}/interp.py +0 -0
  38. {ominfra-0.0.0.dev153.dist-info → ominfra-0.0.0.dev155.dist-info}/LICENSE +0 -0
  39. {ominfra-0.0.0.dev153.dist-info → ominfra-0.0.0.dev155.dist-info}/WHEEL +0 -0
  40. {ominfra-0.0.0.dev153.dist-info → ominfra-0.0.0.dev155.dist-info}/entry_points.txt +0 -0
  41. {ominfra-0.0.0.dev153.dist-info → ominfra-0.0.0.dev155.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,150 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import abc
3
+ import contextlib
4
+ import dataclasses as dc
5
+ import typing as ta
6
+
7
+ from omlish.lite.check import check
8
+
9
+ from ..bootstrap import MainBootstrap
10
+ from ..commands.base import CommandExecutor
11
+ from ..commands.local import LocalCommandExecutor
12
+ from ..remote.connection import InProcessRemoteExecutionConnector
13
+ from ..remote.connection import PyremoteRemoteExecutionConnector
14
+ from ..remote.spawning import RemoteSpawning
15
+ from .targets import DockerManageTarget
16
+ from .targets import InProcessManageTarget
17
+ from .targets import LocalManageTarget
18
+ from .targets import ManageTarget
19
+ from .targets import SshManageTarget
20
+ from .targets import SubprocessManageTarget
21
+
22
+
23
+ ##
24
+
25
+
26
+ class ManageTargetConnector(abc.ABC):
27
+ @abc.abstractmethod
28
+ def connect(self, tgt: ManageTarget) -> ta.AsyncContextManager[CommandExecutor]:
29
+ raise NotImplementedError
30
+
31
+
32
+ ##
33
+
34
+
35
+ ManageTargetConnectorMap = ta.NewType('ManageTargetConnectorMap', ta.Mapping[ta.Type[ManageTarget], ManageTargetConnector]) # noqa
36
+
37
+
38
+ @dc.dataclass(frozen=True)
39
+ class TypeSwitchedManageTargetConnector(ManageTargetConnector):
40
+ connectors: ManageTargetConnectorMap
41
+
42
+ def get_connector(self, ty: ta.Type[ManageTarget]) -> ManageTargetConnector:
43
+ for k, v in self.connectors.items():
44
+ if issubclass(ty, k):
45
+ return v
46
+ raise KeyError(ty)
47
+
48
+ def connect(self, tgt: ManageTarget) -> ta.AsyncContextManager[CommandExecutor]:
49
+ return self.get_connector(type(tgt)).connect(tgt)
50
+
51
+
52
+ ##
53
+
54
+
55
+ @dc.dataclass(frozen=True)
56
+ class LocalManageTargetConnector(ManageTargetConnector):
57
+ _local_executor: LocalCommandExecutor
58
+ _in_process_connector: InProcessRemoteExecutionConnector
59
+ _pyremote_connector: PyremoteRemoteExecutionConnector
60
+ _bootstrap: MainBootstrap
61
+
62
+ @contextlib.asynccontextmanager
63
+ async def connect(self, tgt: ManageTarget) -> ta.AsyncGenerator[CommandExecutor, None]:
64
+ lmt = check.isinstance(tgt, LocalManageTarget)
65
+
66
+ if isinstance(lmt, InProcessManageTarget):
67
+ imt = check.isinstance(lmt, InProcessManageTarget)
68
+
69
+ if imt.mode == InProcessManageTarget.Mode.DIRECT:
70
+ yield self._local_executor
71
+
72
+ elif imt.mode == InProcessManageTarget.Mode.FAKE_REMOTE:
73
+ async with self._in_process_connector.connect() as rce:
74
+ yield rce
75
+
76
+ else:
77
+ raise TypeError(imt.mode)
78
+
79
+ elif isinstance(lmt, SubprocessManageTarget):
80
+ async with self._pyremote_connector.connect(
81
+ RemoteSpawning.Target(
82
+ python=lmt.python,
83
+ ),
84
+ self._bootstrap,
85
+ ) as rce:
86
+ yield rce
87
+
88
+ else:
89
+ raise TypeError(lmt)
90
+
91
+
92
+ ##
93
+
94
+
95
+ @dc.dataclass(frozen=True)
96
+ class DockerManageTargetConnector(ManageTargetConnector):
97
+ _pyremote_connector: PyremoteRemoteExecutionConnector
98
+ _bootstrap: MainBootstrap
99
+
100
+ @contextlib.asynccontextmanager
101
+ async def connect(self, tgt: ManageTarget) -> ta.AsyncGenerator[CommandExecutor, None]:
102
+ dmt = check.isinstance(tgt, DockerManageTarget)
103
+
104
+ sh_parts: ta.List[str] = ['docker']
105
+ if dmt.image is not None:
106
+ sh_parts.extend(['run', '-i', dmt.image])
107
+ elif dmt.container_id is not None:
108
+ sh_parts.extend(['exec', dmt.container_id])
109
+ else:
110
+ raise ValueError(dmt)
111
+
112
+ async with self._pyremote_connector.connect(
113
+ RemoteSpawning.Target(
114
+ shell=' '.join(sh_parts),
115
+ python=dmt.python,
116
+ ),
117
+ self._bootstrap,
118
+ ) as rce:
119
+ yield rce
120
+
121
+
122
+ ##
123
+
124
+
125
+ @dc.dataclass(frozen=True)
126
+ class SshManageTargetConnector(ManageTargetConnector):
127
+ _pyremote_connector: PyremoteRemoteExecutionConnector
128
+ _bootstrap: MainBootstrap
129
+
130
+ @contextlib.asynccontextmanager
131
+ async def connect(self, tgt: ManageTarget) -> ta.AsyncGenerator[CommandExecutor, None]:
132
+ smt = check.isinstance(tgt, SshManageTarget)
133
+
134
+ sh_parts: ta.List[str] = ['ssh']
135
+ if smt.key_file is not None:
136
+ sh_parts.extend(['-i', smt.key_file])
137
+ addr = check.not_none(smt.host)
138
+ if smt.username is not None:
139
+ addr = f'{smt.username}@{addr}'
140
+ sh_parts.append(addr)
141
+
142
+ async with self._pyremote_connector.connect(
143
+ RemoteSpawning.Target(
144
+ shell=' '.join(sh_parts),
145
+ shell_quote=True,
146
+ python=smt.python,
147
+ ),
148
+ self._bootstrap,
149
+ ) as rce:
150
+ yield rce
@@ -0,0 +1,42 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.inject import Injector
5
+ from omlish.lite.inject import InjectorBindingOrBindings
6
+ from omlish.lite.inject import InjectorBindings
7
+ from omlish.lite.inject import inj
8
+
9
+ from .connection import DockerManageTargetConnector
10
+ from .connection import LocalManageTargetConnector
11
+ from .connection import ManageTargetConnector
12
+ from .connection import ManageTargetConnectorMap
13
+ from .connection import SshManageTargetConnector
14
+ from .connection import TypeSwitchedManageTargetConnector
15
+ from .targets import DockerManageTarget
16
+ from .targets import LocalManageTarget
17
+ from .targets import SshManageTarget
18
+
19
+
20
+ def bind_targets() -> InjectorBindings:
21
+ lst: ta.List[InjectorBindingOrBindings] = [
22
+ inj.bind(LocalManageTargetConnector, singleton=True),
23
+ inj.bind(DockerManageTargetConnector, singleton=True),
24
+ inj.bind(SshManageTargetConnector, singleton=True),
25
+
26
+ inj.bind(TypeSwitchedManageTargetConnector, singleton=True),
27
+ inj.bind(ManageTargetConnector, to_key=TypeSwitchedManageTargetConnector),
28
+ ]
29
+
30
+ #
31
+
32
+ def provide_manage_target_connector_map(injector: Injector) -> ManageTargetConnectorMap:
33
+ return ManageTargetConnectorMap({
34
+ LocalManageTarget: injector[LocalManageTargetConnector],
35
+ DockerManageTarget: injector[DockerManageTargetConnector],
36
+ SshManageTarget: injector[SshManageTargetConnector],
37
+ })
38
+ lst.append(inj.bind(provide_manage_target_connector_map, singleton=True))
39
+
40
+ #
41
+
42
+ return inj.as_bindings(*lst)
@@ -0,0 +1,87 @@
1
+ # ruff: noqa: UP006 UP007
2
+ """
3
+ It's desugaring. Subprocess and locals are only leafs. Retain an origin?
4
+ ** TWO LAYERS ** - ManageTarget is user-facing, ConnectorTarget is bound, internal
5
+ """
6
+ import abc
7
+ import dataclasses as dc
8
+ import enum
9
+ import typing as ta
10
+
11
+ from omlish.lite.check import check
12
+
13
+
14
+ ##
15
+
16
+
17
+ class ManageTarget(abc.ABC): # noqa
18
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
19
+ super().__init_subclass__(**kwargs)
20
+
21
+ check.state(cls.__name__.endswith('ManageTarget'))
22
+
23
+
24
+ #
25
+
26
+
27
+ @dc.dataclass(frozen=True)
28
+ class PythonRemoteManageTarget:
29
+ DEFAULT_PYTHON: ta.ClassVar[str] = 'python3'
30
+ python: str = DEFAULT_PYTHON
31
+
32
+
33
+ #
34
+
35
+
36
+ class RemoteManageTarget(ManageTarget, abc.ABC):
37
+ pass
38
+
39
+
40
+ class PhysicallyRemoteManageTarget(RemoteManageTarget, abc.ABC):
41
+ pass
42
+
43
+
44
+ class LocalManageTarget(ManageTarget, abc.ABC):
45
+ pass
46
+
47
+
48
+ ##
49
+
50
+
51
+ @dc.dataclass(frozen=True)
52
+ class SshManageTarget(PhysicallyRemoteManageTarget, PythonRemoteManageTarget):
53
+ host: ta.Optional[str] = None
54
+ username: ta.Optional[str] = None
55
+ key_file: ta.Optional[str] = None
56
+
57
+ def __post_init__(self) -> None:
58
+ check.non_empty_str(self.host)
59
+
60
+
61
+ ##
62
+
63
+
64
+ @dc.dataclass(frozen=True)
65
+ class DockerManageTarget(RemoteManageTarget, PythonRemoteManageTarget): # noqa
66
+ image: ta.Optional[str] = None
67
+ container_id: ta.Optional[str] = None
68
+
69
+ def __post_init__(self) -> None:
70
+ check.arg(bool(self.image) ^ bool(self.container_id))
71
+
72
+
73
+ ##
74
+
75
+
76
+ @dc.dataclass(frozen=True)
77
+ class InProcessManageTarget(LocalManageTarget):
78
+ class Mode(enum.Enum):
79
+ DIRECT = enum.auto()
80
+ FAKE_REMOTE = enum.auto()
81
+
82
+ mode: Mode = Mode.DIRECT
83
+
84
+
85
+ @dc.dataclass(frozen=True)
86
+ class SubprocessManageTarget(LocalManageTarget, PythonRemoteManageTarget):
87
+ pass
@@ -961,8 +961,6 @@ def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
961
961
  """
962
962
  TODO:
963
963
  - def maybe(v: lang.Maybe[T])
964
- - patch / override lite.check ?
965
- - checker interface?
966
964
  """
967
965
 
968
966
 
@@ -2270,6 +2268,20 @@ def attr_setting(obj, attr, val, *, default=None): # noqa
2270
2268
  setattr(obj, attr, orig)
2271
2269
 
2272
2270
 
2271
+ ##
2272
+
2273
+
2274
+ class aclosing(contextlib.AbstractAsyncContextManager): # noqa
2275
+ def __init__(self, thing):
2276
+ self.thing = thing
2277
+
2278
+ async def __aenter__(self):
2279
+ return self.thing
2280
+
2281
+ async def __aexit__(self, *exc_info):
2282
+ await self.thing.aclose()
2283
+
2284
+
2273
2285
  ########################################
2274
2286
  # ../../../../../omlish/lite/logs.py
2275
2287
  """
@@ -2545,7 +2557,8 @@ def configure_standard_logging(
2545
2557
  """
2546
2558
  TODO:
2547
2559
  - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
2548
- - nonstrict toggle
2560
+ - namedtuple
2561
+ - literals
2549
2562
  """
2550
2563
 
2551
2564
 
@@ -2835,14 +2848,18 @@ class ObjMarshalerManager:
2835
2848
  ) -> ObjMarshaler:
2836
2849
  if isinstance(ty, type):
2837
2850
  if abc.ABC in ty.__bases__:
2838
- return PolymorphicObjMarshaler.of([ # type: ignore
2851
+ impls = [ity for ity in deep_subclasses(ty) if abc.ABC not in ity.__bases__] # type: ignore
2852
+ if all(ity.__qualname__.endswith(ty.__name__) for ity in impls):
2853
+ ins = {ity: snake_case(ity.__qualname__[:-len(ty.__name__)]) for ity in impls}
2854
+ else:
2855
+ ins = {ity: ity.__qualname__ for ity in impls}
2856
+ return PolymorphicObjMarshaler.of([
2839
2857
  PolymorphicObjMarshaler.Impl(
2840
2858
  ity,
2841
- ity.__qualname__,
2859
+ itn,
2842
2860
  rec(ity),
2843
2861
  )
2844
- for ity in deep_subclasses(ty)
2845
- if abc.ABC not in ity.__bases__
2862
+ for ity, itn in ins.items()
2846
2863
  ])
2847
2864
 
2848
2865
  if issubclass(ty, enum.Enum):