//! Un devcontainer en cours d'exécution : inspection et exécution de commandes. use std::time::Duration; use crate::{ consts::DEFAULT_EXEC_TIMEOUT, errors::ContainerError, exec::ExecOutput, runtime::ContainerRuntime, }; /// Un devcontainer en cours d'exécution. #[derive(Debug, Clone)] pub struct Container { runtime: ContainerRuntime, name: String, workspace_folder: String, remote_user: Option, network: Option, image: Option, } impl Container { /// Assemble un container démarré, avec son réseau et son image à nettoyer. pub(crate) fn new( runtime: ContainerRuntime, name: String, workspace_folder: String, remote_user: Option, network: Option, image: Option, ) -> Self { Self { runtime, name, workspace_folder, remote_user, network, image, } } pub fn name(&self) -> &str { &self.name } pub fn workspace_folder(&self) -> &str { &self.workspace_folder } /// Exécute une commande dans le container et renvoie sa sortie. /// /// La commande est transmise sous forme de vecteur d'arguments (argv, sans shell), /// donc aucun échappement ni interpolation n'est effectué. pub async fn exec(&self, cmd: &[&str]) -> Result { self.exec_with_timeout(cmd, DEFAULT_EXEC_TIMEOUT).await } pub(crate) async fn exec_with_timeout( &self, cmd: &[&str], timeout: Duration, ) -> Result { self.runtime .exec(&self.name, cmd, self.remote_user.as_deref(), timeout) .await } /// Exécute un script shell dans le container via `sh -c`. pub async fn exec_shell(&self, script: &str) -> Result { self.exec(&["sh", "-c", script]).await } /// Arrête le container. pub async fn stop(&self) -> Result<(), ContainerError> { self.runtime.stop_container(&self.name).await } /// Supprime le container, son réseau et son image. /// /// La suppression du réseau et de l'image est best-effort : ils peuvent déjà être absents. pub async fn remove(&self) -> Result<(), ContainerError> { self.runtime.remove_container(&self.name).await?; if let Some(network) = &self.network { let _ = self.runtime.remove_network(network).await; } if let Some(image) = &self.image { let _ = self.runtime.remove_image(image).await; } Ok(()) } }