diff --git a/cargo-shuttle/src/lib.rs b/cargo-shuttle/src/lib.rs index b74b10dca1..1c973e3f5f 100644 --- a/cargo-shuttle/src/lib.rs +++ b/cargo-shuttle/src/lib.rs @@ -1917,7 +1917,7 @@ impl Shuttle { }); #[cfg(target_family = "unix")] - { + let exit_result = { let mut sigterm_notif = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) .expect("Can not get the SIGTERM signal receptor"); @@ -1925,16 +1925,21 @@ impl Shuttle { tokio::signal::unix::signal(tokio::signal::unix::SignalKind::interrupt()) .expect("Can not get the SIGINT signal receptor"); tokio::select! { + exit_result = runtime.wait() => { + Some(exit_result) + } _ = sigterm_notif.recv() => { - eprintln!("cargo-shuttle received SIGTERM. Killing all the runtimes..."); + eprintln!("cargo-shuttle received SIGTERM. Killing the runtime..."); + None }, _ = sigint_notif.recv() => { - eprintln!("cargo-shuttle received SIGINT. Killing all the runtimes..."); + eprintln!("cargo-shuttle received SIGINT. Killing the runtime..."); + None } - }; - } + } + }; #[cfg(target_family = "windows")] - { + let exit_result = { let mut ctrl_break_notif = tokio::signal::windows::ctrl_break() .expect("Can not get the CtrlBreak signal receptor"); let mut ctrl_c_notif = @@ -1945,28 +1950,48 @@ impl Shuttle { .expect("Can not get the CtrlLogoff signal receptor"); let mut ctrl_shutdown_notif = tokio::signal::windows::ctrl_shutdown() .expect("Can not get the CtrlShutdown signal receptor"); - tokio::select! { + exit_result = runtime.wait() => { + Some(exit_result) + } _ = ctrl_break_notif.recv() => { eprintln!("cargo-shuttle received ctrl-break."); + None }, _ = ctrl_c_notif.recv() => { eprintln!("cargo-shuttle received ctrl-c."); + None }, _ = ctrl_close_notif.recv() => { eprintln!("cargo-shuttle received ctrl-close."); + None }, _ = ctrl_logoff_notif.recv() => { eprintln!("cargo-shuttle received ctrl-logoff."); + None }, _ = ctrl_shutdown_notif.recv() => { eprintln!("cargo-shuttle received ctrl-shutdown."); + None } } + }; + match exit_result { + Some(Ok(exit_status)) => { + bail!( + "Runtime process exited with code {}", + exit_status.code().unwrap_or_default() + ); + } + Some(Err(e)) => { + bail!("Failed to wait for runtime process to exit: {e}"); + } + None => { + runtime.kill().await?; + } } - runtime.kill().await?; - // println!("Run `cargo shuttle deploy` to deploy your Shuttle service."); + println!("Run `cargo shuttle deploy` to deploy your Shuttle service."); Ok(CommandOutcome::Ok) } diff --git a/cargo-shuttle/src/provisioner_server.rs b/cargo-shuttle/src/provisioner_server.rs index 3f31883d21..fd0f8193a6 100644 --- a/cargo-shuttle/src/provisioner_server.rs +++ b/cargo-shuttle/src/provisioner_server.rs @@ -537,7 +537,7 @@ pub mod beta { Ok(res) } - pub async fn provision( + async fn provision( state: Arc, method: Method, uri: &str, @@ -576,10 +576,10 @@ pub mod beta { .into(), ), }; - resource::Response { - r#type: shuttle_resource.r#type, - config: serde_json::Value::Null, - data: serde_json::to_value(&res).unwrap(), + ShuttleResourceOutput { + output: serde_json::to_value(&res).unwrap(), + custom: serde_json::Value::Null, + state: Some(resource::ResourceState::Ready), } } resource::Type::Container => { @@ -588,28 +588,23 @@ pub mod beta { let res = prov.start_container(config) .await .context("Failed to start Docker container. Make sure that a Docker engine is running.")?; - resource::Response { - r#type: shuttle_resource.r#type, - config: serde_json::Value::Null, - data: serde_json::to_value(&res).unwrap(), + ShuttleResourceOutput { + output: serde_json::to_value(&res).unwrap(), + custom: serde_json::Value::Null, + state: Some(resource::ResourceState::Ready), } } - resource::Type::Secrets => resource::Response { - r#type: shuttle_resource.r#type, - config: serde_json::Value::Null, - data: serde_json::to_value(&state.secrets).unwrap(), + resource::Type::Secrets => ShuttleResourceOutput { + output: serde_json::to_value(&state.secrets).unwrap(), + custom: serde_json::Value::Null, + state: Some(resource::ResourceState::Ready), }, _ => { bail!("Resource not supported"); } }; - serde_json::to_vec(&ShuttleResourceOutput { - output: response, - custom: serde_json::Value::Null, - state: Some(resource::ResourceState::Ready), - }) - .unwrap() + serde_json::to_vec(&response).unwrap() } _ => bail!("Received unsupported resource request"), }) diff --git a/runtime/src/beta.rs b/runtime/src/beta.rs index e4e1765a78..53b7aa6d60 100644 --- a/runtime/src/beta.rs +++ b/runtime/src/beta.rs @@ -16,7 +16,7 @@ use shuttle_common::{ resource::{ResourceInput, ResourceState, Type}, secrets::Secret, }; -use shuttle_service::{Environment, ResourceFactory, Service}; +use shuttle_service::{Environment, ResourceFactory, Service, ShuttleResourceOutput}; use crate::__internals::{Loader, Runner}; @@ -157,7 +157,12 @@ pub async fn start(loader: impl Loader + Send + 'static, runner: impl Runner + S { // Secrets don't need to be requested here since we already got them above. if shuttle_resource.r#type == Type::Secrets { - *bytes = serde_json::to_vec(&secrets).expect("to serialize struct"); + *bytes = serde_json::to_vec(&ShuttleResourceOutput { + output: serde_json::to_value(&secrets).unwrap(), + custom: serde_json::Value::Null, + state: Some(ResourceState::Ready), + }) + .expect("to serialize struct"); continue; } println!("Provisioning {}", shuttle_resource.r#type); @@ -166,12 +171,12 @@ pub async fn start(loader: impl Loader + Send + 'static, runner: impl Runner + S .provision_resource_beta(&project_id, shuttle_resource.clone()) .await { - Ok(o) => match o.state.expect("resource to have a state") { + Ok(output) => match output.state.clone().expect("resource to have a state") { ResourceState::Provisioning | ResourceState::Authorizing => { tokio::time::sleep(tokio::time::Duration::from_millis(2000)).await; } ResourceState::Ready => { - *bytes = serde_json::to_vec(&o.output).expect("to serialize struct"); + *bytes = serde_json::to_vec(&output).expect("to serialize struct"); break; } bad_state => {