use crate::{
composition::{Composition, StaticManagementPolicy},
container::CreatedContainer,
docker::Docker,
DockerTestError, Network, OperationalContainer, PendingContainer,
};
use dynamic::DynamicContainers;
use external::ExternalContainers;
use internal::InternalContainers;
use std::{collections::HashSet, sync::LazyLock};
mod dynamic;
mod external;
mod internal;
mod network;
pub use dynamic::CreateDynamicContainer;
pub(crate) use network::SCOPED_NETWORKS;
pub(crate) static STATIC_CONTAINERS: LazyLock<StaticContainers> =
LazyLock::new(StaticContainers::default);
#[derive(Default)]
pub struct StaticContainers {
internal: InternalContainers,
external: ExternalContainers,
dynamic: DynamicContainers,
}
impl StaticContainers {
pub async fn create(
&self,
composition: Composition,
client: &Docker,
network: Option<&str>,
network_mode: &Network,
) -> Result<CreatedContainer, DockerTestError> {
if let Some(policy) = composition.static_management_policy() {
match policy {
StaticManagementPolicy::Internal => self
.internal
.create(composition, client, network, network_mode)
.await
.map(CreatedContainer::Pending),
StaticManagementPolicy::External => {
let external = self
.external
.include(composition, client, network, network_mode)
.await?;
Ok(CreatedContainer::StaticExternal(external))
}
StaticManagementPolicy::Dynamic => {
self.dynamic
.create(composition, client, network, network_mode)
.await
}
}
} else {
Err(DockerTestError::Startup(
"tried to create static container without a management policy".to_string(),
))
}
}
pub async fn external_containers(&self) -> Vec<OperationalContainer> {
let mut external = self.external.containers().await;
let mut dynamic_running_prior = self.dynamic.prior_running_containers().await;
external.append(&mut dynamic_running_prior);
external
}
pub async fn start(
&self,
container: &PendingContainer,
) -> Result<OperationalContainer, DockerTestError> {
if let Some(policy) = &container.static_management_policy {
match policy {
StaticManagementPolicy::External => Err(DockerTestError::Startup(
"tried to start an external container".to_string(),
)),
StaticManagementPolicy::Internal => self.internal.start(container).await,
StaticManagementPolicy::Dynamic => self.dynamic.start(container).await,
}
} else {
Err(DockerTestError::Startup(
"tried to start a non-exiting static container".to_string(),
))
}
}
pub async fn cleanup(
&self,
client: &Docker,
network: &str,
network_mode: &Network,
to_cleanup: Vec<&str>,
) {
let cleanup: HashSet<&str> = to_cleanup.into_iter().collect();
self.internal.cleanup(client, network, &cleanup).await;
self.dynamic
.disconnect(client, network, network_mode, &cleanup)
.await;
self.external
.disconnect(client, network, network_mode, &cleanup)
.await;
}
}