From 686ed87389070dddccad024b0bb6fbd8ec99b705 Mon Sep 17 00:00:00 2001 From: Elmar Schug Date: Thu, 21 Dec 2023 14:55:59 +0100 Subject: [PATCH] Refactored error handling of CARL's store_/delete_cluster_deployment. --- .../carl/services/cluster-manager.proto | 62 ++++--- .../opendut-carl-api/src/carl/cluster.rs | 105 +++++------ .../opendut-carl-api/src/proto/services.rs | 174 +++++++++++++++++- opendut-carl/src/cluster/manager.rs | 52 +++--- opendut-carl/src/grpc/cluster_manager.rs | 106 ++++------- .../src/commands/cluster_deployment.rs | 2 +- opendut-lea/src/clusters/overview.rs | 2 +- .../src/client/implementation.rs | 1 - 8 files changed, 331 insertions(+), 173 deletions(-) diff --git a/opendut-carl/opendut-carl-api/proto/opendut/carl/services/cluster-manager.proto b/opendut-carl/opendut-carl-api/proto/opendut/carl/services/cluster-manager.proto index 7a71a177b..48fd61943 100644 --- a/opendut-carl/opendut-carl-api/proto/opendut/carl/services/cluster-manager.proto +++ b/opendut-carl/opendut-carl-api/proto/opendut/carl/services/cluster-manager.proto @@ -138,63 +138,83 @@ message ListClusterConfigurationsFailure {} // StoreClusterDeployment // message StoreClusterDeploymentRequest { - opendut.types.cluster.ClusterDeployment deployment = 1; + opendut.types.cluster.ClusterDeployment cluster_deployment = 1; } message StoreClusterDeploymentResponse { - oneof result { + oneof reply { StoreClusterDeploymentFailure failure = 1; StoreClusterDeploymentSuccess success = 15; } } -message StoreClusterDeploymentSuccess {} +message StoreClusterDeploymentSuccess { + opendut.types.cluster.ClusterId cluster_id = 1; +} + +message StoreClusterDeploymentFailure { + oneof error { + StoreClusterDeploymentFailureIllegalClusterState illegal_cluster_state = 1; + StoreClusterDeploymentFailureInternal internal = 2; + } +} + +message StoreClusterDeploymentFailureIllegalClusterState { + opendut.types.cluster.ClusterId cluster_id = 1; + opendut.types.cluster.ClusterName cluster_name = 2; + opendut.types.cluster.ClusterState actual_state = 3; + repeated opendut.types.cluster.ClusterState required_states = 4; +} -message StoreClusterDeploymentFailure {} +message StoreClusterDeploymentFailureInternal { + opendut.types.cluster.ClusterId cluster_id = 1; + opendut.types.cluster.ClusterName cluster_name = 2; + string cause = 3; +} // // DeleteClusterDeployment // message DeleteClusterDeploymentRequest { - opendut.types.cluster.ClusterId id = 1; + opendut.types.cluster.ClusterId cluster_id = 1; } message DeleteClusterDeploymentResponse { - oneof result { + oneof reply { DeleteClusterDeploymentFailure failure = 1; DeleteClusterDeploymentSuccess success = 15; } } message DeleteClusterDeploymentSuccess { - opendut.types.cluster.ClusterDeployment deployment = 1; + opendut.types.cluster.ClusterDeployment cluster_deployment = 1; } message DeleteClusterDeploymentFailure { - oneof reason { - DeleteClusterDeploymentFailureClusterIdRequired cluster_id_required = 1; - DeleteClusterDeploymentFailureInvalidClusterId invalid_cluster_id = 2; - DeleteClusterDeploymentFailureNotFound cluster_not_found = 3; - DeleteClusterDeploymentFailureInternal internal = 4; + oneof error { + DeleteClusterDeploymentFailureClusterDeploymentNotFound cluster_deployment_not_found = 1; + DeleteClusterDeploymentFailureIllegalClusterState illegal_cluster_state = 2; + DeleteClusterDeploymentFailureInternal internal = 3; } } -message DeleteClusterDeploymentFailureClusterIdRequired {} - -message DeleteClusterDeploymentFailureInvalidClusterId { - string cause = 1; +message DeleteClusterDeploymentFailureClusterDeploymentNotFound { + opendut.types.cluster.ClusterId cluster_id = 1; } -message DeleteClusterDeploymentFailureNotFound { - opendut.types.cluster.ClusterId id = 1; +message DeleteClusterDeploymentFailureIllegalClusterState { + opendut.types.cluster.ClusterId cluster_id = 1; + opendut.types.cluster.ClusterName cluster_name = 2; + opendut.types.cluster.ClusterState actual_state = 3; + repeated opendut.types.cluster.ClusterState required_states = 4; } message DeleteClusterDeploymentFailureInternal { - opendut.types.cluster.ClusterId id = 1; - string cause = 2; + opendut.types.cluster.ClusterId cluster_id = 1; + opendut.types.cluster.ClusterName cluster_name = 2; + string cause = 3; } - // // ListClusterDeployments // diff --git a/opendut-carl/opendut-carl-api/src/carl/cluster.rs b/opendut-carl/opendut-carl-api/src/carl/cluster.rs index e1f3367b3..19b84f38e 100644 --- a/opendut-carl/opendut-carl-api/src/carl/cluster.rs +++ b/opendut-carl/opendut-carl-api/src/carl/cluster.rs @@ -1,6 +1,5 @@ #[cfg(any(feature = "client", feature = "wasm-client"))] pub use client::*; - use opendut_types::cluster::{ClusterId, ClusterName}; use opendut_types::cluster::state::{ClusterState, ClusterStates}; @@ -54,28 +53,42 @@ pub struct ListClusterConfigurationsError { message: String, } - #[derive(thiserror::Error, Debug)] -#[error("{message}")] -pub struct StoreClusterDeploymentError { - message: String, +pub enum StoreClusterDeploymentError { + #[error("ClusterDeployment for cluster '{cluster_name}' <{cluster_id}> cannot be changed when cluster is in state '{actual_state}'! A cluster can be updated when: {required_states}")] + IllegalClusterState { + cluster_id: ClusterId, + cluster_name: ClusterName, + actual_state: ClusterState, + required_states: ClusterStates, + }, + #[error("ClusterDeployment for cluster '{cluster_name}' <{cluster_id}> could not be changed, due to internal errors:\n {cause}")] + Internal { + cluster_id: ClusterId, + cluster_name: ClusterName, + cause: String + } } #[derive(thiserror::Error, Debug)] pub enum DeleteClusterDeploymentError { - #[error("Invalid ClusterId: {cause}")] - InvalidClusterId { - cause: String + #[error("ClusterDeployment for cluster <{cluster_id}> could not be deleted, because a ClusterDeployment with that id does not exist!")] + ClusterDeploymentNotFound { + cluster_id: ClusterId }, - #[error("Unknown cluster id <{id}>")] - ClusterNotFound { - id: ClusterId + #[error("ClusterDeployment for cluster '{cluster_name}' <{cluster_id}> cannot be deleted when cluster is in state '{actual_state}'! A peer can be deleted when: {required_states}")] + IllegalClusterState { + cluster_id: ClusterId, + cluster_name: ClusterName, + actual_state: ClusterState, + required_states: ClusterStates, }, - #[error("Internal error when deleting cluster with id <{id}>.\n{cause}")] + #[error("ClusterDeployment for cluster '{cluster_name}' <{cluster_id}> deleted with internal errors:\n {cause}")] Internal { - id: ClusterId, - cause: String, - }, + cluster_id: ClusterId, + cluster_name: ClusterName, + cause: String + } } #[derive(thiserror::Error, Debug)] @@ -150,8 +163,8 @@ mod client { Err(ClientError::UsageError(error)) } cluster_manager::delete_cluster_configuration_response::Reply::Success(success) => { - let peer_id = extract!(success.cluster_configuration)?; - Ok(peer_id) + let cluster_id = extract!(success.cluster_configuration)?; + Ok(cluster_id) } } } @@ -208,17 +221,23 @@ mod client { } } - pub async fn store_cluster_deployment(&mut self, deployment: &ClusterDeployment) -> Result<(), StoreClusterDeploymentError> { + pub async fn store_cluster_deployment(&mut self, deployment: ClusterDeployment) -> Result> { + let request = tonic::Request::new(cluster_manager::StoreClusterDeploymentRequest { - deployment: Some(Clone::clone(deployment).into()), + cluster_deployment: Some(deployment.into()), }); - match self.inner.store_cluster_deployment(request).await { - Ok(_) => { - Ok(()) - }, - Err(status) => { - Err(StoreClusterDeploymentError { message: format!("gRPC failure: {status}") }) + let response = self.inner.store_cluster_deployment(request).await? + .into_inner(); + + match extract!(response.reply)? { + cluster_manager::store_cluster_deployment_response::Reply::Failure(failure) => { + let error = StoreClusterDeploymentError::try_from(failure)?; + Err(ClientError::UsageError(error)) + } + cluster_manager::store_cluster_deployment_response::Reply::Success(success) => { + let cluster_id = extract!(success.cluster_id)?; + Ok(cluster_id) } } } @@ -226,38 +245,20 @@ mod client { pub async fn delete_cluster_deployment(&mut self, cluster_id: ClusterId) -> Result> { let request = tonic::Request::new(cluster_manager::DeleteClusterDeploymentRequest { - id: Some(cluster_id.into()), + cluster_id: Some(cluster_id.into()), }); - let response = self.inner.delete_cluster_deployment(request) - .await? + let response = self.inner.delete_cluster_deployment(request).await? .into_inner(); - let result = extract!(response.result)?; - - match result { - cluster_manager::delete_cluster_deployment_response::Result::Failure(failure) => { - match failure.reason { - Some(cluster_manager::delete_cluster_deployment_failure::Reason::ClusterNotFound(cluster_manager::DeleteClusterDeploymentFailureNotFound { .. })) => { - Err(ClientError::UsageError(DeleteClusterDeploymentError::ClusterNotFound { id: cluster_id } )) - } - Some(cluster_manager::delete_cluster_deployment_failure::Reason::InvalidClusterId(cluster_manager::DeleteClusterDeploymentFailureInvalidClusterId { cause })) => { - Err(ClientError::UsageError(DeleteClusterDeploymentError::InvalidClusterId { cause } )) - } - Some(cluster_manager::delete_cluster_deployment_failure::Reason::ClusterIdRequired(_)) => { - Err(ClientError::InvalidRequest(format!("DeleteClusterDeploymentRequest requires ClusterId!"))) - } - None => { - Err(ClientError::InvalidRequest(format!("DeleteClusterDeploymentFailure contains no reason!"))) - } - Some(cluster_manager::delete_cluster_deployment_failure::Reason::Internal(cluster_manager::DeleteClusterDeploymentFailureInternal { cause, .. })) => { - Err(ClientError::UsageError(DeleteClusterDeploymentError::Internal { id: cluster_id, cause } )) - } - } + match extract!(response.reply)? { + cluster_manager::delete_cluster_deployment_response::Reply::Failure(failure) => { + let error = DeleteClusterDeploymentError::try_from(failure)?; + Err(ClientError::UsageError(error)) } - cluster_manager::delete_cluster_deployment_response::Result::Success(success) => { - let cluster_deployment = extract!(success.deployment)?; - Ok(cluster_deployment) + cluster_manager::delete_cluster_deployment_response::Reply::Success(success) => { + let cluster_id = extract!(success.cluster_deployment)?; + Ok(cluster_id) } } } diff --git a/opendut-carl/opendut-carl-api/src/proto/services.rs b/opendut-carl/opendut-carl-api/src/proto/services.rs index 5d1fc3793..8978c80d9 100644 --- a/opendut-carl/opendut-carl-api/src/proto/services.rs +++ b/opendut-carl/opendut-carl-api/src/proto/services.rs @@ -3,7 +3,7 @@ pub mod cluster_manager { use opendut_types::cluster::state::ClusterState; use opendut_types::proto::{ConversionError, ConversionErrorBuilder}; - use crate::carl::cluster::{CreateClusterConfigurationError, DeleteClusterConfigurationError}; + use crate::carl::cluster::{CreateClusterConfigurationError, DeleteClusterConfigurationError, DeleteClusterDeploymentError, StoreClusterDeploymentError}; tonic::include_proto!("opendut.carl.services.cluster_manager"); @@ -178,6 +178,178 @@ pub mod cluster_manager { Ok(DeleteClusterConfigurationError::Internal { cluster_id, cluster_name, cause: failure.cause }) } } + + impl From for StoreClusterDeploymentFailure { + fn from(error: StoreClusterDeploymentError) -> Self { + let proto_error = match error { + StoreClusterDeploymentError::IllegalClusterState { cluster_id, cluster_name, actual_state, required_states } => { + store_cluster_deployment_failure::Error::IllegalClusterState(StoreClusterDeploymentFailureIllegalClusterState { + cluster_id: Some(cluster_id.into()), + cluster_name: Some(cluster_name.into()), + actual_state: Some(actual_state.into()), + required_states: required_states.into(), + }) + } + StoreClusterDeploymentError::Internal { cluster_id, cluster_name, cause } => { + store_cluster_deployment_failure::Error::Internal(StoreClusterDeploymentFailureInternal { + cluster_id: Some(cluster_id.into()), + cluster_name: Some(cluster_name.into()), + cause + }) + } + }; + StoreClusterDeploymentFailure { + error: Some(proto_error) + } + } + } + + impl TryFrom for StoreClusterDeploymentError { + type Error = ConversionError; + fn try_from(failure: StoreClusterDeploymentFailure) -> Result { + type ErrorBuilder = ConversionErrorBuilder; + let error = failure.error + .ok_or_else(|| ErrorBuilder::new("Field 'error' not set"))?; + let error = match error { + store_cluster_deployment_failure::Error::IllegalClusterState(error) => { + error.try_into()? + } + store_cluster_deployment_failure::Error::Internal(error) => { + error.try_into()? + } + }; + Ok(error) + } + } + + impl TryFrom for StoreClusterDeploymentError { + type Error = ConversionError; + fn try_from(failure: StoreClusterDeploymentFailureIllegalClusterState) -> Result { + type ErrorBuilder = ConversionErrorBuilder; + let cluster_id: ClusterId = failure.cluster_id + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_id' not set"))? + .try_into()?; + let cluster_name: ClusterName = failure.cluster_name + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_name' not set"))? + .try_into()?; + let actual_state: ClusterState = failure.actual_state + .ok_or_else(|| ErrorBuilder::new("Field 'actual_state' not set"))? + .try_into()?; + let required_states = failure.required_states + .try_into()?; + Ok(StoreClusterDeploymentError::IllegalClusterState { cluster_id, cluster_name, actual_state, required_states }) + } + } + + impl TryFrom for StoreClusterDeploymentError { + type Error = ConversionError; + fn try_from(failure: StoreClusterDeploymentFailureInternal) -> Result { + type ErrorBuilder = ConversionErrorBuilder; + let cluster_id: ClusterId = failure.cluster_id + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_id' not set"))? + .try_into()?; + let cluster_name: ClusterName = failure.cluster_name + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_name' not set"))? + .try_into()?; + Ok(StoreClusterDeploymentError::Internal { cluster_id, cluster_name, cause: failure.cause }) + } + } + + impl From for DeleteClusterDeploymentFailure { + fn from(error: DeleteClusterDeploymentError) -> Self { + let proto_error = match error { + DeleteClusterDeploymentError::ClusterDeploymentNotFound { cluster_id } => { + delete_cluster_deployment_failure::Error::ClusterDeploymentNotFound(DeleteClusterDeploymentFailureClusterDeploymentNotFound { + cluster_id: Some(cluster_id.into()) + }) + } + DeleteClusterDeploymentError::IllegalClusterState { cluster_id, cluster_name, actual_state, required_states } => { + delete_cluster_deployment_failure::Error::IllegalClusterState(DeleteClusterDeploymentFailureIllegalClusterState { + cluster_id: Some(cluster_id.into()), + cluster_name: Some(cluster_name.into()), + actual_state: Some(actual_state.into()), + required_states: required_states.into(), + }) + } + DeleteClusterDeploymentError::Internal { cluster_id, cluster_name, cause } => { + delete_cluster_deployment_failure::Error::Internal(DeleteClusterDeploymentFailureInternal { + cluster_id: Some(cluster_id.into()), + cluster_name: Some(cluster_name.into()), + cause + }) + } + }; + DeleteClusterDeploymentFailure { + error: Some(proto_error) + } + } + } + + impl TryFrom for DeleteClusterDeploymentError { + type Error = ConversionError; + fn try_from(failure: DeleteClusterDeploymentFailure) -> Result { + type ErrorBuilder = ConversionErrorBuilder; + let error = failure.error + .ok_or_else(|| ErrorBuilder::new("Field 'error' not set"))?; + let error = match error { + delete_cluster_deployment_failure::Error::ClusterDeploymentNotFound(error) => { + error.try_into()? + } + delete_cluster_deployment_failure::Error::IllegalClusterState(error) => { + error.try_into()? + } + delete_cluster_deployment_failure::Error::Internal(error) => { + error.try_into()? + } + }; + Ok(error) + } + } + + impl TryFrom for DeleteClusterDeploymentError { + type Error = ConversionError; + fn try_from(failure: DeleteClusterDeploymentFailureClusterDeploymentNotFound) -> Result { + type ErrorBuilder = ConversionErrorBuilder; + let cluster_id: ClusterId = failure.cluster_id + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_id' not set"))? + .try_into()?; + Ok(DeleteClusterDeploymentError::ClusterDeploymentNotFound { cluster_id }) + } + } + + impl TryFrom for DeleteClusterDeploymentError { + type Error = ConversionError; + fn try_from(failure: DeleteClusterDeploymentFailureIllegalClusterState) -> Result { + type ErrorBuilder = ConversionErrorBuilder; + let cluster_id: ClusterId = failure.cluster_id + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_id' not set"))? + .try_into()?; + let cluster_name: ClusterName = failure.cluster_name + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_name' not set"))? + .try_into()?; + let actual_state: ClusterState = failure.actual_state + .ok_or_else(|| ErrorBuilder::new("Field 'actual_state' not set"))? + .try_into()?; + let required_states = failure.required_states + .try_into()?; + Ok(DeleteClusterDeploymentError::IllegalClusterState { cluster_id, cluster_name, actual_state, required_states }) + } + } + + impl TryFrom for DeleteClusterDeploymentError { + type Error = ConversionError; + fn try_from(failure: DeleteClusterDeploymentFailureInternal) -> Result { + type ErrorBuilder = ConversionErrorBuilder; + let cluster_id: ClusterId = failure.cluster_id + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_id' not set"))? + .try_into()?; + let cluster_name: ClusterName = failure.cluster_name + .ok_or_else(|| ErrorBuilder::new("Field 'cluster_name' not set"))? + .try_into()?; + Ok(DeleteClusterDeploymentError::Internal { cluster_id, cluster_name, cause: failure.cause }) + } + } + } pub mod metadata_provider { diff --git a/opendut-carl/src/cluster/manager.rs b/opendut-carl/src/cluster/manager.rs index 0af7d311a..a5eb86258 100644 --- a/opendut-carl/src/cluster/manager.rs +++ b/opendut-carl/src/cluster/manager.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use opendut_carl_api::carl::cluster::DeleteClusterDeploymentError; +use opendut_carl_api::carl::cluster::{DeleteClusterDeploymentError, StoreClusterDeploymentError}; use opendut_carl_api::proto::services::peer_messaging_broker::AssignCluster; use opendut_carl_api::proto::services::peer_messaging_broker::downstream::Message; use opendut_types::cluster::{ClusterConfiguration, ClusterDeployment, ClusterId}; @@ -94,17 +94,35 @@ impl ClusterManager { }).await } - pub async fn create_deployment(&self, deployment: ClusterDeployment) -> Result<(), DeployClusterError> { + pub async fn store_cluster_deployment(&self, deployment: ClusterDeployment) -> Result { let cluster_id = deployment.id; - self.store_deployment(deployment).await; - self.deploy(cluster_id).await - } - - pub async fn store_deployment(&self, deployment: ClusterDeployment) { - log::trace!("Storing deployment: {:?}", deployment); self.resources_manager.resources_mut(|resources| { resources.insert(deployment.id, deployment); }).await; + if let Err(error) = self.deploy(cluster_id).await { + log::error!("Failed to deploy cluster <{cluster_id}>, due to:\n {error}"); + } + Ok(cluster_id) + } + + pub async fn delete_cluster_deployment(&self, cluster_id: ClusterId) -> Result { + + let (deployment, configuration) = self.resources_manager + .resources_mut(|resources| { + resources.remove::(cluster_id) + .map(|deployment| (deployment, resources.get::(cluster_id))) + }) + .await + .ok_or(DeleteClusterDeploymentError::ClusterDeploymentNotFound { cluster_id })?; + + if let Some(configuration) = configuration { + if let Vpn::Enabled { vpn_client } = &self.vpn { + vpn_client.delete_cluster(cluster_id).await + .map_err(|error| DeleteClusterDeploymentError::Internal { cluster_id, cluster_name: configuration.name, cause: error.to_string() })?; + } + } + + Ok(deployment) } pub async fn find_deployment(&self, id: ClusterId) -> Option { @@ -118,32 +136,20 @@ impl ClusterManager { resources.iter::().cloned().collect::>() }).await } - - pub async fn delete_deployment(&self, id: ClusterId) -> Result { - let deployment = self.resources_manager.resources_mut(|resources| { - resources.remove::(id) - }).await; - let deployment = deployment.ok_or(DeleteClusterDeploymentError::ClusterNotFound { id })?; - - if let Vpn::Enabled { vpn_client } = &self.vpn { - vpn_client.delete_cluster(id).await - .map_err(|error| DeleteClusterDeploymentError::Internal { id, cause: error.to_string() })?; - } - Ok(deployment) - } - } #[cfg(test)] mod test { use std::collections::HashSet; use std::time::Duration; + use googletest::prelude::*; + use opendut_types::cluster::ClusterName; use opendut_types::peer::{PeerDescriptor, PeerId, PeerName}; use opendut_types::topology::{Device, DeviceId, InterfaceName, Topology}; - use crate::actions::{CreateClusterConfigurationParams, StorePeerDescriptorParams}; + use crate::actions::{CreateClusterConfigurationParams, StorePeerDescriptorParams}; use crate::peer::broker::broker::PeerMessagingBroker; use crate::resources::manager::ResourcesManager; diff --git a/opendut-carl/src/grpc/cluster_manager.rs b/opendut-carl/src/grpc/cluster_manager.rs index 6ccb6f28a..19287dc0c 100644 --- a/opendut-carl/src/grpc/cluster_manager.rs +++ b/opendut-carl/src/grpc/cluster_manager.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use tonic::{Request, Response, Status}; use tonic_web::CorsGrpcWeb; -use opendut_carl_api::carl::cluster::DeleteClusterDeploymentError; use opendut_carl_api::proto::services::cluster_manager::*; use opendut_carl_api::proto::services::cluster_manager::cluster_manager_server::{ClusterManager as ClusterManagerService, ClusterManagerServer}; use opendut_types::cluster::{ClusterConfiguration, ClusterDeployment, ClusterId}; @@ -141,20 +140,27 @@ impl ClusterManagerService for ClusterManagerFacade { })) } - - async fn store_cluster_deployment(&self, request: Request) -> Result, Status> { log::trace!("Received request: {:?}", request); - match request.into_inner().deployment { - None => { - Err(Status::invalid_argument("ClusterDeployment is required.")) - } - Some(deployment) => { - let deployment = ClusterDeployment::try_from(deployment); - self.cluster_manager.create_deployment(deployment.unwrap()).await.unwrap(); // TODO: Handle error + let request = request.into_inner(); + let cluster_deployment: ClusterDeployment = extract!(request.cluster_deployment)?; + + let result = self.cluster_manager.store_cluster_deployment(cluster_deployment).await; + + match result { + Err(error) => { Ok(Response::new(StoreClusterDeploymentResponse { - result: Some(store_cluster_deployment_response::Result::Success(StoreClusterDeploymentSuccess {})) + reply: Some(store_cluster_deployment_response::Reply::Failure(error.into())) + })) + } + Ok(cluster_id) => { + Ok(Response::new(StoreClusterDeploymentResponse { + reply: Some(store_cluster_deployment_response::Reply::Success( + StoreClusterDeploymentSuccess { + cluster_id: Some(cluster_id.into()) + } + )) })) } } @@ -162,72 +168,26 @@ impl ClusterManagerService for ClusterManagerFacade { async fn delete_cluster_deployment(&self, request: Request) -> Result, Status> { log::trace!("Received request: {:?}", request); - match request.into_inner().id { - None => { + + let request = request.into_inner(); + let cluster_id: ClusterId = extract!(request.cluster_id)?; + + let result = self.cluster_manager.delete_cluster_deployment(cluster_id).await; // TODO: Replace with action + + match result { + Err(error) => { Ok(Response::new(DeleteClusterDeploymentResponse { - result: Some(delete_cluster_deployment_response::Result::Failure( - DeleteClusterDeploymentFailure { - reason: Some(delete_cluster_deployment_failure::Reason::ClusterIdRequired(DeleteClusterDeploymentFailureClusterIdRequired {})) - } - )) + reply: Some(delete_cluster_deployment_response::Reply::Failure(error.into())) })) } - Some(id) => { - match ClusterId::try_from(id) { - Err(cause) => { - Ok(Response::new(DeleteClusterDeploymentResponse { - result: Some(delete_cluster_deployment_response::Result::Failure( - DeleteClusterDeploymentFailure { - reason: Some(delete_cluster_deployment_failure::Reason::InvalidClusterId(DeleteClusterDeploymentFailureInvalidClusterId { - cause: cause.to_string() - })) - } - )) - })) - } - Ok(id) => { - match self.cluster_manager.delete_deployment(id).await { - Err(DeleteClusterDeploymentError::ClusterNotFound { id }) => { - Ok(Response::new(DeleteClusterDeploymentResponse { - result: Some(delete_cluster_deployment_response::Result::Failure( - DeleteClusterDeploymentFailure { - reason: Some(delete_cluster_deployment_failure::Reason::ClusterNotFound(DeleteClusterDeploymentFailureNotFound { - id: Some(id.into()) - })) - } - )) - })) - } - Err(DeleteClusterDeploymentError::InvalidClusterId { cause }) => { - Ok(Response::new(DeleteClusterDeploymentResponse { - result: Some(delete_cluster_deployment_response::Result::Failure( - DeleteClusterDeploymentFailure { - reason: Some(delete_cluster_deployment_failure::Reason::InvalidClusterId(DeleteClusterDeploymentFailureInvalidClusterId { cause })) - } - )) - })) - } - Ok(cluster_deployment) => { - Ok(Response::new(DeleteClusterDeploymentResponse { - result: Some(delete_cluster_deployment_response::Result::Success( - DeleteClusterDeploymentSuccess { - deployment: Some(cluster_deployment.into()) - } - )) - })) - } - Err(DeleteClusterDeploymentError::Internal { id, cause }) => { - Ok(Response::new( DeleteClusterDeploymentResponse { - result: Some(delete_cluster_deployment_response::Result::Failure( - DeleteClusterDeploymentFailure { - reason: Some(delete_cluster_deployment_failure::Reason::Internal(DeleteClusterDeploymentFailureInternal { id: Some(id.into()), cause } )), - } - )), - })) - } + Ok(cluster_configuration) => { + Ok(Response::new(DeleteClusterDeploymentResponse { + reply: Some(delete_cluster_deployment_response::Reply::Success( + DeleteClusterDeploymentSuccess { + cluster_deployment: Some(cluster_configuration.into()) } - } - } + )) + })) } } } diff --git a/opendut-cleo/src/commands/cluster_deployment.rs b/opendut-cleo/src/commands/cluster_deployment.rs index 43ff94ce8..c222e2cba 100644 --- a/opendut-cleo/src/commands/cluster_deployment.rs +++ b/opendut-cleo/src/commands/cluster_deployment.rs @@ -9,7 +9,7 @@ pub mod create { let id = ClusterId::from(id); let deployment = ClusterDeployment { id }; - carl.cluster.store_cluster_deployment(&deployment).await + carl.cluster.store_cluster_deployment(deployment).await .map_err(|error| format!("Could not create cluster deployment for ClusterID: '{}'.\n {}", id, error))?; println!("Successfully created cluster deployment for cluster <{}>.", id); diff --git a/opendut-lea/src/clusters/overview.rs b/opendut-lea/src/clusters/overview.rs index 959d4de9f..f5fff42ef 100644 --- a/opendut-lea/src/clusters/overview.rs +++ b/opendut-lea/src/clusters/overview.rs @@ -28,7 +28,7 @@ pub fn ClustersOverview() -> impl IntoView { let mut carl = globals.expect_client(); let id = Clone::clone(id); async move { - let _ = carl.cluster.store_cluster_deployment(&ClusterDeployment { id }).await; + let _ = carl.cluster.store_cluster_deployment(ClusterDeployment { id }).await; } }); diff --git a/opendut-vpn/opendut-vpn-netbird/src/client/implementation.rs b/opendut-vpn/opendut-vpn-netbird/src/client/implementation.rs index ec2764960..2c68a05bf 100644 --- a/opendut-vpn/opendut-vpn-netbird/src/client/implementation.rs +++ b/opendut-vpn/opendut-vpn-netbird/src/client/implementation.rs @@ -413,7 +413,6 @@ fn json_header_value() -> HeaderValue { .expect("MIME type for application/json should always be convertable to a header value.") } - ///Verify compatibility with examples from here: https://docs.netbird.io/api #[cfg(test)] mod tests {