From 1ecb2048b6c60c3a8439d8c7ee9e8b192d370800 Mon Sep 17 00:00:00 2001 From: gonzalezzfelipe Date: Mon, 3 Feb 2025 15:44:03 -0300 Subject: [PATCH 1/2] chore: Support JSON output --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/ports/format.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++- src/ports/list.rs | 14 ++++++--- src/ports/mod.rs | 2 +- src/ports/show.rs | 14 +++++++-- 6 files changed, 100 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8510092..cf442cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -566,7 +566,7 @@ dependencies = [ [[package]] name = "dmtrctl" -version = "2.0.1" +version = "2.1.0" dependencies = [ "base64 0.22.1", "clap", diff --git a/Cargo.toml b/Cargo.toml index 4aa1471..df7206b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dmtrctl" -version = "2.0.2" +version = "2.1.0" edition = "2021" repository = "https://github.com/demeter-run/cli" license = "Apache-2.0" diff --git a/src/ports/format.rs b/src/ports/format.rs index 9fd4556..6fe0396 100644 --- a/src/ports/format.rs +++ b/src/ports/format.rs @@ -3,6 +3,15 @@ use comfy_table::presets::UTF8_FULL; use comfy_table::{ContentArrangement, Table}; use dmtri::demeter::ops::v1alpha::Resource; use miette::IntoDiagnostic; +use serde::Serialize; + +#[derive(clap::ValueEnum, Clone, Default, Debug, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum OutputFormat { + #[default] + Table, + Json, +} pub fn pretty_print_resource_table(resources: Vec) { let mut table = Table::new(); @@ -26,7 +35,72 @@ pub fn pretty_print_resource_table(resources: Vec) { println!("{table}"); } -pub fn pretty_print_resouce_detail_table(resources: Vec) -> miette::Result<()> { +pub fn pretty_print_resource_json(resources: Vec) { + let mut collector = vec![]; + for resource in resources { + collector.push(serde_json::Map::from_iter(vec![ + ("id".to_string(), serde_json::Value::from(resource.id)), + ("name".to_string(), serde_json::Value::from(resource.name)), + ("kind".to_string(), serde_json::Value::from(resource.kind)), + ( + "created_at".to_string(), + serde_json::Value::from(resource.created_at), + ), + ( + "spec".to_string(), + serde_json::from_str::(&resource.spec).unwrap(), + ), + ( + "annotations".to_string(), + serde_json::from_str::( + &resource.annotations.unwrap_or_default(), + ) + .unwrap(), + ), + ])) + } + println!("{}", serde_json::to_string_pretty(&collector).unwrap()); +} + +pub fn pretty_print_resource_detail_json(resource: &Resource) { + println!( + "{}", + serde_json::to_string_pretty( + &(serde_json::Map::from_iter(vec![ + ( + "id".to_string(), + serde_json::Value::from(resource.id.clone()) + ), + ( + "name".to_string(), + serde_json::Value::from(resource.name.clone()) + ), + ( + "kind".to_string(), + serde_json::Value::from(resource.kind.clone()) + ), + ( + "created_at".to_string(), + serde_json::Value::from(resource.created_at.clone()), + ), + ( + "spec".to_string(), + serde_json::from_str::(&resource.spec).unwrap(), + ), + ( + "annotations".to_string(), + serde_json::from_str::( + &resource.annotations.clone().unwrap_or_default(), + ) + .unwrap(), + ), + ])) + ) + .unwrap() + ); +} + +pub fn pretty_print_resource_detail_table(resources: Vec) -> miette::Result<()> { let mut table = Table::new(); let Some(first_resource) = resources.first() else { diff --git a/src/ports/list.rs b/src/ports/list.rs index 20fac9a..dea1155 100644 --- a/src/ports/list.rs +++ b/src/ports/list.rs @@ -5,12 +5,15 @@ use crate::{ rpc::{self}, }; -use super::format::pretty_print_resource_table; +use super::format::{pretty_print_resource_table, pretty_print_resource_json, OutputFormat}; #[derive(Parser)] -pub struct Args {} +pub struct Args { + #[clap(short, long, default_value_t, value_enum)] + pub output: OutputFormat, +} -pub async fn run(cli: &crate::Cli) -> miette::Result<()> { +pub async fn run(args: Args, cli: &crate::Cli) -> miette::Result<()> { let _ctx = cli .context .as_ref() @@ -24,7 +27,10 @@ pub async fn run(cli: &crate::Cli) -> miette::Result<()> { return Ok(()); } - pretty_print_resource_table(response); + match args.output { + OutputFormat::Json => pretty_print_resource_json(response), + OutputFormat::Table => pretty_print_resource_table(response), + } Ok(()) } diff --git a/src/ports/mod.rs b/src/ports/mod.rs index c0b1751..97d74ab 100644 --- a/src/ports/mod.rs +++ b/src/ports/mod.rs @@ -32,7 +32,7 @@ pub enum Commands { pub async fn run(args: Args, cli: &crate::Cli) -> miette::Result<()> { match args.command { - Commands::List(_) => list::run(cli).await, + Commands::List(x) => list::run(x, cli).await, Commands::Show(x) => show::run(x, cli).await, Commands::Create(x) => create::run(x, cli).await, Commands::Delete(x) => delete::run(x, cli).await, diff --git a/src/ports/show.rs b/src/ports/show.rs index 35c2abe..6070870 100644 --- a/src/ports/show.rs +++ b/src/ports/show.rs @@ -2,12 +2,15 @@ use clap::Parser; use crate::{context::extract_context_data, rpc}; -use super::format::pretty_print_resouce_detail_table; +use super::format::{pretty_print_resource_detail_table, pretty_print_resource_detail_json, OutputFormat}; #[derive(Parser)] pub struct Args { /// the resource uuid id: String, + + #[clap(short, long, default_value_t, value_enum)] + pub output: OutputFormat, } pub async fn run(args: Args, cli: &crate::Cli) -> miette::Result<()> { @@ -24,6 +27,13 @@ pub async fn run(args: Args, cli: &crate::Cli) -> miette::Result<()> { return Ok(()); } - pretty_print_resouce_detail_table(resouces)?; + match args.output { + OutputFormat::Json => { + let response = resouces.first().unwrap(); + pretty_print_resource_detail_json(response) + }, + OutputFormat::Table => pretty_print_resource_detail_table(resouces)?, + } + Ok(()) } From c85f34430bd19a34cf494b96d983e234c1e7306b Mon Sep 17 00:00:00 2001 From: gonzalezzfelipe Date: Tue, 4 Feb 2025 10:38:53 -0300 Subject: [PATCH 2/2] Improve output format --- src/ports/format.rs | 64 +++++++++++++++++++++++++-------------------- src/ports/list.rs | 10 +++---- src/ports/show.rs | 12 +++------ 3 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/ports/format.rs b/src/ports/format.rs index 6fe0396..35cfbd2 100644 --- a/src/ports/format.rs +++ b/src/ports/format.rs @@ -13,6 +13,22 @@ pub enum OutputFormat { Json, } +impl OutputFormat { + pub fn pretty_print(&self, resources: Vec) { + match self { + OutputFormat::Table => pretty_print_resource_table(resources), + OutputFormat::Json => pretty_print_resource_json(resources), + } + } + + pub fn pretty_print_single(&self, resource: &Resource) { + match self { + OutputFormat::Table => pretty_print_resource_detail_table(resource), + OutputFormat::Json => pretty_print_resource_detail_json(resource), + } + } +} + pub fn pretty_print_resource_table(resources: Vec) { let mut table = Table::new(); @@ -100,17 +116,13 @@ pub fn pretty_print_resource_detail_json(resource: &Resource) { ); } -pub fn pretty_print_resource_detail_table(resources: Vec) -> miette::Result<()> { +pub fn pretty_print_resource_detail_table(resource: &Resource) { let mut table = Table::new(); - let Some(first_resource) = resources.first() else { - return Ok(()); - }; - let annotations = serde_json::from_str::( - &first_resource.annotations.clone().unwrap_or_default(), + &resource.annotations.clone().unwrap_or_default(), ) - .into_diagnostic()?; + .unwrap(); let mut annotations_headers: Vec = annotations .as_array() .unwrap() @@ -127,29 +139,25 @@ pub fn pretty_print_resource_detail_table(resources: Vec) -> miette::R .set_content_arrangement(ContentArrangement::Dynamic) .set_header(headers); - for resource in resources { - let mut values: Vec = vec![resource.name]; - - if let Some(annotations) = resource.annotations { - let annotations: serde_json::Value = - serde_json::from_str(&annotations).into_diagnostic()?; - - for value in annotations.as_array().unwrap().iter() { - values.push( - value - .get("value") - .unwrap() - .as_str() - .unwrap_or_default() - .into(), - ); - } + let mut values: Vec = vec![resource.name.clone()]; + + if let Some(annotations) = &resource.annotations { + let annotations: serde_json::Value = + serde_json::from_str(annotations).into_diagnostic().unwrap(); + + for value in annotations.as_array().unwrap().iter() { + values.push( + value + .get("value") + .unwrap() + .as_str() + .unwrap_or_default() + .into(), + ); } - - table.add_row(values); } - println!("{table}"); + table.add_row(values); - Ok(()) + println!("{table}"); } diff --git a/src/ports/list.rs b/src/ports/list.rs index dea1155..b49a8d2 100644 --- a/src/ports/list.rs +++ b/src/ports/list.rs @@ -2,10 +2,10 @@ use clap::Parser; use crate::{ context::extract_context_data, - rpc::{self}, + rpc, }; -use super::format::{pretty_print_resource_table, pretty_print_resource_json, OutputFormat}; +use super::format::OutputFormat; #[derive(Parser)] pub struct Args { @@ -27,10 +27,6 @@ pub async fn run(args: Args, cli: &crate::Cli) -> miette::Result<()> { return Ok(()); } - match args.output { - OutputFormat::Json => pretty_print_resource_json(response), - OutputFormat::Table => pretty_print_resource_table(response), - } - + args.output.pretty_print(response); Ok(()) } diff --git a/src/ports/show.rs b/src/ports/show.rs index 6070870..c2cefee 100644 --- a/src/ports/show.rs +++ b/src/ports/show.rs @@ -2,7 +2,7 @@ use clap::Parser; use crate::{context::extract_context_data, rpc}; -use super::format::{pretty_print_resource_detail_table, pretty_print_resource_detail_json, OutputFormat}; +use super::format::OutputFormat; #[derive(Parser)] pub struct Args { @@ -27,13 +27,7 @@ pub async fn run(args: Args, cli: &crate::Cli) -> miette::Result<()> { return Ok(()); } - match args.output { - OutputFormat::Json => { - let response = resouces.first().unwrap(); - pretty_print_resource_detail_json(response) - }, - OutputFormat::Table => pretty_print_resource_detail_table(resouces)?, - } - + let response = resouces.first().unwrap(); + args.output.pretty_print_single(response); Ok(()) }