diff --git a/influxdb_iox/tests/end_to_end_cases/router_api.rs b/influxdb_iox/tests/end_to_end_cases/router_api.rs index 0e8675287c..0bb3620434 100644 --- a/influxdb_iox/tests/end_to_end_cases/router_api.rs +++ b/influxdb_iox/tests/end_to_end_cases/router_api.rs @@ -1,4 +1,8 @@ -use influxdb_iox_client::router::generated_types::{QuerySinks, Router}; +use influxdb_iox_client::router::{ + generated_types::{Matcher, MatcherToShard, QuerySinks, Router, ShardConfig}, + UpdateRouterError, +}; +use test_helpers::assert_error; use crate::{ common::server_fixture::{ServerFixture, ServerType}, @@ -7,7 +11,7 @@ use crate::{ #[tokio::test] async fn test_router_crud() { - let server_fixture = ServerFixture::create_shared(ServerType::Router).await; + let server_fixture = ServerFixture::create_single_use(ServerType::Router).await; let mut client = server_fixture.router_client(); let router_name_a = rand_name(); @@ -65,3 +69,44 @@ async fn test_router_crud() { assert_eq!(&routers[0], &cfg_bar); client.delete_router(&router_name_b).await.unwrap(); } + +#[tokio::test] +async fn test_router_update_invalid_argument() { + let server_fixture = ServerFixture::create_single_use(ServerType::Router).await; + let mut client = server_fixture.router_client(); + + let router_name = rand_name(); + + let cfg_valid = Router { + name: router_name.clone(), + write_sharder: Default::default(), + write_sinks: Default::default(), + query_sinks: Default::default(), + }; + let cfg_invalid = Router { + write_sharder: Some(ShardConfig { + specific_targets: vec![MatcherToShard { + matcher: Some(Matcher { + table_name_regex: "*".to_owned(), + }), + shard: 1, + }], + hash_ring: None, + }), + ..cfg_valid.clone() + }; + + // invalid args don't create routers + let res = client.update_router(cfg_invalid.clone()).await; + assert_error!(res, UpdateRouterError::InvalidArgument(_)); + let routers = client.list_routers().await.unwrap(); + assert_eq!(routers.len(), 0); + + // invalid args don't update routesr + client.update_router(cfg_valid.clone()).await.unwrap(); + let res = client.update_router(cfg_invalid).await; + assert_error!(res, UpdateRouterError::InvalidArgument(_)); + let routers = client.list_routers().await.unwrap(); + assert_eq!(routers.len(), 1); + assert_eq!(&routers[0], &cfg_valid); +} diff --git a/influxdb_iox_client/src/client/router.rs b/influxdb_iox_client/src/client/router.rs index d58189be97..bd5df95733 100644 --- a/influxdb_iox_client/src/client/router.rs +++ b/influxdb_iox_client/src/client/router.rs @@ -13,6 +13,10 @@ pub mod generated_types { /// Errors returned by Client::list_routers #[derive(Debug, Error)] pub enum ListRoutersError { + /// Server indicated that it is not (yet) available + #[error("Server unavailable: {}", .0.message())] + Unavailable(tonic::Status), + /// Client received an unexpected error from the server #[error("Unexpected server error: {}: {}", .0.code(), .0.message())] ServerError(tonic::Status), @@ -21,6 +25,14 @@ pub enum ListRoutersError { /// Errors returned by Client::update_router #[derive(Debug, Error)] pub enum UpdateRouterError { + /// Server indicated that it is not (yet) available + #[error("Server unavailable: {}", .0.message())] + Unavailable(tonic::Status), + + /// Server returned an invalid argument error + #[error("Invalid argument: {}", .0.message())] + InvalidArgument(tonic::Status), + /// Client received an unexpected error from the server #[error("Unexpected server error: {}: {}", .0.code(), .0.message())] ServerError(tonic::Status), @@ -29,6 +41,10 @@ pub enum UpdateRouterError { /// Errors returned by Client::delete_router #[derive(Debug, Error)] pub enum DeleteRouterError { + /// Server indicated that it is not (yet) available + #[error("Server unavailable: {}", .0.message())] + Unavailable(tonic::Status), + /// Client received an unexpected error from the server #[error("Unexpected server error: {}: {}", .0.code(), .0.message())] ServerError(tonic::Status), @@ -80,7 +96,11 @@ impl Client { .inner .list_routers(ListRoutersRequest {}) .await - .map_err(ListRoutersError::ServerError)?; + .map_err(|status| match status.code() { + tonic::Code::Unavailable => ListRoutersError::Unavailable(status), + _ => ListRoutersError::ServerError(status), + })?; + Ok(response.into_inner().routers) } @@ -94,18 +114,27 @@ impl Client { router: Some(config), }) .await - .map_err(UpdateRouterError::ServerError)?; + .map_err(|status| match status.code() { + tonic::Code::Unavailable => UpdateRouterError::Unavailable(status), + tonic::Code::InvalidArgument => UpdateRouterError::InvalidArgument(status), + _ => UpdateRouterError::ServerError(status), + })?; + Ok(()) } /// Delete router - pub async fn delete_router(&mut self, router_name: &str) -> Result<(), UpdateRouterError> { + pub async fn delete_router(&mut self, router_name: &str) -> Result<(), DeleteRouterError> { self.inner .delete_router(DeleteRouterRequest { router_name: router_name.to_string(), }) .await - .map_err(UpdateRouterError::ServerError)?; + .map_err(|status| match status.code() { + tonic::Code::Unavailable => DeleteRouterError::Unavailable(status), + _ => DeleteRouterError::ServerError(status), + })?; + Ok(()) } }