use podup::{Engine, StatsOptions};
use crate::cli::*;
fn profile_filtered(
file: &podup::compose::types::ComposeFile,
profile: &[String],
targets: &[String],
) -> podup::compose::types::ComposeFile {
let mut filtered = file.clone();
podup::retain_active_profiles_with_targets(&mut filtered, profile, targets);
filtered
}
pub(crate) async fn dispatch(
engine: &Engine,
file: &podup::compose::types::ComposeFile,
command: Commands,
profile: &[String],
) -> podup::Result<()> {
match command {
Commands::Up {
detach,
build,
watch,
remove_orphans,
no_recreate,
force_recreate,
no_deps,
timeout: _,
scale: _,
pull: _,
no_build: _,
quiet_pull: _,
wait,
wait_timeout,
no_start,
timestamps,
renew_anon_volumes: _,
services,
} => {
if remove_orphans {
engine.remove_orphans(file).await?;
} else {
engine.warn_orphans(file).await?;
}
if build {
engine.build_all(file, &services).await?;
}
if no_start {
engine
.create_with_options(
file,
profile,
&services,
no_recreate,
force_recreate,
no_deps,
)
.await?;
return Ok(());
}
engine
.up_with_options(
file,
detach,
profile,
&services,
no_recreate,
force_recreate,
no_deps,
)
.await?;
if wait {
let fut = engine.wait_services_healthy(file, &services);
match wait_timeout {
Some(secs) => tokio::time::timeout(std::time::Duration::from_secs(secs), fut)
.await
.map_err(|_| podup::ComposeError::WaitTimeout { secs })??,
None => fut.await?,
}
}
if watch {
engine.watch(file).await?;
} else if !detach {
engine.attach_logs_with_options(file, timestamps).await?;
let _ = engine.stop(file, &[]).await;
}
}
Commands::Down {
volumes,
remove_orphans,
rmi,
timeout: _,
} => {
if remove_orphans {
engine.remove_orphans(file).await?;
}
engine.down_with_options(file, volumes).await?;
if let Some(scope) = rmi {
engine
.remove_service_images(file, scope == RmiScope::Local)
.await?;
}
}
Commands::Start {
wait,
wait_timeout,
services,
} => {
let file = &profile_filtered(file, profile, &services);
engine.start(file, &services).await?;
if wait {
match wait_timeout {
Some(secs) => {
let budget = std::time::Duration::from_secs(secs);
let fut =
engine.wait_services_healthy_within(file, &services, Some(budget));
tokio::time::timeout(budget, fut)
.await
.map_err(|_| podup::ComposeError::WaitTimeout { secs })??;
}
None => engine.wait_services_healthy(file, &services).await?,
}
}
}
Commands::Stop {
services,
timeout: _,
} => {
let file = &profile_filtered(file, profile, &services);
engine.stop(file, &services).await?
}
Commands::Scale { pairs } => engine.scale(file, &pairs).await?,
Commands::Create {
build,
force_recreate,
no_recreate,
pull: _,
no_deps,
services,
} => {
if build {
engine.build_all(file, &services).await?;
}
engine
.create_with_options(
file,
profile,
&services,
no_recreate,
force_recreate,
no_deps,
)
.await?
}
Commands::Build {
no_cache,
pull,
build_arg,
progress: _,
push,
quiet,
services,
} => {
let file = &profile_filtered(file, profile, &services);
engine
.build_all_with_options(
file,
&services,
&podup::BuildOptions {
no_cache,
pull,
build_args: build_arg,
quiet,
},
)
.await?;
if push {
engine
.push_with_quiet(file, &services, podup::PushOptions::default(), quiet)
.await?;
}
}
Commands::Rm {
force,
volumes,
stop,
services,
} => {
if stop {
engine.unpause(file, &services).await?;
engine.stop(file, &services).await?;
}
engine
.rm_with_options(file, &services, force, volumes)
.await?
}
Commands::Kill {
signal,
remove_orphans,
services,
} => {
let filtered = profile_filtered(file, profile, &services);
engine.kill(&filtered, &services, &signal).await?;
if remove_orphans {
engine.remove_orphans(file).await?;
}
}
Commands::Pause { services } => {
let file = &profile_filtered(file, profile, &services);
engine.pause(file, &services).await?
}
Commands::Unpause { services } => {
let file = &profile_filtered(file, profile, &services);
engine.unpause(file, &services).await?
}
Commands::Run {
service,
rm: _,
no_rm,
detach,
env_overrides,
name,
service_ports,
user: _,
workdir: _,
entrypoint: _,
volume: _,
publish: _,
interactive: _,
no_tty: _,
no_deps: _,
label: _,
cmd,
} => {
engine
.run(
file,
&service,
podup::RunOptions {
cmd,
rm: !no_rm,
detach,
env_overrides,
name_override: name,
service_ports,
},
)
.await?
}
Commands::Cp {
src,
dst,
index,
follow_link,
archive,
} => {
engine
.cp_with_options(
file,
&src,
&dst,
podup::CpOptions {
index,
follow_link,
archive,
},
)
.await?
}
Commands::Ps { .. } => unreachable!("handled before compose parsing"),
Commands::Top { format, services } => {
engine
.top_with_options(file, &services, format == OutputFormat::Json)
.await?
}
Commands::Events {
format,
since,
until,
filter,
json,
} => {
let json = json || format == EventsFormat::Json;
engine
.stream_events_with_options(
json,
&podup::EventsOptions {
since,
until,
filters: filter,
},
)
.await?
}
Commands::Attach {
service,
index,
no_stdin: _,
sig_proxy: _,
detach_keys: _,
} => engine.attach_with_index(file, &service, index).await?,
Commands::Wait { services } => {
let file = &profile_filtered(file, profile, &services);
engine.wait_services(file, &services).await?
}
Commands::Commit {
service,
image,
message,
author,
pause,
change,
index,
} => {
engine
.commit_with_options(
file,
&service,
&image,
index,
podup::CommitOptions {
message,
author,
pause: Some(pause),
changes: change,
},
)
.await?
}
Commands::Export {
service,
output,
index,
} => engine.export(file, &service, output, index).await?,
Commands::Stats {
no_stream,
all,
no_trunc,
format,
services,
} => {
let opts = StatsOptions::new(no_stream, all, no_trunc, format == OutputFormat::Json);
engine.stats_with_options(file, &services, opts).await?
}
Commands::Push {
ignore_push_failures,
tls_verify,
quiet,
services,
} => {
let file = &profile_filtered(file, profile, &services);
engine
.push_with_quiet(
file,
&services,
podup::PushOptions {
ignore_failures: ignore_push_failures,
tls_verify,
},
quiet,
)
.await?
}
Commands::Port {
service,
private_port,
proto,
index,
} => {
engine
.port_with_index(file, &service, &private_port, &proto, index)
.await?
}
Commands::Volumes {
quiet,
format,
services,
} => {
engine
.list_volumes(
file,
&services,
podup::VolumesOptions {
quiet,
json: format == OutputFormat::Json,
},
)
.await?
}
Commands::Images {
quiet,
format,
services,
} => {
let file = &profile_filtered(file, profile, &services);
engine
.images_with_services(
file,
&services,
podup::ImagesOptions {
quiet,
json: format == OutputFormat::Json,
},
)
.await?
}
Commands::Logs {
follow,
tail,
since,
until,
timestamps,
no_color,
no_log_prefix,
services,
} => {
engine
.logs_with_display(
file,
&services,
podup::LogsOptions {
follow,
tail,
since,
until,
timestamps,
},
podup::LogsDisplay {
no_color,
no_log_prefix,
},
)
.await?
}
Commands::Exec {
env,
user,
workdir,
privileged,
detach,
no_tty: _,
index,
service,
cmd,
} => {
engine
.exec_with_options(
file,
&service,
cmd,
podup::ExecOptions {
env,
user,
workdir,
privileged,
detach,
index,
},
)
.await?
}
Commands::Pull {
quiet: _,
ignore_pull_failures,
include_deps,
policy: _,
services,
} => {
let file = &profile_filtered(file, profile, &services);
engine
.pull_services_with_options(
file,
&services,
podup::PullOptions {
ignore_failures: ignore_pull_failures,
include_deps,
},
)
.await?
}
Commands::Restart {
timeout: _,
no_deps,
services,
} => {
let file = &profile_filtered(file, profile, &services);
engine
.restart_with_options(file, &services, no_deps)
.await?
}
Commands::Config { .. } => unreachable!("handled above"),
Commands::Generate { .. } => unreachable!("handled above"),
Commands::Watch => engine.watch(file).await?,
Commands::Help { .. } => unreachable!("handled before compose parsing"),
Commands::Ls { .. } => unreachable!("handled before compose parsing"),
#[cfg(feature = "update")]
Commands::Update { .. } => unreachable!("handled before compose parsing"),
#[cfg(feature = "completions")]
Commands::Completions { .. } => unreachable!("handled before compose parsing"),
}
Ok(())
}