forklaunch 1.18.0

Launch faster with forklaunch
use std::io::Write;

use anyhow::{Context, Result};
use clap::{Arg, ArgAction, ArgMatches, Command};
use serde_json::json;
use termcolor::{ColorChoice, StandardStream, WriteColor};

use crate::{
    CliCommand,
    core::command::command,
    managed::client::{
        Missing, post_text, print_dryrun, require_managed_mode, resolve_managed_auth,
    },
};

#[derive(Debug)]
pub(super) struct ResumeCommand;

impl ResumeCommand {
    pub(super) fn new() -> Self {
        Self
    }
}

impl CliCommand for ResumeCommand {
    fn command(&self) -> Command {
        command(
            "resume",
            "Re-queue a launch that failed or is holding for deployment approval",
        )
        .long_about(
            "Re-queue a launch that failed or is holding for deployment approval.\n\n\
             This is the LAUNCH retry: from provisioning_failed it re-enters provisioning and\n\
             re-runs the idempotent step list (nothing already created is created twice); for\n\
             a launch parked with launchApprovalState=pending it re-queues the deploy.\n\n\
             A reset that failed is retried with `instance reset`, not with this — the launch\n\
             path mints no claim link for an instance that is still claimed.",
        )
        .arg(
            Arg::new("id")
                .long("id")
                .required(true)
                .help("Id of the instance"),
        )
        .arg(
            Arg::new("dryrun")
                .long("dryrun")
                .help("Print the request that would be sent without sending it")
                .action(ArgAction::SetTrue),
        )
    }

    fn handler(&self, matches: &ArgMatches) -> Result<()> {
        let mut stdout = StandardStream::stdout(ColorChoice::Always);
        let id = matches
            .get_one::<String>("id")
            .context("--id is required")?;
        let path = format!("/instances/{}/resume-provisioning", urlencoding::encode(id));

        if matches.get_flag("dryrun") {
            return print_dryrun("POST", &path, Some(&json!({})));
        }

        let auth_mode = resolve_managed_auth()?;
        require_managed_mode(&auth_mode)?;

        let message = post_text(
            &path,
            json!({}),
            Missing::Resource(format!(
                "instance '{}' holding for approval or in provisioning_failed",
                id
            )),
        )?;

        log_ok!(stdout, "{}", message);
        log_info!(
            stdout,
            "Follow it with `forklaunch managed instance get --id {}`.",
            id
        );
        writeln!(stdout)?;
        Ok(())
    }
}