add depends_on start order resolution
This commit is contained in:
		@@ -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");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user