add depends_on start order resolution
This commit is contained in:
parent
d22037031a
commit
228e8ff9b9
@ -5,13 +5,14 @@ use bollard::container::{Config, CreateContainerOptions, RemoveContainerOptions}
|
||||
use bollard::models::{HostConfig, PortBinding, PortMap, RestartPolicy, RestartPolicyNameEnum};
|
||||
use bollard::Docker;
|
||||
use std::collections::HashMap;
|
||||
use std::iter::Map;
|
||||
|
||||
pub(crate) async fn create_containers(
|
||||
compose: &DockerCompose,
|
||||
docker: &Docker,
|
||||
detach: bool,
|
||||
) -> anyhow::Result<Vec<String>> {
|
||||
let mut container_ids = Vec::new();
|
||||
) -> anyhow::Result<HashMap<String, String>> {
|
||||
let mut container_ids = HashMap::new();
|
||||
let parent_dir = parent_dir_name()?;
|
||||
for (name, service) in &compose.services {
|
||||
let env = create_env_vec(&service.environment);
|
||||
@ -43,14 +44,62 @@ pub(crate) async fn create_containers(
|
||||
conf,
|
||||
)
|
||||
.await?;
|
||||
container_ids.push(create_info.id);
|
||||
container_ids.insert(name.clone(), create_info.id);
|
||||
}
|
||||
Ok(container_ids)
|
||||
}
|
||||
|
||||
pub(crate) async fn start_containers(docker: &Docker, ids: Vec<String>) -> anyhow::Result<()> {
|
||||
for id in ids {
|
||||
docker.start_container::<String>(&id, None).await?;
|
||||
fn resolve_start_order(compose: &DockerCompose) -> Vec<String> {
|
||||
let mut start_order = Vec::new();
|
||||
let mut visited = HashMap::new();
|
||||
|
||||
for service_name in compose.services.keys() {
|
||||
resolve_service(service_name, compose, &mut visited, &mut start_order);
|
||||
}
|
||||
|
||||
start_order
|
||||
}
|
||||
|
||||
fn resolve_service(
|
||||
service_name: &str,
|
||||
compose: &DockerCompose,
|
||||
visited: &mut HashMap<String, bool>,
|
||||
start_order: &mut Vec<String>,
|
||||
) {
|
||||
if let Some(&true) = visited.get(service_name) {
|
||||
return;
|
||||
}
|
||||
visited.insert(service_name.to_string(), true);
|
||||
|
||||
if let Some(service) = compose.services.get(service_name) {
|
||||
if let Some(dependencies) = &service.depends_on {
|
||||
for dependency in dependencies {
|
||||
resolve_service(dependency, compose, visited, start_order);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
start_order.push(service_name.to_string());
|
||||
}
|
||||
|
||||
pub(crate) async fn start_containers(
|
||||
compose: &DockerCompose,
|
||||
docker: &Docker,
|
||||
ids: HashMap<String, String>,
|
||||
) -> anyhow::Result<()> {
|
||||
// resolve dependency resolution
|
||||
let start_order = resolve_start_order(compose);
|
||||
|
||||
for container_name in start_order {
|
||||
docker
|
||||
.start_container::<String>(
|
||||
ids.get(&container_name).ok_or(anyhow!(
|
||||
"no created container found with name {}",
|
||||
container_name
|
||||
))?,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ pub async fn up(compose_file: Option<String>, detach: bool) -> anyhow::Result<()
|
||||
pull_images(&compose, &docker).await;
|
||||
create_volumes(&compose, &docker).await?;
|
||||
let ids = create_containers(&compose, &docker, detach).await?;
|
||||
start_containers(&docker, ids.clone()).await?;
|
||||
start_containers(&compose, &docker, ids.clone()).await?;
|
||||
|
||||
if !detach {
|
||||
monitor_build_outputs(&docker, ids).await?;
|
||||
|
@ -3,11 +3,17 @@ use bollard::container::{AttachContainerOptions, LogOutput};
|
||||
use bollard::Docker;
|
||||
use futures_util::future::join_all;
|
||||
use futures_util::StreamExt;
|
||||
use std::collections::HashMap;
|
||||
use std::iter::Map;
|
||||
|
||||
pub(crate) async fn monitor_build_outputs(docker: &Docker, ids: Vec<String>) -> anyhow::Result<()> {
|
||||
pub(crate) async fn monitor_build_outputs(
|
||||
docker: &Docker,
|
||||
ids: HashMap<String, String>,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut handles = vec![];
|
||||
for id in ids.clone() {
|
||||
for id in ids.values() {
|
||||
let docker = docker.clone();
|
||||
let id = id.clone();
|
||||
handles.push(tokio::spawn(async move {
|
||||
let r = monitor_logs(&docker, id.clone()).await;
|
||||
println!("Container {} exited with {:?}", id, r)
|
||||
@ -17,7 +23,7 @@ pub(crate) async fn monitor_build_outputs(docker: &Docker, ids: Vec<String>) ->
|
||||
tokio::select! {
|
||||
_ = tokio::signal::ctrl_c() => {
|
||||
println!("Ctrl-c received, stopping containers");
|
||||
stop_containers_by_ids(docker, ids.clone()).await?;
|
||||
stop_containers_by_ids(docker, ids.values().map(|v| v.to_string()).collect()).await?;
|
||||
}
|
||||
_ = join_all(handles) => {
|
||||
println!("All containers exited");
|
||||
|
Loading…
Reference in New Issue
Block a user