|
|
@@ -140,8 +140,18 @@ async fn main() -> Result<()> {
|
|
|
cluster,
|
|
|
node,
|
|
|
power_off,
|
|
|
+ no_wait,
|
|
|
} => {
|
|
|
- handle_stop(&config, &recipe_name, &cluster, &node, power_off, dry_run).await?;
|
|
|
+ handle_stop(
|
|
|
+ &config,
|
|
|
+ &recipe_name,
|
|
|
+ &cluster,
|
|
|
+ &node,
|
|
|
+ !no_wait,
|
|
|
+ power_off,
|
|
|
+ dry_run,
|
|
|
+ )
|
|
|
+ .await?;
|
|
|
}
|
|
|
Commands::Health {
|
|
|
cluster: cluster_name,
|
|
|
@@ -325,21 +335,19 @@ async fn handle_logs(
|
|
|
.await?;
|
|
|
Ok(())
|
|
|
}
|
|
|
-
|
|
|
/// Handle `stop` command: stop containers and optionally power off.
|
|
|
pub(crate) async fn handle_stop(
|
|
|
config: &Config,
|
|
|
recipe_name: &str,
|
|
|
cluster: &str,
|
|
|
node: &[String],
|
|
|
+ wait: bool,
|
|
|
power_off: bool,
|
|
|
dry_run: bool,
|
|
|
) -> Result<()> {
|
|
|
- let (stopped_cluster, stopped_nodes): (Cluster, Vec<String>) = if !node.is_empty() {
|
|
|
- let cluster = resolve_cluster_for_op(config, recipe_name, cluster).await?;
|
|
|
- let nodes = node.to_vec();
|
|
|
- docker::stop_cluster(config, &cluster, recipe_name, &nodes, dry_run).await?;
|
|
|
- (cluster, nodes)
|
|
|
+ let (cluster, nodes): (Cluster, Vec<String>) = if !node.is_empty() {
|
|
|
+ let c = resolve_cluster_for_op(config, recipe_name, cluster).await?;
|
|
|
+ (c, node.to_vec())
|
|
|
} else {
|
|
|
let variants = docker::deploy::discover_recipe_deployments(config, recipe_name).await?;
|
|
|
if variants.is_empty() {
|
|
|
@@ -347,42 +355,26 @@ pub(crate) async fn handle_stop(
|
|
|
}
|
|
|
if variants.len() == 1 {
|
|
|
let v = &variants[0];
|
|
|
- let cluster = select_cluster_by_name(config, &v.cluster)?;
|
|
|
- let nodes = v.nodes.clone();
|
|
|
- docker::stop_cluster(config, &cluster, recipe_name, &nodes, dry_run).await?;
|
|
|
- (cluster, nodes)
|
|
|
+ let c = select_cluster_by_name(config, &v.cluster)?;
|
|
|
+ (c, v.nodes.clone())
|
|
|
} else {
|
|
|
- let mut msg = format!(
|
|
|
- "Multiple deployments of '{}' found — use --node to select:\n",
|
|
|
- recipe_name
|
|
|
- );
|
|
|
- for (i, v) in variants.iter().enumerate() {
|
|
|
- let nodes = v
|
|
|
- .nodes
|
|
|
- .iter()
|
|
|
- .map(|n| format!("--node {}", n))
|
|
|
- .collect::<Vec<_>>()
|
|
|
- .join(" ");
|
|
|
- msg.push_str(&format!(
|
|
|
- " {}: cluster '{}' with {}\n",
|
|
|
- i + 1,
|
|
|
- v.cluster,
|
|
|
- nodes
|
|
|
- ));
|
|
|
- }
|
|
|
- anyhow::bail!(msg);
|
|
|
+ anyhow::bail!(docker::deploy::multi_deployment_error(
|
|
|
+ recipe_name,
|
|
|
+ &variants
|
|
|
+ ));
|
|
|
}
|
|
|
};
|
|
|
+ docker::stop_cluster(config, &cluster, recipe_name, &nodes, wait, dry_run).await?;
|
|
|
|
|
|
// Run recipe `after_stop` hooks (e.g. restore_dgx_services) on the
|
|
|
// nodes that were actually stopped. Best-effort against the loaded
|
|
|
// recipe; if the recipe file is unavailable, skip silently.
|
|
|
if let Ok(recipe) = crate::config::load_recipe(recipe_name, &config.recipe_sources).await {
|
|
|
- crate::after_stop::run(config, &stopped_cluster, &recipe, dry_run).await?;
|
|
|
+ crate::after_stop::run(config, &cluster, &recipe, dry_run).await?;
|
|
|
}
|
|
|
|
|
|
if power_off {
|
|
|
- crate::power::power_off(config, &stopped_cluster, &stopped_nodes, dry_run).await?;
|
|
|
+ crate::power::power_off(config, &cluster, &nodes, dry_run).await?;
|
|
|
}
|
|
|
Ok(())
|
|
|
}
|