-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #499 from latchbio/ayush/latch-attach
attach to nf workdir
- Loading branch information
Showing
7 changed files
with
268 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import asyncio | ||
import json | ||
import secrets | ||
import sys | ||
from typing import Optional | ||
from urllib.parse import urljoin, urlparse | ||
|
||
import click | ||
import websockets.client as websockets | ||
import websockets.exceptions as ws_exceptions | ||
from latch_sdk_config.latch import NUCLEUS_URL | ||
|
||
from latch_cli.utils import get_auth_header | ||
|
||
from .utils import get_pvc_info | ||
from .ws_utils import forward_stdio | ||
|
||
|
||
async def connect(execution_id: str, session_id: str): | ||
async with websockets.connect( | ||
urlparse(urljoin(NUCLEUS_URL, "/workflows/cli/attach-nf-workdir")) | ||
._replace(scheme="wss") | ||
.geturl(), | ||
close_timeout=0, | ||
extra_headers={"Authorization": get_auth_header()}, | ||
) as ws: | ||
request = {"execution_id": int(execution_id), "session_id": session_id} | ||
|
||
await ws.send(json.dumps(request)) | ||
data = await ws.recv() | ||
|
||
msg = "" | ||
try: | ||
res = json.loads(data) | ||
if "error" in res: | ||
raise RuntimeError(res["error"]) | ||
except json.JSONDecodeError: | ||
msg = "Unable to connect to pod - internal error." | ||
except RuntimeError as e: | ||
msg = str(e) | ||
|
||
if msg != "": | ||
raise RuntimeError(msg) | ||
|
||
await forward_stdio(ws) | ||
|
||
|
||
def get_session_id(): | ||
return secrets.token_bytes(8).hex() | ||
|
||
|
||
def attach(execution_id: Optional[str] = None): | ||
execution_id = get_pvc_info(execution_id) | ||
session_id = get_session_id() | ||
|
||
click.secho( | ||
"Attaching to workdir - this may take a few seconds...", dim=True, italic=True | ||
) | ||
|
||
import termios | ||
import tty | ||
|
||
old_settings_stdin = termios.tcgetattr(sys.stdin.fileno()) | ||
tty.setraw(sys.stdin) | ||
|
||
msg = "" | ||
try: | ||
asyncio.run(connect(execution_id, session_id)) | ||
except ws_exceptions.ConnectionClosedError as e: | ||
msg = json.loads(e.reason)["error"] | ||
except RuntimeError as e: | ||
msg = str(e) | ||
finally: | ||
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, old_settings_stdin) | ||
|
||
if msg != "": | ||
click.secho(msg, fg="red") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import asyncio | ||
import json | ||
import sys | ||
from typing import Optional | ||
from urllib.parse import urljoin, urlparse | ||
|
||
import websockets.client as websockets | ||
from latch_sdk_config.latch import NUCLEUS_URL | ||
|
||
from latch_cli.services.k8s.utils import ( | ||
ContainerNode, | ||
EGNNode, | ||
ExecutionInfoNode, | ||
get_container_info, | ||
get_egn_info, | ||
get_execution_info, | ||
) | ||
from latch_cli.utils import get_auth_header | ||
|
||
from .ws_utils import forward_stdio | ||
|
||
|
||
async def connect(egn_info: EGNNode, container_info: Optional[ContainerNode]): | ||
async with websockets.connect( | ||
urlparse(urljoin(NUCLEUS_URL, "/workflows/cli/shell")) | ||
._replace(scheme="wss") | ||
.geturl(), | ||
close_timeout=0, | ||
extra_headers={"Authorization": get_auth_header()}, | ||
) as ws: | ||
request = { | ||
"egn_id": egn_info["id"], | ||
"container_index": ( | ||
container_info["index"] if container_info is not None else None | ||
), | ||
} | ||
|
||
await ws.send(json.dumps(request)) | ||
data = await ws.recv() | ||
|
||
msg = "" | ||
try: | ||
res = json.loads(data) | ||
if "error" in res: | ||
raise RuntimeError(res["error"]) | ||
except json.JSONDecodeError: | ||
msg = "Unable to connect to pod - internal error." | ||
except RuntimeError as e: | ||
msg = str(e) | ||
|
||
if msg != "": | ||
raise RuntimeError(msg) | ||
|
||
await forward_stdio(ws) | ||
|
||
|
||
def exec( | ||
execution_id: Optional[str] = None, | ||
egn_id: Optional[str] = None, | ||
container_index: Optional[int] = None, | ||
): | ||
execution_info: Optional[ExecutionInfoNode] = None | ||
if egn_id is None: | ||
execution_info = get_execution_info(execution_id) | ||
|
||
egn_info = get_egn_info(execution_info, egn_id) | ||
container_info = get_container_info(egn_info, container_index) | ||
|
||
import termios | ||
import tty | ||
|
||
old_settings_stdin = termios.tcgetattr(sys.stdin.fileno()) | ||
tty.setraw(sys.stdin) | ||
|
||
try: | ||
asyncio.run(connect(egn_info, container_info)) | ||
finally: | ||
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, old_settings_stdin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.