boh 0.1.1

A holder of many things
Documentation
use anyhow::Context as _;

#[derive(clap::Subcommand)]
pub enum Subcommand {
    Restart { resource: String },
}

#[derive(clap::Parser)]
pub struct Args {
    #[clap(subcommand)]
    cmd: Subcommand,
}

fn parse_resource(resource: &str) -> anyhow::Result<(&str, &str)> {
    let ind = resource
        .find('/')
        .context("resource must be specified as <kind>/<name>")?;

    let kind = match &resource[..ind] {
        "deployment" => "deployments",
        other => anyhow::bail!("unknown resource kind '{other}'"),
    };

    anyhow::ensure!(
        ind + 1 < resource.len(),
        "the resource name was not provided"
    );

    Ok((kind, &resource[ind + 1..]))
}

pub(super) async fn run(client: super::K8sClient, args: Args) -> anyhow::Result<()> {
    match args.cmd {
        Subcommand::Restart { resource } => {
            let patch = serde_json::json!({
              "spec": {
                "template": {
                  "metadata": {
                    "annotations": {
                      "boh.kubernetes.io/restartedAt": time::OffsetDateTime::now_utc().format(&time::format_description::well_known::Rfc3339).context("failed to format timestamp")?,
                    }
                  }
                }
              }
            });

            let (kind, name) = parse_resource(&resource)?;

            let url = client.make_url(kind, name);

            let res = client
                .client
                .patch(url)
                .header(http::header::ACCEPT, "application/json")
                .header(http::header::CONTENT_TYPE, "application/merge-patch+json")
                .body(serde_json::to_vec(&patch).context("failed to write serialize json patch")?)
                .send()
                .await?;

            let code = res.status();
            let body = res.bytes().await?;

            if !code.is_success() {
                if let Ok(err_str) = String::from_utf8(body.into()) {
                    anyhow::bail!(err_str);
                } else {
                    anyhow::bail!("failed to retrieve error for {code}");
                }
            }

            use std::io::Write;
            let _ = std::io::stdout().write(&body);
        }
    }

    Ok(())
}