use clap::Parser;
use color_eyre::eyre;
use color_eyre::owo_colors::OwoColorize;
use dialoguer::console::Term;
use futures::TryStreamExt;
use time::format_description::well_known::Rfc2822;
use chris::errors::CubeError;
use chris::{
Access, EitherClient, Pipeline, PipelineRw, Plugin, PluginParameter, PluginResponse, PluginRw,
};
use crate::arg::{GivenRunnable, Runnable};
use crate::credentials::Credentials;
use crate::login::{UiUrl, UiUrlRef};
use crate::plugin_clap::clap_params;
#[derive(Parser)]
pub struct DescribeArgs {
plugin_or_pipeline: GivenRunnable,
}
pub async fn describe_runnable(credentials: Credentials, args: DescribeArgs) -> eyre::Result<()> {
let (client, _, ui) = credentials
.get_client([args.plugin_or_pipeline.as_arg_str()])
.await?;
match &client {
EitherClient::Anon(c) => match args.plugin_or_pipeline.resolve_using(c).await? {
Runnable::Plugin(p) => describe_plugin_ro(&p, ui).await,
Runnable::Pipeline(p) => describe_pipeline_ro(&p, ui).await,
},
EitherClient::LoggedIn(c) => match args.plugin_or_pipeline.resolve_using(c).await? {
Runnable::Plugin(p) => describe_plugin_rw(&p, ui).await,
Runnable::Pipeline(p) => {
describe_pipeline_ro(&p, ui).await?;
println!();
print_pipeline_workflow_counts(&p).await
}
},
}
}
fn print_plugin_title(plugin: &PluginResponse, ui: Option<&UiUrlRef>) {
let id_part = format!("(plugin/{})", plugin.id.0);
println!(
"{}: {} {}",
plugin.name.bold().underline().magenta(),
plugin.title,
id_part.dimmed(),
);
if let Some(ui) = ui {
println!("{}/plugin/{}", ui, plugin.id.0)
}
}
fn get_plugin_attributes(plugin: &PluginResponse) -> Vec<(&'static str, &str)> {
let mut attributes = vec![
("Version", plugin.version.as_str()),
("Image", plugin.dock_image.as_str()),
("License", plugin.license.as_str()),
("Code", plugin.public_repo.as_str()),
];
if plugin.documentation != plugin.public_repo.as_str() {
attributes.push(("Documentation", plugin.documentation.as_str()));
}
attributes
}
async fn describe_plugin_ro<A: Access>(plugin: &Plugin<A>, ui: Option<UiUrl>) -> eyre::Result<()> {
print_plugin_title(&plugin.object, ui.as_deref());
println!();
for (name, val) in get_plugin_attributes(&plugin.object) {
println!("{:>16}: {}", name, val)
}
println!();
let params = get_parameters(plugin).await?;
clap_params(&plugin.object.selfexec, ¶ms).print_help()?;
Ok(())
}
async fn describe_plugin_rw(plugin: &PluginRw, ui: Option<UiUrl>) -> eyre::Result<()> {
print_plugin_title(&plugin.object, ui.as_deref());
println!();
let mut attributes = get_plugin_attributes(&plugin.object);
let cr_names = compute_resources_of(plugin).await?;
attributes.push(("Compute Resources", &cr_names));
for (name, val) in attributes {
println!("{:>20}: {}", name, val)
}
println!();
let params = get_parameters(plugin).await?;
clap_params(&plugin.object.selfexec, ¶ms).print_help()?;
Ok(())
}
async fn get_parameters<A: Access>(plugin: &Plugin<A>) -> Result<Vec<PluginParameter>, CubeError> {
plugin.parameters().stream().try_collect().await
}
async fn compute_resources_of(plugin: &PluginRw) -> Result<String, CubeError> {
plugin
.compute_resources()
.stream()
.map_ok(|c| c.name)
.try_collect::<Vec<_>>()
.await
.map(|v| v.join(", "))
}
async fn describe_pipeline_ro<A: Access>(
pipeline: &Pipeline<A>,
_ui: Option<UiUrl>,
) -> eyre::Result<()> {
let id_part = format!("(pipeline/{})", pipeline.object.id.0);
println!(
"{} {}",
pipeline.object.name.bold().underline().bright_magenta(),
id_part.dimmed()
);
println!(" Category: {}", pipeline.object.category.bold());
println!(" Authors: {}", pipeline.object.authors);
println!(
" Created: {}",
pipeline.object.creation_date.format(&Rfc2822)?
);
println!();
let term_cols = std::cmp::min(Term::stdout().size().1, 120) as usize;
for line in textwrap::wrap(pipeline.object.description.as_str(), term_cols) {
println!("{}", line)
}
Ok(())
}
async fn print_pipeline_workflow_counts(pipeline: &PipelineRw) -> eyre::Result<()> {
let count = pipeline.get_workflows().get_count().await?;
if count == 1 {
println!("Pipeline was used {} time", 1.bold().bright_cyan());
} else {
println!("Pipeline was used {} times", count.bold().bright_cyan());
}
Ok(())
}