Skip to content

Commit

Permalink
fix(kubectl-plugin): non-zero exit code on error
Browse files Browse the repository at this point in the history
Signed-off-by: Vandana Varakantham <vandana.varakantham@datacore.com>
  • Loading branch information
datacore-vvarakantham committed Dec 6, 2023
1 parent baa101c commit 4ba2a71
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 75 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions control-plane/plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ serde_json = "1.0.107"
serde_yaml = "0.9.25"
humantime = "2.1.0"
chrono = "0.4.31"
snafu = "0.7.5"

[dev-dependencies]
# Test dependencies
Expand Down
7 changes: 6 additions & 1 deletion control-plane/plugin/src/bin/rest-plugin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async fn execute(cli_args: CliArgs) {
}

// Perform the operations based on the subcommand, with proper output format.
match &cli_args.operations {
let result = match &cli_args.operations {
Operations::Drain(resource) => match resource {
DrainResources::Node(drain_node_args) => {
node::Node::drain(
Expand Down Expand Up @@ -133,4 +133,9 @@ async fn execute(cli_args: CliArgs) {
}
},
};

let _ = result.map_err(|error| {
eprintln!("{error}");
std::process::exit(1);
});
}
36 changes: 23 additions & 13 deletions control-plane/plugin/src/operations.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use crate::resources::{utils, CordonResources, DrainResources, GetResources, ScaleResources};
use crate::resources::{
error::Error, utils, CordonResources, DrainResources, GetResources, ScaleResources,
};
use async_trait::async_trait;

/// Result wrapper for kubectl commands.
pub type KubectlResult = Result<(), Error>;

/// The types of operations that are supported.
#[derive(clap::Subcommand, Debug)]
pub enum Operations {
Expand Down Expand Up @@ -31,38 +36,39 @@ pub trait Drain {
label: String,
drain_timeout: Option<humantime::Duration>,
output: &utils::OutputFormat,
);
) -> KubectlResult;
}

/// List trait.
/// To be implemented by resources which support the 'list' operation.
#[async_trait(?Send)]
pub trait List {
async fn list(output: &utils::OutputFormat);
async fn list(output: &utils::OutputFormat) -> KubectlResult;
}

/// List trait.
/// To be implemented by resources which support the 'list' operation, with context.
#[async_trait(?Send)]
pub trait ListExt {
type Context;
async fn list(output: &utils::OutputFormat, context: &Self::Context);
async fn list(output: &utils::OutputFormat, context: &Self::Context) -> KubectlResult;
}

/// Get trait.
/// To be implemented by resources which support the 'get' operation.
#[async_trait(?Send)]
pub trait Get {
type ID;
async fn get(id: &Self::ID, output: &utils::OutputFormat);
async fn get(id: &Self::ID, output: &utils::OutputFormat) -> KubectlResult;
}

/// Scale trait.
/// To be implemented by resources which support the 'scale' operation.
#[async_trait(?Send)]
pub trait Scale {
type ID;
async fn scale(id: &Self::ID, replica_count: u8, output: &utils::OutputFormat);
async fn scale(id: &Self::ID, replica_count: u8, output: &utils::OutputFormat)
-> KubectlResult;
}

/// Replica topology trait.
Expand All @@ -71,24 +77,28 @@ pub trait Scale {
pub trait ReplicaTopology {
type ID;
type Context;
async fn topologies(output: &utils::OutputFormat, context: &Self::Context);
async fn topology(id: &Self::ID, output: &utils::OutputFormat);
async fn topologies(output: &utils::OutputFormat, context: &Self::Context) -> KubectlResult;
async fn topology(id: &Self::ID, output: &utils::OutputFormat) -> KubectlResult;
}

/// Rebuild trait.
/// To be implemented by resources which support the 'rebuild-history' operation
#[async_trait(?Send)]
pub trait RebuildHistory {
type ID;
async fn rebuild_history(id: &Self::ID, output: &utils::OutputFormat);
async fn rebuild_history(id: &Self::ID, output: &utils::OutputFormat) -> KubectlResult;
}

/// GetBlockDevices trait.
/// To be implemented by resources which support the 'get block-devices' operation
#[async_trait(?Send)]
pub trait GetBlockDevices {
type ID;
async fn get_blockdevices(id: &Self::ID, all: &bool, output: &utils::OutputFormat);
async fn get_blockdevices(
id: &Self::ID,
all: &bool,
output: &utils::OutputFormat,
) -> KubectlResult;
}

/// GetSnapshots trait.
Expand All @@ -103,14 +113,14 @@ pub trait GetSnapshots {
volid: &Self::SourceID,
snapid: &Self::ResourceID,
output: &utils::OutputFormat,
);
) -> KubectlResult;
}

