Skip to content

Commit 1f2a85e

Browse files
Kh4Ljohntmyers
andauthored
fix(cli): clear stale last-used sandbox on deletion (#510)
* fix(cli): clear stale last-used sandbox on deletion When a sandbox is deleted, the locally stored last-used record now gets cleared if it matches the deleted sandbox name. This prevents subsequent commands from falling back to a sandbox that no longer exists, which previously caused confusing gRPC errors. Adds clear_last_sandbox_if_matches() to openshell-bootstrap and calls it from sandbox_delete() after each successful deletion. Closes #172 Signed-off-by: Serge Panev <spanev@nvidia.com> * style: fix rustfmt import ordering and line wrapping Signed-off-by: Serge Panev <spanev@nvidia.com> * fix(cli): pass gateway to sandbox_delete in finalize_sandbox_create_session Signed-off-by: John Myers <johntmyers@users.noreply.github.com> --------- Signed-off-by: Serge Panev <spanev@nvidia.com> Signed-off-by: John Myers <johntmyers@users.noreply.github.com> Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
1 parent 834f8aa commit 1f2a85e

File tree

4 files changed

+29
-10
lines changed

4 files changed

+29
-10
lines changed

crates/openshell-bootstrap/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ pub use crate::docker::{
4848
DockerPreflight, ExistingGatewayInfo, check_docker_available, create_ssh_docker_client,
4949
};
5050
pub use crate::metadata::{
51-
GatewayMetadata, clear_active_gateway, extract_host_from_ssh_destination, get_gateway_metadata,
52-
list_gateways, load_active_gateway, load_gateway_metadata, load_last_sandbox,
53-
remove_gateway_metadata, resolve_ssh_hostname, save_active_gateway, save_last_sandbox,
54-
store_gateway_metadata,
51+
GatewayMetadata, clear_active_gateway, clear_last_sandbox_if_matches,
52+
extract_host_from_ssh_destination, get_gateway_metadata, list_gateways, load_active_gateway,
53+
load_gateway_metadata, load_last_sandbox, remove_gateway_metadata, resolve_ssh_hostname,
54+
save_active_gateway, save_last_sandbox, store_gateway_metadata,
5555
};
5656

5757
/// Options for remote SSH deployment.

crates/openshell-bootstrap/src/metadata.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,20 @@ pub fn load_last_sandbox(gateway: &str) -> Option<String> {
271271
if name.is_empty() { None } else { Some(name) }
272272
}
273273

274+
/// Clear the last-used sandbox record for a gateway if it matches the given name.
275+
///
276+
/// This should be called after a sandbox is deleted so that subsequent commands
277+
/// don't try to connect to a sandbox that no longer exists.
278+
pub fn clear_last_sandbox_if_matches(gateway: &str, sandbox: &str) {
279+
if let Some(current) = load_last_sandbox(gateway) {
280+
if current == sandbox {
281+
if let Ok(path) = last_sandbox_path(gateway) {
282+
let _ = std::fs::remove_file(path);
283+
}
284+
}
285+
}
286+
}
287+
274288
/// List all gateways that have stored metadata.
275289
///
276290
/// Scans `$XDG_CONFIG_HOME/openshell/gateways/` for subdirectories containing

crates/openshell-cli/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2268,7 +2268,7 @@ async fn main() -> Result<()> {
22682268
run::sandbox_list(endpoint, limit, offset, ids, names, &tls).await?;
22692269
}
22702270
SandboxCommands::Delete { names, all } => {
2271-
run::sandbox_delete(endpoint, &names, all, &tls).await?;
2271+
run::sandbox_delete(endpoint, &names, all, &tls, &ctx.name).await?;
22722272
}
22732273
SandboxCommands::Connect { name, editor } => {
22742274
let name = resolve_sandbox_name(name, &ctx.name)?;

crates/openshell-cli/src/run.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ use hyper_util::{client::legacy::Client, rt::TokioExecutor};
1616
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
1717
use miette::{IntoDiagnostic, Result, WrapErr, miette};
1818
use openshell_bootstrap::{
19-
DeployOptions, GatewayMetadata, RemoteOptions, clear_active_gateway, container_name,
20-
extract_host_from_ssh_destination, get_gateway_metadata, list_gateways, load_active_gateway,
21-
remove_gateway_metadata, resolve_ssh_hostname, save_active_gateway, save_last_sandbox,
22-
store_gateway_metadata,
19+
DeployOptions, GatewayMetadata, RemoteOptions, clear_active_gateway,
20+
clear_last_sandbox_if_matches, container_name, extract_host_from_ssh_destination,
21+
get_gateway_metadata, list_gateways, load_active_gateway, remove_gateway_metadata,
22+
resolve_ssh_hostname, save_active_gateway, save_last_sandbox, store_gateway_metadata,
2323
};
2424
use openshell_core::proto::{
2525
ApproveAllDraftChunksRequest, ApproveDraftChunkRequest, ClearDraftChunksRequest,
@@ -1904,13 +1904,14 @@ async fn finalize_sandbox_create_session(
19041904
persist: bool,
19051905
session_result: Result<()>,
19061906
tls: &TlsOptions,
1907+
gateway: &str,
19071908
) -> Result<()> {
19081909
if persist {
19091910
return session_result;
19101911
}
19111912

19121913
let names = [sandbox_name.to_string()];
1913-
if let Err(err) = sandbox_delete(server, &names, false, tls).await {
1914+
if let Err(err) = sandbox_delete(server, &names, false, tls, gateway).await {
19141915
if session_result.is_ok() {
19151916
return Err(err);
19161917
}
@@ -2380,6 +2381,7 @@ pub async fn sandbox_create(
23802381
persist,
23812382
connect_result,
23822383
&effective_tls,
2384+
gateway_name,
23832385
)
23842386
.await;
23852387
}
@@ -2415,6 +2417,7 @@ pub async fn sandbox_create(
24152417
persist,
24162418
exec_result,
24172419
&effective_tls,
2420+
gateway_name,
24182421
)
24192422
.await
24202423
}
@@ -2824,6 +2827,7 @@ pub async fn sandbox_delete(
28242827
names: &[String],
28252828
all: bool,
28262829
tls: &TlsOptions,
2830+
gateway: &str,
28272831
) -> Result<()> {
28282832
let mut client = grpc_client(server, tls).await?;
28292833

@@ -2864,6 +2868,7 @@ pub async fn sandbox_delete(
28642868

28652869
let deleted = response.into_inner().deleted;
28662870
if deleted {
2871+
clear_last_sandbox_if_matches(gateway, name);
28672872
println!("{} Deleted sandbox {name}", "✓".green().bold());
28682873
} else {
28692874
println!("{} Sandbox {name} not found", "!".yellow());

0 commit comments

Comments
 (0)