use core::fmt::Write;
use clap::builder::NonEmptyStringValueParser;
use clap::{Args, Subcommand};
use miette::{miette, IntoDiagnostic};
use ockam::Context;
use ockam_api::cloud::subscription::{Subscription, Subscriptions};
use ockam_api::cloud::ControllerClient;
use ockam_api::nodes::InMemoryNode;
use crate::output::Output;
use crate::util::api::CloudOpts;
use crate::util::async_cmd;
use crate::{docs, CommandGlobalOpts, Result};
#[derive(Clone, Debug, Args)]
#[command(hide = docs::hide())]
pub struct SubscriptionCommand {
#[command(subcommand)]
subcommand: SubscriptionSubcommand,
#[command(flatten)]
cloud_opts: CloudOpts,
}
#[derive(Clone, Debug, Subcommand)]
pub enum SubscriptionSubcommand {
#[command(arg_required_else_help = true)]
Show {
#[arg(group = "id")]
subscription_id: Option<String>,
#[arg(
group = "id",
id = "space",
value_name = "SPACE_ID",
long,
value_parser(NonEmptyStringValueParser::new())
)]
space_id: Option<String>,
},
}
impl SubscriptionCommand {
pub fn run(self, opts: CommandGlobalOpts) -> miette::Result<()> {
async_cmd(&self.name(), opts.clone(), |ctx| async move {
self.async_run(&ctx, opts).await
})
}
pub fn name(&self) -> String {
match &self.subcommand {
SubscriptionSubcommand::Show { .. } => "show subscription",
}
.to_string()
}
async fn async_run(&self, ctx: &Context, opts: CommandGlobalOpts) -> miette::Result<()> {
let node = InMemoryNode::start(ctx, &opts.state).await?;
let controller = node.create_controller().await?;
match &self.subcommand {
SubscriptionSubcommand::Show {
subscription_id,
space_id,
} => {
match get_subscription_by_id_or_space_id(
&controller,
ctx,
subscription_id.clone(),
space_id.clone(),
)
.await?
{
Some(subscription) => opts.terminal.write_line(&subscription.output()?)?,
None => opts
.terminal
.write_line("Please specify either a space id or a subscription id")?,
}
}
};
Ok(())
}
}
pub(crate) async fn get_subscription_by_id_or_space_id(
controller: &ControllerClient,
ctx: &Context,
subscription_id: Option<String>,
space_id: Option<String>,
) -> Result<Option<Subscription>> {
match (subscription_id, space_id) {
(Some(subscription_id), _) => Ok(Some(
controller
.get_subscription(ctx, subscription_id.clone())
.await
.and_then(|s| s.found())
.into_diagnostic()?
.ok_or_else(|| {
miette!(
"no subscription found for subscription id {}",
subscription_id
)
})?,
)),
(None, Some(space_id)) => Ok(Some(
controller
.get_subscription_by_space_id(ctx, space_id.clone())
.await
.and_then(|s| s.found())
.into_diagnostic()?
.ok_or_else(|| miette!("no subscription found for space {}", space_id))?,
)),
_ => Ok(None),
}
}
impl Output for Subscription {
fn output(&self) -> Result<String> {
let mut w = String::new();
write!(w, "Subscription")?;
write!(w, "\n Id: {}", self.id)?;
write!(w, "\n Status: {}", self.status)?;
write!(
w,
"\n Space id: {}",
self.space_id.clone().unwrap_or("N/A".to_string())
)?;
write!(w, "\n Entitlements: {}", self.entitlements)?;
write!(w, "\n Metadata: {}", self.metadata)?;
write!(w, "\n Contact info: {}", self.contact_info)?;
Ok(w)
}
}