/// Cordon trait.
/// To be implemented by resources which support cordoning.
#[async_trait(?Send)]
pub trait Cordoning {
type ID;
async fn cordon(id: &Self::ID, label: &str, output: &utils::OutputFormat);
async fn uncordon(id: &Self::ID, label: &str, output: &utils::OutputFormat);
async fn cordon(id: &Self::ID, label: &str, output: &utils::OutputFormat) -> KubectlResult;
async fn uncordon(id: &Self::ID, label: &str, output: &utils::OutputFormat) -> KubectlResult;
}
19 changes: 15 additions & 4 deletions control-plane/plugin/src/resources/blockdevice.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
operations::GetBlockDevices,
resources::{
error::Error,
utils::{
optional_cell, print_table, CreateRow, GetHeaderRow, OutputFormat,
BLOCKDEVICE_HEADERS_ALL, BLOCKDEVICE_HEADERS_USABLE,
Expand Down Expand Up @@ -124,7 +125,11 @@ impl GetHeaderRow for BlockDeviceUsable {
#[async_trait(?Send)]
impl GetBlockDevices for BlockDevice {
type ID = NodeId;
async fn get_blockdevices(id: &Self::ID, all: &bool, output: &OutputFormat) {
async fn get_blockdevices(
id: &Self::ID,
all: &bool,
output: &OutputFormat,
) -> Result<(), Error> {
let mut used_disks: Vec<String> = vec![];
match RestClient::client().pools_api().get_node_pools(id).await {
Ok(pools) => {
Expand All @@ -140,8 +145,10 @@ impl GetBlockDevices for BlockDevice {
}
}
Err(e) => {
println!("Failed to list blockdevices for node {id} . Error {e}");
return;
return Err(Error::GetBlockDevicesError {
id: id.to_string(),
source: e,
});
}
}

Expand Down Expand Up @@ -169,9 +176,13 @@ impl GetBlockDevices for BlockDevice {
};
}
Err(e) => {
println!("Failed to list blockdevices for node {id} . Error {e}")
return Err(Error::GetBlockDevicesError {
id: id.to_string(),
source: e,
});
}
}
Ok(())
}
}

Expand Down
16 changes: 11 additions & 5 deletions control-plane/plugin/src/resources/cordon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use async_trait::async_trait;
use openapi::models::CordonDrainState;

use crate::{
operations::{Get, List},
operations::{Get, KubectlResult, List},
resources::{
error::Error,
node::{node_display_print, node_display_print_one, NodeDisplayFormat},
utils::OutputFormat,
NodeId,
Expand All @@ -17,21 +18,25 @@ use crate::{
#[async_trait(?Send)]
impl Get for NodeCordon {
type ID = NodeId;
async fn get(id: &Self::ID, output: &OutputFormat) {
async fn get(id: &Self::ID, output: &OutputFormat) -> KubectlResult {
match RestClient::client().nodes_api().get_node(id).await {
Ok(node) => {
node_display_print_one(node.into_body(), output, NodeDisplayFormat::CordonLabels)
}
Err(e) => {
println!("Failed to get node {id}. Error {e}")
return Err(Error::GetNodeError {
id: id.to_string(),
source: e,
});
}
}
Ok(())
}
}

#[async_trait(?Send)]
impl List for NodeCordons {
async fn list(output: &OutputFormat) {
async fn list(output: &OutputFormat) -> KubectlResult {
match RestClient::client().nodes_api().get_nodes(None).await {
Ok(nodes) => {
// iterate through the nodes and filter for only those that have cordon or drain
Expand All @@ -53,8 +58,9 @@ impl List for NodeCordons {
node_display_print(filteredlist, output, NodeDisplayFormat::CordonLabels)
}
Err(e) => {
println!("Failed to list nodes. Error {e}")
return Err(Error::ListNodesError { source: e });
}
}
Ok(())
}
}
16 changes: 11 additions & 5 deletions control-plane/plugin/src/resources/drain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use async_trait::async_trait;
use openapi::models::CordonDrainState;

use crate::{
operations::{Get, List},
operations::{Get, KubectlResult, List},
resources::{
error::Error,
node::{node_display_print, node_display_print_one, NodeDisplayFormat},
utils::OutputFormat,
NodeId,
Expand All @@ -17,19 +18,23 @@ use crate::{
#[async_trait(?Send)]
impl Get for NodeDrain {
type ID = NodeId;
async fn get(id: &Self::ID, output: &OutputFormat) {
async fn get(id: &Self::ID, output: &OutputFormat) -> KubectlResult {
match RestClient::client().nodes_api().get_node(id).await {
Ok(node) => node_display_print_one(node.into_body(), output, NodeDisplayFormat::Drain),
Err(e) => {
println!("Failed to get node {id}. Error {e}")
return Err(Error::GetNodeError {
id: id.to_string(),
source: e,
});
}
}
Ok(())
}
}

#[async_trait(?Send)]
impl List for NodeDrains {
async fn list(output: &OutputFormat) {
async fn list(output: &OutputFormat) -> KubectlResult {
match RestClient::client().nodes_api().get_nodes(None).await {
Ok(nodes) => {
// iterate through the nodes and filter for only those that have drain labels
Expand All @@ -51,8 +56,9 @@ impl List for NodeDrains {
node_display_print(filteredlist, output, NodeDisplayFormat::Drain);
}
Err(e) => {
println!("Failed to list nodes. Error {e}")
return Err(Error::ListNodesError { source: e });
}
}
Ok(())
}
}
77 changes: 77 additions & 0 deletions control-plane/plugin/src/resources/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use snafu::Snafu;

/// All errors returned when kubectl plugin command fails
#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
#[allow(clippy::enum_variant_names)]
pub enum Error {
/// Error when listing block devices fails.
#[snafu(display("Failed to list blockdevices for node {id} . Error {source}"))]
GetBlockDevicesError {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when get node request fails.
#[snafu(display("Failed to get node {id}. Error {source}"))]
GetNodeError {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when node cordon request fails.
#[snafu(display("Failed to get node {id}. Error {source}"))]
NodeCordonError {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when node uncordon request fails.
#[snafu(display("Failed to uncordon node {id}. Error {source}"))]
NodeUncordonError {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when put node drain request fails.
#[snafu(display("Failed to put node drain {id}. Error {source}"))]
PutNodeDrainError {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when list nodes request fails.
#[snafu(display("Failed to list nodes. Error {source}"))]
ListNodesError {
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when get pool request fails.
#[snafu(display("Failed to get pool {id}. Error {source}"))]
GetPoolError {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when list pools request fails.
#[snafu(display("Failed to list pools. Error {source}"))]
ListPoolsError {
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when get volume request fails.
#[snafu(display("Failed to get volume {id}. Error {source}"))]
GetVolumeError {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when get rebuild history for volume request fails.
#[snafu(display("Failed to get rebuild history for volume {id}. Error {source}"))]
GetRebuildHistory {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when scale volume request fails.
#[snafu(display("Failed to scale volume {id}. Error {source}"))]
ScaleVolumeError {
id: String,
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
/// Error when list snapshots request fails.
#[snafu(display("Failed to list volume snapshots. Error {source}"))]
ListSnapshotsError {
source: openapi::tower::client::Error<openapi::models::RestJsonError>,
},
}
1 change: 1 addition & 0 deletions control-plane/plugin/src/resources/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::resources::{
pub mod blockdevice;
pub mod cordon;
pub mod drain;
pub mod error;
pub mod node;
pub mod pool;
pub mod snapshot;
Expand Down
Loading

0 comments on commit 4ba2a71

Please sign in to comment.