Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit eb290db

Browse files
authored
Merge branch 'main' into keepalive
2 parents 3907ba7 + dbc50d2 commit eb290db

2 files changed

Lines changed: 50 additions & 22 deletions

File tree

  • packages

packages/jumpstarter-cli/jumpstarter_cli/shell.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,25 @@
1212

1313
@click.command("shell")
1414
@opt_config()
15+
@click.argument("command", nargs=-1)
1516
# client specific
1617
# TODO: warn if these are specified with exporter config
1718
@click.option("--lease", "lease_name")
1819
@opt_selector
1920
@opt_duration_partial(default=timedelta(minutes=30), show_default="00:30:00")
2021
# end client specific
2122
@handle_exceptions
22-
def shell(config, lease_name, selector, duration):
23+
def shell(config, command: tuple[str, ...], lease_name, selector, duration):
2324
"""
24-
Spawns a shell connecting to a local or remote exporter
25+
Spawns a shell (or custom command) connecting to a local or remote exporter
26+
27+
COMMAND is the custom command to run instead of shell.
28+
29+
Example:
30+
31+
.. code-block:: bash
32+
33+
$ jmp shell --exporter foo -- python bar.py
2534
"""
2635

2736
match config:
@@ -31,11 +40,23 @@ def shell(config, lease_name, selector, duration):
3140
with config.lease(selector=selector, lease_name=lease_name, duration=duration) as lease:
3241
with lease.serve_unix() as path:
3342
with lease.monitor():
34-
exit_code = launch_shell(path, "remote", config.drivers.allow, config.drivers.unsafe)
43+
exit_code = launch_shell(
44+
path,
45+
"remote",
46+
config.drivers.allow,
47+
config.drivers.unsafe,
48+
command=command,
49+
)
3550

3651
sys.exit(exit_code)
3752

3853
case ExporterConfigV1Alpha1():
3954
with config.serve_unix() as path:
4055
# SAFETY: the exporter config is local thus considered trusted
41-
launch_shell(path, "local", allow=[], unsafe=True)
56+
launch_shell(
57+
path,
58+
"local",
59+
allow=[],
60+
unsafe=True,
61+
command=command,
62+
)

packages/jumpstarter/jumpstarter/common/utils.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,14 @@ def env():
8080
PROMPT_CWD = "\\W"
8181

8282

83-
def launch_shell(host: str, context: str, allow: list[str], unsafe: bool) -> int:
83+
def launch_shell(
84+
host: str,
85+
context: str,
86+
allow: [str],
87+
unsafe: bool,
88+
*,
89+
command: tuple[str, ...] | None = None,
90+
) -> int:
8491
"""Launch a shell with a custom prompt indicating the exporter type.
8592
8693
Args:
@@ -89,21 +96,21 @@ def launch_shell(host: str, context: str, allow: list[str], unsafe: bool) -> int
8996
allow: List of allowed drivers
9097
unsafe: Whether to allow drivers outside of the allow list
9198
"""
92-
cmd = [os.environ.get("SHELL", "bash")]
93-
if cmd[0].endswith("bash"):
94-
cmd.append("--norc")
95-
cmd.append("--noprofile")
96-
97-
process = Popen(
98-
cmd,
99-
stdin=sys.stdin,
100-
stdout=sys.stdout,
101-
stderr=sys.stderr,
102-
env=os.environ
103-
| {
104-
JUMPSTARTER_HOST: host,
105-
JMP_DRIVERS_ALLOW: "UNSAFE" if unsafe else ",".join(allow),
106-
"PS1": f"{ANSI_GRAY}{PROMPT_CWD} {ANSI_YELLOW}{ANSI_WHITE}{context} {ANSI_YELLOW}{ANSI_RESET} ",
107-
},
108-
)
99+
100+
env = os.environ | {
101+
JUMPSTARTER_HOST: host,
102+
JMP_DRIVERS_ALLOW: "UNSAFE" if unsafe else ",".join(allow),
103+
"PS1": f"{ANSI_GRAY}{PROMPT_CWD} {ANSI_YELLOW}{ANSI_WHITE}{context} {ANSI_YELLOW}{ANSI_RESET} ",
104+
}
105+
106+
if command:
107+
process = Popen(command, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr, env=env)
108+
else:
109+
cmd = [os.environ.get("SHELL", "bash")]
110+
if cmd[0].endswith("bash"):
111+
cmd.append("--norc")
112+
cmd.append("--noprofile")
113+
114+
process = Popen(cmd, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr, env=env)
115+
109116
return process.wait()

0 commit comments

Comments
 (0)