aws-annoying 0.4.0__py3-none-any.whl → 0.5.0__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.
- aws_annoying/cli/session_manager/_common.py +30 -0
- aws_annoying/cli/session_manager/install.py +2 -2
- aws_annoying/cli/session_manager/port_forward.py +26 -33
- aws_annoying/cli/session_manager/start.py +40 -2
- aws_annoying/session_manager/__init__.py +8 -1
- aws_annoying/session_manager/session_manager.py +24 -35
- aws_annoying/session_manager/shortcuts.py +72 -0
- {aws_annoying-0.4.0.dist-info → aws_annoying-0.5.0.dist-info}/METADATA +1 -1
- {aws_annoying-0.4.0.dist-info → aws_annoying-0.5.0.dist-info}/RECORD +12 -11
- {aws_annoying-0.4.0.dist-info → aws_annoying-0.5.0.dist-info}/WHEEL +0 -0
- {aws_annoying-0.4.0.dist-info → aws_annoying-0.5.0.dist-info}/entry_points.txt +0 -0
- {aws_annoying-0.4.0.dist-info → aws_annoying-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# TODO(lasuillard): Using this file until split CLI from library codebase
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
+
import re
|
|
4
5
|
from typing import Any
|
|
5
6
|
|
|
7
|
+
import boto3
|
|
6
8
|
import typer
|
|
7
9
|
from rich.prompt import Confirm
|
|
8
10
|
|
|
@@ -22,3 +24,31 @@ class SessionManager(_SessionManager):
|
|
|
22
24
|
def install(self, *args: Any, confirm: bool = False, **kwargs: Any) -> None:
|
|
23
25
|
self._confirm = confirm
|
|
24
26
|
return super().install(*args, **kwargs)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_instance_id_by_name(name_or_id: str) -> str | None:
|
|
30
|
+
"""Get the EC2 instance ID by name or ID.
|
|
31
|
+
|
|
32
|
+
Be aware that this function will only return the first instance found
|
|
33
|
+
with the given name, no matter how many instances are found.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
name_or_id: The name or ID of the EC2 instance.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
The instance ID if found, otherwise `None`.
|
|
40
|
+
"""
|
|
41
|
+
if re.match(r"m?i-.+", name_or_id):
|
|
42
|
+
return name_or_id
|
|
43
|
+
|
|
44
|
+
ec2 = boto3.client("ec2")
|
|
45
|
+
response = ec2.describe_instances(Filters=[{"Name": "tag:Name", "Values": [name_or_id]}])
|
|
46
|
+
reservations = response["Reservations"]
|
|
47
|
+
if not reservations:
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
instances = reservations[0]["Instances"]
|
|
51
|
+
if not instances:
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
return str(instances[0]["InstanceId"])
|
|
@@ -18,7 +18,7 @@ def install(
|
|
|
18
18
|
),
|
|
19
19
|
) -> None:
|
|
20
20
|
"""Install AWS Session Manager plugin."""
|
|
21
|
-
session_manager = SessionManager(
|
|
21
|
+
session_manager = SessionManager()
|
|
22
22
|
|
|
23
23
|
# Check session-manager-plugin already installed
|
|
24
24
|
is_installed, binary_path, version = session_manager.verify_installation()
|
|
@@ -28,7 +28,7 @@ def install(
|
|
|
28
28
|
|
|
29
29
|
# Install session-manager-plugin
|
|
30
30
|
print("⬇️ Installing AWS Session Manager plugin. You could be prompted for admin privileges request.")
|
|
31
|
-
session_manager.install(confirm=yes)
|
|
31
|
+
session_manager.install(confirm=yes, downloader=TQDMDownloader())
|
|
32
32
|
|
|
33
33
|
# Verify installation
|
|
34
34
|
is_installed, binary_path, version = session_manager.verify_installation()
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
import re
|
|
5
4
|
import signal
|
|
5
|
+
import subprocess
|
|
6
6
|
from pathlib import Path # noqa: TC003
|
|
7
7
|
|
|
8
|
-
import boto3
|
|
9
8
|
import typer
|
|
10
9
|
from rich import print # noqa: A004
|
|
11
10
|
|
|
12
|
-
from aws_annoying.utils.downloader import TQDMDownloader
|
|
13
|
-
|
|
14
11
|
from ._app import session_manager_app
|
|
15
|
-
from ._common import SessionManager
|
|
12
|
+
from ._common import SessionManager, get_instance_id_by_name
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
# https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html
|
|
@@ -57,7 +54,7 @@ def port_forward( # noqa: PLR0913
|
|
|
57
54
|
),
|
|
58
55
|
) -> None:
|
|
59
56
|
"""Start a port forwarding session using AWS Session Manager."""
|
|
60
|
-
session_manager = SessionManager(
|
|
57
|
+
session_manager = SessionManager()
|
|
61
58
|
|
|
62
59
|
# Check if the PID file already exists
|
|
63
60
|
if pid_file.exists():
|
|
@@ -80,21 +77,16 @@ def port_forward( # noqa: PLR0913
|
|
|
80
77
|
print(f"⚠️ Tried to terminate process with PID {existing_pid} but does not exist.")
|
|
81
78
|
|
|
82
79
|
# Resolve the instance name or ID
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
# If the instance name is provided, get the instance ID
|
|
87
|
-
instance_id = _get_instance_id_by_name(through)
|
|
88
|
-
if instance_id:
|
|
89
|
-
print(f"❗ Instance ID resolved: [bold]{instance_id}[/bold]")
|
|
90
|
-
else:
|
|
91
|
-
print(f"🚫 Instance with name '{through}' not found.")
|
|
92
|
-
raise typer.Exit(1)
|
|
93
|
-
|
|
80
|
+
instance_id = get_instance_id_by_name(through)
|
|
81
|
+
if instance_id:
|
|
82
|
+
print(f"❗ Instance ID resolved: [bold]{instance_id}[/bold]")
|
|
94
83
|
target = instance_id
|
|
84
|
+
else:
|
|
85
|
+
print(f"🚫 Instance with name '{through}' not found.")
|
|
86
|
+
raise typer.Exit(1)
|
|
95
87
|
|
|
96
88
|
# Initiate the session
|
|
97
|
-
|
|
89
|
+
command = session_manager.build_command(
|
|
98
90
|
target=target,
|
|
99
91
|
document_name="AWS-StartPortForwardingSessionToRemoteHost",
|
|
100
92
|
parameters={
|
|
@@ -104,23 +96,24 @@ def port_forward( # noqa: PLR0913
|
|
|
104
96
|
},
|
|
105
97
|
reason=reason,
|
|
106
98
|
)
|
|
99
|
+
stdout: subprocess._FILE
|
|
100
|
+
if log_file is not None: # noqa: SIM108
|
|
101
|
+
stdout = log_file.open(mode="at+", buffering=1)
|
|
102
|
+
else:
|
|
103
|
+
stdout = subprocess.DEVNULL
|
|
104
|
+
|
|
105
|
+
print(
|
|
106
|
+
f"🚀 Starting port forwarding session through [bold]{through}[/bold] with reason: [italic]{reason!r}[/italic].",
|
|
107
|
+
)
|
|
108
|
+
proc = subprocess.Popen( # noqa: S603
|
|
109
|
+
command,
|
|
110
|
+
stdout=stdout,
|
|
111
|
+
stderr=subprocess.STDOUT,
|
|
112
|
+
text=True,
|
|
113
|
+
close_fds=False, # FD inherited from parent process
|
|
114
|
+
)
|
|
107
115
|
print(f"✅ Session Manager Plugin started with PID {proc.pid}. Outputs will be logged to {log_file.absolute()}.")
|
|
108
116
|
|
|
109
117
|
# Write the PID to the file
|
|
110
118
|
pid_file.write_text(str(proc.pid))
|
|
111
119
|
print(f"💾 PID file written to {pid_file.absolute()}.")
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def _get_instance_id_by_name(name: str) -> str | None:
|
|
115
|
-
"""Get the EC2 instance ID by name."""
|
|
116
|
-
ec2 = boto3.client("ec2")
|
|
117
|
-
response = ec2.describe_instances(Filters=[{"Name": "tag:Name", "Values": [name]}])
|
|
118
|
-
reservations = response["Reservations"]
|
|
119
|
-
if not reservations:
|
|
120
|
-
return None
|
|
121
|
-
|
|
122
|
-
instances = reservations[0]["Instances"]
|
|
123
|
-
if not instances:
|
|
124
|
-
return None
|
|
125
|
-
|
|
126
|
-
return str(instances[0]["InstanceId"])
|
|
@@ -1,9 +1,47 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from rich import print # noqa: A004
|
|
7
|
+
|
|
3
8
|
from ._app import session_manager_app
|
|
9
|
+
from ._common import SessionManager, get_instance_id_by_name
|
|
10
|
+
|
|
11
|
+
# TODO(lasuillard): ECS support (#24)
|
|
12
|
+
# TODO(lasuillard): Interactive instance selection
|
|
4
13
|
|
|
5
14
|
|
|
6
15
|
@session_manager_app.command()
|
|
7
|
-
def start(
|
|
16
|
+
def start(
|
|
17
|
+
target: str = typer.Option(
|
|
18
|
+
...,
|
|
19
|
+
show_default=False,
|
|
20
|
+
help="The name or ID of the EC2 instance to connect to.",
|
|
21
|
+
),
|
|
22
|
+
reason: str = typer.Option(
|
|
23
|
+
"",
|
|
24
|
+
help="The reason for starting the session.",
|
|
25
|
+
),
|
|
26
|
+
) -> None:
|
|
8
27
|
"""Start new session."""
|
|
9
|
-
|
|
28
|
+
session_manager = SessionManager()
|
|
29
|
+
|
|
30
|
+
# Resolve the instance name or ID
|
|
31
|
+
instance_id = get_instance_id_by_name(target)
|
|
32
|
+
if instance_id:
|
|
33
|
+
print(f"❗ Instance ID resolved: [bold]{instance_id}[/bold]")
|
|
34
|
+
target = instance_id
|
|
35
|
+
else:
|
|
36
|
+
print(f"🚫 Instance with name '{target}' not found.")
|
|
37
|
+
raise typer.Exit(1)
|
|
38
|
+
|
|
39
|
+
# Start the session, replacing the current process
|
|
40
|
+
print(f"🚀 Starting session to target [bold]{target}[/bold] with reason: [italic]{reason!r}[/italic].")
|
|
41
|
+
command = session_manager.build_command(
|
|
42
|
+
target=target,
|
|
43
|
+
document_name="SSM-SessionManagerRunShell",
|
|
44
|
+
parameters={},
|
|
45
|
+
reason=reason,
|
|
46
|
+
)
|
|
47
|
+
os.execvp(command[0], command) # noqa: S606
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
from .errors import PluginNotInstalledError, SessionManagerError, UnsupportedPlatformError
|
|
2
2
|
from .session_manager import SessionManager
|
|
3
|
+
from .shortcuts import port_forward
|
|
3
4
|
|
|
4
|
-
__all__ = (
|
|
5
|
+
__all__ = (
|
|
6
|
+
"PluginNotInstalledError",
|
|
7
|
+
"SessionManager",
|
|
8
|
+
"SessionManagerError",
|
|
9
|
+
"UnsupportedPlatformError",
|
|
10
|
+
"port_forward",
|
|
11
|
+
)
|
|
@@ -28,15 +28,13 @@ logger = logging.getLogger(__name__)
|
|
|
28
28
|
class SessionManager:
|
|
29
29
|
"""AWS Session Manager plugin manager."""
|
|
30
30
|
|
|
31
|
-
def __init__(self, *, session: boto3.session.Session | None = None
|
|
31
|
+
def __init__(self, *, session: boto3.session.Session | None = None) -> None:
|
|
32
32
|
"""Initialize SessionManager.
|
|
33
33
|
|
|
34
34
|
Args:
|
|
35
35
|
session: Boto3 session to use for AWS operations.
|
|
36
|
-
downloader: File downloader to use for downloading the plugin.
|
|
37
36
|
"""
|
|
38
37
|
self.session = session or boto3.session.Session()
|
|
39
|
-
self.downloader = downloader
|
|
40
38
|
|
|
41
39
|
# ------------------------------------------------------------------------
|
|
42
40
|
# Installation
|
|
@@ -90,6 +88,7 @@ class SessionManager:
|
|
|
90
88
|
linux_distribution: _LinuxDistribution | None = None,
|
|
91
89
|
arch: str | None = None,
|
|
92
90
|
root: bool | None = None,
|
|
91
|
+
downloader: AbstractDownloader,
|
|
93
92
|
) -> None:
|
|
94
93
|
"""Install AWS Session Manager plugin.
|
|
95
94
|
|
|
@@ -99,17 +98,23 @@ class SessionManager:
|
|
|
99
98
|
If `None` and current `os` is `"Linux"`, will try to detect the distribution from current system.
|
|
100
99
|
arch: The architecture to install the plugin on. If `None`, will use the current architecture.
|
|
101
100
|
root: Whether to run the installation as root. If `None`, will check if the current user is root.
|
|
101
|
+
downloader: File downloader to use for downloading the plugin.
|
|
102
102
|
"""
|
|
103
103
|
os = os or platform.system()
|
|
104
104
|
arch = arch or platform.machine()
|
|
105
105
|
|
|
106
106
|
if os == "Windows":
|
|
107
|
-
self._install_windows()
|
|
107
|
+
self._install_windows(downloader=downloader)
|
|
108
108
|
elif os == "Darwin":
|
|
109
|
-
self._install_macos(arch=arch, root=root or is_root())
|
|
109
|
+
self._install_macos(arch=arch, root=root or is_root(), downloader=downloader)
|
|
110
110
|
elif os == "Linux":
|
|
111
111
|
linux_distribution = linux_distribution or _detect_linux_distribution()
|
|
112
|
-
self._install_linux(
|
|
112
|
+
self._install_linux(
|
|
113
|
+
linux_distribution=linux_distribution,
|
|
114
|
+
arch=arch,
|
|
115
|
+
root=root or is_root(),
|
|
116
|
+
downloader=downloader,
|
|
117
|
+
)
|
|
113
118
|
else:
|
|
114
119
|
msg = f"Unsupported operating system: {os}"
|
|
115
120
|
raise UnsupportedPlatformError(msg)
|
|
@@ -118,20 +123,20 @@ class SessionManager:
|
|
|
118
123
|
"""Hook to run before invoking plugin installation command."""
|
|
119
124
|
|
|
120
125
|
# https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-windows.html
|
|
121
|
-
def _install_windows(self) -> None:
|
|
126
|
+
def _install_windows(self, *, downloader: AbstractDownloader) -> None:
|
|
122
127
|
"""Install session-manager-plugin on Windows via EXE installer."""
|
|
123
128
|
download_url = (
|
|
124
129
|
"https://s3.amazonaws.com/session-manager-downloads/plugin/latest/windows/SessionManagerPluginSetup.exe"
|
|
125
130
|
)
|
|
126
131
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
127
132
|
p = Path(temp_dir)
|
|
128
|
-
exe_installer =
|
|
133
|
+
exe_installer = downloader.download(download_url, to=p / "SessionManagerPluginSetup.exe")
|
|
129
134
|
command = [str(exe_installer), "/quiet"]
|
|
130
135
|
self.before_install(command)
|
|
131
136
|
subprocess.call(command, cwd=p) # noqa: S603
|
|
132
137
|
|
|
133
138
|
# https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html
|
|
134
|
-
def _install_macos(self, *, arch: str, root: bool) -> None:
|
|
139
|
+
def _install_macos(self, *, arch: str, root: bool, downloader: AbstractDownloader) -> None:
|
|
135
140
|
"""Install session-manager-plugin on macOS via signed installer."""
|
|
136
141
|
# ! Intel chip will not be supported
|
|
137
142
|
if arch == "x86_64":
|
|
@@ -148,7 +153,7 @@ class SessionManager:
|
|
|
148
153
|
|
|
149
154
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
150
155
|
p = Path(temp_dir)
|
|
151
|
-
pkg_installer =
|
|
156
|
+
pkg_installer = downloader.download(download_url, to=p / "session-manager-plugin.pkg")
|
|
152
157
|
|
|
153
158
|
# Run installer
|
|
154
159
|
command = command_as_root(
|
|
@@ -179,6 +184,7 @@ class SessionManager:
|
|
|
179
184
|
linux_distribution: _LinuxDistribution,
|
|
180
185
|
arch: str,
|
|
181
186
|
root: bool,
|
|
187
|
+
downloader: AbstractDownloader,
|
|
182
188
|
) -> None:
|
|
183
189
|
name = linux_distribution.name
|
|
184
190
|
version = linux_distribution.version
|
|
@@ -200,7 +206,7 @@ class SessionManager:
|
|
|
200
206
|
|
|
201
207
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
202
208
|
p = Path(temp_dir)
|
|
203
|
-
deb_installer =
|
|
209
|
+
deb_installer = downloader.download(download_url, to=p / "session-manager-plugin.deb")
|
|
204
210
|
|
|
205
211
|
# Invoke installation command
|
|
206
212
|
command = command_as_root(["dpkg", "--install", str(deb_installer)], root=root)
|
|
@@ -241,28 +247,25 @@ class SessionManager:
|
|
|
241
247
|
raise UnsupportedPlatformError(msg)
|
|
242
248
|
|
|
243
249
|
# ------------------------------------------------------------------------
|
|
244
|
-
#
|
|
250
|
+
# Command
|
|
245
251
|
# ------------------------------------------------------------------------
|
|
246
|
-
def
|
|
252
|
+
def build_command(
|
|
247
253
|
self,
|
|
248
|
-
*,
|
|
249
254
|
target: str,
|
|
250
255
|
document_name: str,
|
|
251
256
|
parameters: dict[str, Any],
|
|
252
257
|
reason: str | None = None,
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
"""Start new session.
|
|
258
|
+
) -> list[str]:
|
|
259
|
+
"""Build command for starting a session.
|
|
256
260
|
|
|
257
261
|
Args:
|
|
258
|
-
target: The target instance ID
|
|
262
|
+
target: The target instance ID.
|
|
259
263
|
document_name: The SSM document name to use for the session.
|
|
260
264
|
parameters: The parameters to pass to the SSM document.
|
|
261
265
|
reason: The reason for starting the session.
|
|
262
|
-
log_file: Optional file to log output to.
|
|
263
266
|
|
|
264
267
|
Returns:
|
|
265
|
-
|
|
268
|
+
The command to start the session.
|
|
266
269
|
"""
|
|
267
270
|
is_installed, binary_path, version = self.verify_installation()
|
|
268
271
|
if not is_installed:
|
|
@@ -279,7 +282,7 @@ class SessionManager:
|
|
|
279
282
|
)
|
|
280
283
|
|
|
281
284
|
region = self.session.region_name
|
|
282
|
-
|
|
285
|
+
return [
|
|
283
286
|
str(binary_path),
|
|
284
287
|
json.dumps(response),
|
|
285
288
|
region,
|
|
@@ -289,20 +292,6 @@ class SessionManager:
|
|
|
289
292
|
f"https://ssm.{region}.amazonaws.com",
|
|
290
293
|
]
|
|
291
294
|
|
|
292
|
-
stdout: subprocess._FILE
|
|
293
|
-
if log_file is not None: # noqa: SIM108
|
|
294
|
-
stdout = log_file.open(mode="at+", buffering=1)
|
|
295
|
-
else:
|
|
296
|
-
stdout = subprocess.DEVNULL
|
|
297
|
-
|
|
298
|
-
return subprocess.Popen( # noqa: S603
|
|
299
|
-
command,
|
|
300
|
-
stdout=stdout,
|
|
301
|
-
stderr=subprocess.STDOUT,
|
|
302
|
-
text=True,
|
|
303
|
-
close_fds=False, # FD inherited from parent process
|
|
304
|
-
)
|
|
305
|
-
|
|
306
295
|
|
|
307
296
|
# ? Could be moved to utils, but didn't because it's too specific to this module
|
|
308
297
|
class _LinuxDistribution(NamedTuple):
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import subprocess
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from .session_manager import SessionManager
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@contextmanager
|
|
18
|
+
def port_forward(
|
|
19
|
+
*,
|
|
20
|
+
through: str,
|
|
21
|
+
local_port: int,
|
|
22
|
+
remote_host: str,
|
|
23
|
+
remote_port: int,
|
|
24
|
+
reason: str | None = None,
|
|
25
|
+
) -> Iterator[subprocess.Popen[str]]:
|
|
26
|
+
"""Context manager for port forwarding sessions.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
through: The instance ID to use as port-forwarding proxy.
|
|
30
|
+
local_port: The local port to listen to.
|
|
31
|
+
remote_host: The remote host to connect to.
|
|
32
|
+
remote_port: The remote port to connect to.
|
|
33
|
+
reason: The reason for starting the session.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
The command to start the session.
|
|
37
|
+
"""
|
|
38
|
+
session_manager = SessionManager()
|
|
39
|
+
command = session_manager.build_command(
|
|
40
|
+
target=through,
|
|
41
|
+
document_name="AWS-StartPortForwardingSessionToRemoteHost",
|
|
42
|
+
parameters={
|
|
43
|
+
"localPortNumber": [str(local_port)],
|
|
44
|
+
"host": [remote_host],
|
|
45
|
+
"portNumber": [str(remote_port)],
|
|
46
|
+
},
|
|
47
|
+
reason=reason,
|
|
48
|
+
)
|
|
49
|
+
try:
|
|
50
|
+
proc = subprocess.Popen( # noqa: S603
|
|
51
|
+
command,
|
|
52
|
+
stdout=subprocess.PIPE,
|
|
53
|
+
stderr=subprocess.STDOUT,
|
|
54
|
+
text=True,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# * Must be unreachable
|
|
58
|
+
if proc.stdout is None:
|
|
59
|
+
msg = "Standard output is not available"
|
|
60
|
+
raise RuntimeError(msg)
|
|
61
|
+
|
|
62
|
+
# Wait for the session to start
|
|
63
|
+
# ? Not sure this is trustworthy health check
|
|
64
|
+
# TODO(lasuillard): Need timeout to avoid hanging forever
|
|
65
|
+
for line in proc.stdout:
|
|
66
|
+
if "Waiting for connections..." in line:
|
|
67
|
+
logger.info("Session started successfully.")
|
|
68
|
+
break
|
|
69
|
+
|
|
70
|
+
yield proc
|
|
71
|
+
finally:
|
|
72
|
+
proc.terminate()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aws-annoying
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Utils to handle some annoying AWS tasks.
|
|
5
5
|
Project-URL: Homepage, https://github.com/lasuillard/aws-annoying
|
|
6
6
|
Project-URL: Repository, https://github.com/lasuillard/aws-annoying.git
|
|
@@ -11,20 +11,21 @@ aws_annoying/cli/mfa/_app.py,sha256=Ub7gxb6kGF3Ve1ucQSOjHmc4jAu8mxgegcXsIbOzLLQ,
|
|
|
11
11
|
aws_annoying/cli/mfa/configure.py,sha256=vsoHfTVFF2dPgiYsp2L-EkMwtAA0_-tVwFd6Wv6DscU,3746
|
|
12
12
|
aws_annoying/cli/session_manager/__init__.py,sha256=FkT6jT6OXduOURN61d-U6hgd-XluQbvuVtKXXiXgSEk,105
|
|
13
13
|
aws_annoying/cli/session_manager/_app.py,sha256=OVOHW0iyKzunvaqLhjoseHw1-WxJ1gGb7QmiyAEezyY,221
|
|
14
|
-
aws_annoying/cli/session_manager/_common.py,sha256=
|
|
15
|
-
aws_annoying/cli/session_manager/install.py,sha256=
|
|
16
|
-
aws_annoying/cli/session_manager/port_forward.py,sha256=
|
|
17
|
-
aws_annoying/cli/session_manager/start.py,sha256=
|
|
14
|
+
aws_annoying/cli/session_manager/_common.py,sha256=u23F4mJOHWHphLYL1gOAh8J3a_Odyk4VVvI175KWmzg,1616
|
|
15
|
+
aws_annoying/cli/session_manager/install.py,sha256=zcQi91xVFKhbSOD4VBc6YG9-fDnhymVyK63PlITdxug,1445
|
|
16
|
+
aws_annoying/cli/session_manager/port_forward.py,sha256=J8_CIrTsbcOYRYOdHkdz81dkaNWxI_l70E8gyJ-Ukh8,4192
|
|
17
|
+
aws_annoying/cli/session_manager/start.py,sha256=pPS0jKuURGTX-WTix3owqqisX-bmCydqfyqC0kFGnt8,1358
|
|
18
18
|
aws_annoying/cli/session_manager/stop.py,sha256=ttU6nlbVgBkZDtY-DwUyCstv5TFtat5TljkyuY8QICU,1482
|
|
19
|
-
aws_annoying/session_manager/__init__.py,sha256=
|
|
19
|
+
aws_annoying/session_manager/__init__.py,sha256=IENviL3ux2LF7o9xFGYEiqaGw03hxnyNX2btbB1xyEU,318
|
|
20
20
|
aws_annoying/session_manager/errors.py,sha256=YioKlRtZ-GUP0F_ts_ebw7-HYkxe8mTes6HK821Kuiw,353
|
|
21
|
-
aws_annoying/session_manager/session_manager.py,sha256=
|
|
21
|
+
aws_annoying/session_manager/session_manager.py,sha256=myZxY_WE4akdlTsH1mOvf0Ublwg-hf1vEkEcmdZyYSU,12147
|
|
22
|
+
aws_annoying/session_manager/shortcuts.py,sha256=uFRPGia_5gqfBDxwOjmLg7UFzhvkSFUqopWuzN5_kbA,1973
|
|
22
23
|
aws_annoying/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
24
|
aws_annoying/utils/debugger.py,sha256=UFllDCGI2gPtwo1XS5vqw0qyR6bYr7XknmBwSxalKIc,754
|
|
24
25
|
aws_annoying/utils/downloader.py,sha256=aB5RzT-LpbFX24-2HXlAkdgVowc4TR9FWT_K8WwZ1BE,1923
|
|
25
26
|
aws_annoying/utils/platform.py,sha256=h3DUWmTMM-_4TfTWNqY0uNqyVsBjAuMm2DEbG-daxe8,742
|
|
26
|
-
aws_annoying-0.
|
|
27
|
-
aws_annoying-0.
|
|
28
|
-
aws_annoying-0.
|
|
29
|
-
aws_annoying-0.
|
|
30
|
-
aws_annoying-0.
|
|
27
|
+
aws_annoying-0.5.0.dist-info/METADATA,sha256=kHaGAHqfkZ8Ip4NzcLbE7Bh01oA1CvoTsUa3Ljx1ctU,1916
|
|
28
|
+
aws_annoying-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
29
|
+
aws_annoying-0.5.0.dist-info/entry_points.txt,sha256=DcKE5V0WvVJ8wUOHxyUz1yLAJOuuJUgRPlMcQ4O7jEs,66
|
|
30
|
+
aws_annoying-0.5.0.dist-info/licenses/LICENSE,sha256=Q5GkvYijQ2KTQ-QWhv43ilzCno4ZrzrEuATEQZd9rYo,1067
|
|
31
|
+
aws_annoying-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|