Skip to content

Commit

Permalink
refactor(rest-plugin): use execution handler trait
Browse files Browse the repository at this point in the history
Allows for tidier composition of operations, which will be especially useful
to reduce code duplication in kubectl plugin.

Signed-off-by: Tiago Castro <[email protected]>
  • Loading branch information
tiagolobocastro committed Jan 23, 2024
1 parent 0c79316 commit 4033d17
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 75 deletions.
189 changes: 115 additions & 74 deletions control-plane/plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
},
resources::{
blockdevice, cordon, drain, node, pool, snapshot, volume, CordonResources, DrainResources,
GetCordonArgs, GetDrainArgs, GetResources, ScaleResources,
GetCordonArgs, GetDrainArgs, GetResources, ScaleResources, UnCordonResources,
},
};

Expand All @@ -26,6 +26,12 @@ impl Drop for TracingFlusher {
}
}

/// Every rest plugin operation must implement this trait to become composable.
#[async_trait::async_trait(?Send)]
pub trait ExecuteOperation {
async fn execute(&self, cli_args: &RestCliArgs) -> PluginResult;
}

#[derive(clap::Parser, Debug)]
#[clap(name = utils::package_description!(), version = utils::version_info_str!())]
pub struct RestCliArgs {
Expand All @@ -50,79 +56,11 @@ impl RestCliArgs {
/// Execute the operation specified in `Self::operations`, with proper output format.
pub async fn execute(&self) -> PluginResult {
match &self.operation {
Operations::Drain(resource) => match resource {
DrainResources::Node(drain_node_args) => {
node::Node::drain(
&drain_node_args.node_id(),
drain_node_args.label(),
drain_node_args.drain_timeout(),
&self.output,
)
.await
}
},
Operations::Get(resource) => match resource {
GetResources::Cordon(get_cordon_resource) => match get_cordon_resource {
GetCordonArgs::Node { id: node_id } => {
cordon::NodeCordon::get(node_id, &self.output).await
}
GetCordonArgs::Nodes => cordon::NodeCordons::list(&self.output).await,
},
GetResources::Drain(get_drain_resource) => match get_drain_resource {
GetDrainArgs::Node { id: node_id } => {
drain::NodeDrain::get(node_id, &self.output).await
}
GetDrainArgs::Nodes => drain::NodeDrains::list(&self.output).await,
},
GetResources::Volumes(vol_args) => {
volume::Volumes::list(&self.output, vol_args).await
}
GetResources::Volume { id } => volume::Volume::get(id, &self.output).await,
GetResources::RebuildHistory { id } => {
volume::Volume::rebuild_history(id, &self.output).await
}
GetResources::VolumeReplicaTopologies(vol_args) => {
volume::Volume::topologies(&self.output, vol_args).await
}
GetResources::VolumeReplicaTopology { id } => {
volume::Volume::topology(id, &self.output).await
}
GetResources::Pools => pool::Pools::list(&self.output).await,
GetResources::Pool { id } => pool::Pool::get(id, &self.output).await,
GetResources::Nodes => node::Nodes::list(&self.output).await,
GetResources::Node(args) => node::Node::get(&args.node_id(), &self.output).await,
GetResources::BlockDevices(bdargs) => {
blockdevice::BlockDevice::get_blockdevices(
&bdargs.node_id(),
&bdargs.all(),
&self.output,
)
.await
}
GetResources::VolumeSnapshots(snapargs) => {
snapshot::VolumeSnapshots::get_snapshots(
&snapargs.volume(),
&snapargs.snapshot(),
&self.output,
)
.await
}
},
Operations::Scale(resource) => match resource {
ScaleResources::Volume { id, replica_count } => {
volume::Volume::scale(id, *replica_count, &self.output).await
}
},
Operations::Cordon(resource) => match resource {
CordonResources::Node { id, label } => {
node::Node::cordon(id, label, &self.output).await
}
},
Operations::Uncordon(resource) => match resource {
CordonResources::Node { id, label } => {
node::Node::uncordon(id, label, &self.output).await
}
},
Operations::Drain(resource) => resource.execute(self).await,
Operations::Get(resource) => resource.execute(self).await,
Operations::Scale(resource) => resource.execute(self).await,
Operations::Cordon(resource) => resource.execute(self).await,
Operations::Uncordon(resource) => resource.execute(self).await,
}
}
/// Initialize tracing (including opentelemetry).
Expand All @@ -147,3 +85,106 @@ impl RestCliArgs {
TracingFlusher {}
}
}

#[async_trait::async_trait(?Send)]
impl ExecuteOperation for DrainResources {
async fn execute(&self, cli_args: &RestCliArgs) -> PluginResult {
match self {
DrainResources::Node(drain_node_args) => {
node::Node::drain(
&drain_node_args.node_id(),
drain_node_args.label(),
drain_node_args.drain_timeout(),
&cli_args.output,
)
.await
}
}
}
}

#[async_trait::async_trait(?Send)]
impl ExecuteOperation for GetResources {
async fn execute(&self, cli_args: &RestCliArgs) -> PluginResult {
match self {
GetResources::Cordon(get_cordon_resource) => match get_cordon_resource {
GetCordonArgs::Node { id: node_id } => {
cordon::NodeCordon::get(node_id, &cli_args.output).await
}
GetCordonArgs::Nodes => cordon::NodeCordons::list(&cli_args.output).await,
},
GetResources::Drain(get_drain_resource) => match get_drain_resource {
GetDrainArgs::Node { id: node_id } => {
drain::NodeDrain::get(node_id, &cli_args.output).await
}
GetDrainArgs::Nodes => drain::NodeDrains::list(&cli_args.output).await,
},
GetResources::Volumes(vol_args) => {
volume::Volumes::list(&cli_args.output, vol_args).await
}
GetResources::Volume { id } => volume::Volume::get(id, &cli_args.output).await,
GetResources::RebuildHistory { id } => {
volume::Volume::rebuild_history(id, &cli_args.output).await
}
GetResources::VolumeReplicaTopologies(vol_args) => {
volume::Volume::topologies(&cli_args.output, vol_args).await
}
GetResources::VolumeReplicaTopology { id } => {
volume::Volume::topology(id, &cli_args.output).await
}
GetResources::Pools => pool::Pools::list(&cli_args.output).await,
GetResources::Pool { id } => pool::Pool::get(id, &cli_args.output).await,
GetResources::Nodes => node::Nodes::list(&cli_args.output).await,
GetResources::Node(args) => node::Node::get(&args.node_id(), &cli_args.output).await,
GetResources::BlockDevices(bdargs) => {
blockdevice::BlockDevice::get_blockdevices(
&bdargs.node_id(),
&bdargs.all(),
&cli_args.output,
)
.await
}
GetResources::VolumeSnapshots(snapargs) => {
snapshot::VolumeSnapshots::get_snapshots(
&snapargs.volume(),
&snapargs.snapshot(),
&cli_args.output,
)
.await
}
}
}
}

#[async_trait::async_trait(?Send)]
impl ExecuteOperation for ScaleResources {
async fn execute(&self, cli_args: &RestCliArgs) -> PluginResult {
match self {
ScaleResources::Volume { id, replica_count } => {
volume::Volume::scale(id, *replica_count, &cli_args.output).await
}
}
}
}

#[async_trait::async_trait(?Send)]
impl ExecuteOperation for CordonResources {
async fn execute(&self, cli_args: &RestCliArgs) -> PluginResult {
match self {
CordonResources::Node { id, label } => {
node::Node::cordon(id, label, &cli_args.output).await
}
}
}
}

#[async_trait::async_trait(?Send)]
impl ExecuteOperation for UnCordonResources {
async fn execute(&self, cli_args: &RestCliArgs) -> PluginResult {
match self {
UnCordonResources::Node { id, label } => {
node::Node::uncordon(id, label, &cli_args.output).await
}
}
}
}
3 changes: 2 additions & 1 deletion control-plane/plugin/src/operations.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::resources::{
error::Error, utils, CordonResources, DrainResources, GetResources, ScaleResources,
UnCordonResources,
};
use async_trait::async_trait;

Expand All @@ -23,7 +24,7 @@ pub enum Operations {
Cordon(CordonResources),
/// 'Uncordon' resources.
#[clap(subcommand)]
Uncordon(CordonResources),
Uncordon(UnCordonResources),
}

/// Drain trait.
Expand Down
8 changes: 8 additions & 0 deletions control-plane/plugin/src/resources/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ pub enum CordonResources {
Node { id: NodeId, label: String },
}

/// The types of resources that support uncordoning.
#[derive(clap::Subcommand, Debug)]
pub enum UnCordonResources {
/// Removes the cordon label from the node.
/// When the node has no more cordon labels, it is effectively uncordoned.
Node { id: NodeId, label: String },
}

/// The types of resources that support the 'get cordon' operation.
#[derive(clap::Subcommand, Debug)]
pub enum GetCordonArgs {
Expand Down

0 comments on commit 4033d17

Please sign in to comment.