A focused Docker Compose management web application.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: start/stop actions

Brooke 83dddbab 2c15a36c

+89 -27
+48
packages/node/src/api/actions.rs
··· 29 29 .await?; 30 30 return Ok(().into()); 31 31 } 32 + 33 + /// Starts the given project and all its services. 34 + #[endpoint] 35 + pub async fn start_project(project: PathParam<String>, depot: &mut Depot) -> LuminaryResponse<()> { 36 + let engine = obtain!(depot, LuminaryEngine); 37 + 38 + engine.start(project.into_inner(), None).await?; 39 + return Ok(().into()); 40 + } 41 + 42 + /// Starts the given service of the project. 43 + #[endpoint] 44 + pub async fn start_service( 45 + project: PathParam<String>, 46 + service: PathParam<String>, 47 + depot: &mut Depot, 48 + ) -> LuminaryResponse<()> { 49 + let engine = obtain!(depot, LuminaryEngine); 50 + 51 + engine 52 + .start(project.into_inner(), Some(service.into_inner())) 53 + .await?; 54 + return Ok(().into()); 55 + } 56 + 57 + /// Stops the given project and all its services. 58 + #[endpoint] 59 + pub async fn stop_project(project: PathParam<String>, depot: &mut Depot) -> LuminaryResponse<()> { 60 + let engine = obtain!(depot, LuminaryEngine); 61 + 62 + engine.stop(project.into_inner(), None).await?; 63 + return Ok(().into()); 64 + } 65 + 66 + /// Stops the given service of the project. 67 + #[endpoint] 68 + pub async fn stop_service( 69 + project: PathParam<String>, 70 + service: PathParam<String>, 71 + depot: &mut Depot, 72 + ) -> LuminaryResponse<()> { 73 + let engine = obtain!(depot, LuminaryEngine); 74 + 75 + engine 76 + .stop(project.into_inner(), Some(service.into_inner())) 77 + .await?; 78 + return Ok(().into()); 79 + }
+5 -1
packages/node/src/api/mod.rs
··· 72 72 Router::with_path("/project/{project}") 73 73 .push(Router::with_path("logs").get(logs_subscribe)) 74 74 .push(Router::with_path("restart").post(actions::restart_project)) 75 + .push(Router::with_path("start").post(actions::start_project)) 76 + .push(Router::with_path("stop").post(actions::stop_project)) 75 77 .push( 76 78 Router::with_path("service/{service}") 77 - .push(Router::with_path("restart").post(actions::restart_service)), 79 + .push(Router::with_path("restart").post(actions::restart_service)) 80 + .push(Router::with_path("start").post(actions::start_service)) 81 + .push(Router::with_path("stop").post(actions::stop_service)), 78 82 ), 79 83 ), 80 84 ),
+34 -26
packages/node/src/core/action.rs
··· 1 1 use eyre::{ContextCompat, Result, bail}; 2 - use futures_util::{Stream, StreamExt}; 2 + use futures_util::StreamExt; 3 3 use luminary_macros::wrap_err; 4 4 5 5 use crate::core::{LuminaryAction, LuminaryEngine}; ··· 47 47 return Ok(()); 48 48 } 49 49 50 - /// Waits for the given stream to complete and sets the project's action to Idle once done. 51 - /// TODO: Eventually we may want to stream this back to the client instead of just waiting. 52 - fn wait<T>( 50 + /// A helper function to run a given command for a project and optionally, a specific service within that project. 51 + // TODO: Eventually we may want to stream this back to the client instead of just waiting. 52 + async fn run( 53 53 &self, 54 + action: LuminaryAction, 54 55 project: String, 55 56 service: Option<String>, 56 - mut stream: impl Stream<Item = T> + Unpin + Send + 'static, 57 - ) -> tokio::task::JoinHandle<()> { 58 - let this = self.clone(); 59 - return tokio::spawn(async move { 60 - while let Some(_) = stream.next().await {} 61 - match this.set_action(project, service, LuminaryAction::Idle).await { 62 - Err(e) => log::error!("Failed to reset action: {:?}", e), 63 - Ok(_) => (), 64 - } 65 - }); 57 + mut args: Vec<&str>, 58 + ) -> Result<()> { 59 + self.set_action(project.clone(), service.clone(), action).await?; 60 + 61 + if let Some(service) = &service { 62 + args.push(service); 63 + } 64 + 65 + let mut stream = self.cli(&project, args)?; 66 + while let Some(_) = stream.next().await {} 67 + self.set_action(project, service, LuminaryAction::Idle).await?; 68 + return Ok(()); 66 69 } 67 70 68 71 /// Restarts the given project and optionally, a specific service within that project. 69 72 #[wrap_err("Failed to restart project/service")] 70 - pub async fn restart( 71 - &self, 72 - project: String, 73 - service: Option<String>, 74 - ) -> Result<tokio::task::JoinHandle<()>> { 75 - self.set_action(project.clone(), service.clone(), LuminaryAction::Restarting) 73 + pub async fn restart(&self, project: String, service: Option<String>) -> Result<()> { 74 + self.run(LuminaryAction::Restarting, project, service, vec!["restart"]) 76 75 .await?; 76 + Ok(()) 77 + } 77 78 78 - let mut args = vec!["restart"]; 79 - if let Some(service) = &service { 80 - args.push(service); 81 - } 79 + /// Starts the given project and optionally, a specific service within that project. 80 + #[wrap_err("Failed to start project/service")] 81 + pub async fn start(&self, project: String, service: Option<String>) -> Result<()> { 82 + self.run(LuminaryAction::Starting, project, service, vec!["up", "-d"]) 83 + .await?; 84 + Ok(()) 85 + } 82 86 83 - let stream = self.cli(&project, args)?; 84 - return Ok(self.wait(project, service, stream)); 87 + /// Stops the given project and optionally, a specific service within that project. 88 + #[wrap_err("Failed to stop project/service")] 89 + pub async fn stop(&self, project: String, service: Option<String>) -> Result<()> { 90 + self.run(LuminaryAction::Stopping, project, service, vec!["down"]) 91 + .await?; 92 + Ok(()) 85 93 } 86 94 }
+2
packages/node/src/core/model.rs
··· 159 159 pub enum LuminaryAction { 160 160 Idle, 161 161 Restarting, 162 + Stopping, 163 + Starting, 162 164 } 163 165 164 166 /// Stores the log channel and buffer for a project.