Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(topology): add show labels in pools #855

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
}