Skip to content

Commit

Permalink
feat(topology): add show-label flag in get pools/pool
Browse files Browse the repository at this point in the history
Signed-off-by: sinhaashish <[email protected]>
  • Loading branch information
sinhaashish committed Sep 6, 2024
1 parent 423dab2 commit 6f7d5ce
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 13 deletions.
4 changes: 3 additions & 1 deletion control-plane/plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ impl ExecuteOperation for GetResources {
volume::Volume::topology(id, &cli_args.output).await
}
GetResources::Pools(args) => pool::Pools::list(args, &cli_args.output).await,
GetResources::Pool { id } => pool::Pool::get(id, &cli_args.output).await,
GetResources::Pool(args) => {
pool::Pool::get(&args.pool_id(), args, &cli_args.output).await
}
GetResources::Nodes(args) => node::Nodes::list(args, &cli_args.output).await,
GetResources::Node(args) => {
node::Node::get(&args.node_id(), args, &cli_args.output).await
Expand Down
4 changes: 2 additions & 2 deletions control-plane/plugin/src/resources/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::resources::{
blockdevice::BlockDeviceArgs,
node::{DrainNodeArgs, GetNodeArgs, GetNodesArgs},
pool::GetPoolsArgs,
pool::{GetPoolArgs, GetPoolsArgs},
snapshot::VolumeSnapshotArgs,
volume::VolumesArgs,
};
Expand Down Expand Up @@ -51,7 +51,7 @@ pub enum GetResources {
/// Get all pools.
Pools(GetPoolsArgs),
/// Get pool with the given ID.
Pool { id: PoolId },
Pool(GetPoolArgs),
/// Get all nodes.
Nodes(GetNodesArgs),
/// Get node with the given ID.
Expand Down
149 changes: 139 additions & 10 deletions control-plane/plugin/src/resources/pool.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
extern crate utils as external_utils;
use crate::{
operations::{Get, Label, ListWithArgs, PluginResult},
operations::{GetWithArgs, Label, ListWithArgs, PluginResult},
resources::{
error::{Error, LabelAssignSnafu, OpError, TopologyError},
utils,
utils::{
optional_cell, print_table, validate_topology_key, validate_topology_value, CreateRow,
GetHeaderRow, OutputFormat,
CreateRows, GetHeaderRow, OutputFormat,
},
NodeId, PoolId,
},
rest_wrapper::RestClient,
};

use async_trait::async_trait;
use openapi::apis::StatusCode;
use prettytable::Row;
use prettytable::{Cell, Row};
use serde::Serialize;
use snafu::ResultExt;
use std::collections::HashMap;

Expand Down Expand Up @@ -68,6 +71,27 @@ impl GetHeaderRow for openapi::models::Pool {
}
}

/// Arguments used when getting a pool.
#[derive(Debug, Clone, clap::Args)]
pub struct GetPoolArgs {
/// Id of the pool.
pool_id: PoolId,
/// Show the labels of the pool.
#[clap(long, default_value = "false")]
show_labels: bool,
}

impl GetPoolArgs {
/// Return the pool ID.
pub fn pool_id(&self) -> PoolId {
self.pool_id.clone()
}
/// Return whether to show the labels of the pool.
pub fn show_labels(&self) -> bool {
self.show_labels
}
}

/// Arguments used when getting pools.
#[derive(Debug, Clone, clap::Args)]
pub struct GetPoolsArgs {
Expand All @@ -84,6 +108,10 @@ pub struct GetPoolsArgs {
/// Pools must satisfy all of the specified label constraints.
#[clap(short = 'l', long)]
selector: Option<String>,

/// Show the labels of the pool.
#[clap(long, default_value = "false")]
show_labels: bool,
}

impl GetPoolsArgs {
Expand All @@ -101,6 +129,11 @@ impl GetPoolsArgs {
pub fn selector(&self) -> &Option<String> {
&self.selector
}

/// Return whether to show the labels of the pool.
pub fn show_labels(&self) -> bool {
self.show_labels
}
}

#[async_trait(?Send)]
Expand Down Expand Up @@ -133,7 +166,17 @@ impl ListWithArgs for Pools {
},
None => true,
});
utils::print_table(output, pools);

let pools_display = PoolDisplay::new_pools(pools.clone(), args.show_labels());
match output {
OutputFormat::Yaml | OutputFormat::Json => {
print_table(output, pools_display.inner);
}
OutputFormat::None => {
print_table(output, pools_display);
}
}

Ok(())
}
}
Expand All @@ -143,14 +186,22 @@ impl ListWithArgs for Pools {
pub struct Pool {}

#[async_trait(?Send)]
impl Get for Pool {
impl GetWithArgs for Pool {
type ID = PoolId;
async fn get(id: &Self::ID, output: &utils::OutputFormat) -> PluginResult {
type Args = GetPoolArgs;
async fn get(id: &Self::ID, args: &Self::Args, output: &utils::OutputFormat) -> PluginResult {
match RestClient::client().pools_api().get_pool(id).await {
Ok(pool) => {
// Print table, json or yaml based on output format.
utils::print_table(output, pool.into_body());
}
Ok(pool) => match output {
OutputFormat::Yaml | OutputFormat::Json => {
print_table(output, pool.clone().into_body());
}
OutputFormat::None => {
print_table(
output,
PoolDisplay::new(pool.into_body(), args.show_labels()),
);
}
},
Err(e) => {
return Err(Error::GetPoolError {
id: id.to_string(),
Expand Down Expand Up @@ -279,3 +330,81 @@ impl Label for Pool {
Ok(())
}
}

/// The PoolDisplay structure is responsible for controlling the display formatting of Pool
/// objects. `#[serde(flatten)]` and `#[serde(skip)]` attributes are used to ensure that when the
/// object is serialised, only the `inner` object is represented.
#[derive(Serialize, Debug)]
pub struct PoolDisplay {
#[serde(flatten)]
pub inner: Vec<openapi::models::Pool>,
#[serde(skip)]
show_labels: bool,
}

impl PoolDisplay {
/// Create a new `PoolDisplay` instance.
pub(crate) fn new(pool: openapi::models::Pool, show_labels: bool) -> Self {
let vec: Vec<openapi::models::Pool> = vec![pool];
Self {
inner: vec,
show_labels,
}
}
/// Create a new `PoolDisplay` instance from a vector of pools.
pub(crate) fn new_pools(pools: Vec<openapi::models::Pool>, show_labels: bool) -> Self {
Self {
inner: pools,
show_labels,
}
}

/// Get a list of pool labels.
pub(crate) fn pool_label_list(pool: &openapi::models::Pool) -> Vec<String> {
let mut pools_labels: Vec<String> = vec![];
let internal_label = external_utils::dsp_created_by_key();

match &pool.spec {
Some(spec) => match &spec.labels {
Some(ds) => {
pools_labels = ds
.iter()
// Dont return the created_by_dsp label for the gets
.filter(|(key, _)| *key != &internal_label)
.map(|(key, value)| format!("{}={}", key, value))
.collect();
}
None => {}
},
None => {}
}
pools_labels
}
}

// Create the header for a `PoolDisplay` object.
impl GetHeaderRow for PoolDisplay {
fn get_header_row(&self) -> Row {
let mut header = (*utils::POOLS_HEADERS).clone();
if self.show_labels {
header.extend(vec!["LABELS"]);
}
header
}
}

impl CreateRows for PoolDisplay {
fn create_rows(&self) -> Vec<Row> {
let mut rows = vec![];
for pool in self.inner.iter() {
let mut row = pool.row();
if self.show_labels {
let labelstring = PoolDisplay::pool_label_list(pool).join(", ");
// Add the pool labels to each row.
row.add_cell(Cell::new(&labelstring));
}
rows.push(row);
}
rows
}
}

0 comments on commit 6f7d5ce

Please sign in to comment.