From 3847aa0bbd6b84688bcbcf0fd5d552beb821ca51 Mon Sep 17 00:00:00 2001 From: Morten Lied Johansen Date: Fri, 29 Sep 2023 12:53:34 +0200 Subject: [PATCH] Implement AivenObject for DynamicObject, eliminating need for specific types All relevant objects have data in the same fields, and the DynamicObject allows generic access to those fields. It makes much more sense to implement mutations on the basis of the generic access in DynamicObject, than implementing the AivenObject trait for all Aiven types with identical code for each type. --- src/aiven_types/mod.rs | 33 +++++++++++++++++++++++++++++++++ src/web.rs | 30 +----------------------------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/aiven_types/mod.rs b/src/aiven_types/mod.rs index 6ebbf29..3d91cb0 100644 --- a/src/aiven_types/mod.rs +++ b/src/aiven_types/mod.rs @@ -1,3 +1,4 @@ +use kube::core::DynamicObject; use std::collections::BTreeMap; use crate::aiven_types::aiven_opensearches::OpenSearch; @@ -34,6 +35,38 @@ pub trait AivenObject { } } +impl AivenObject for DynamicObject { + fn get_cloud_name(&self) -> Option { + self.data["spec"]["cloudName"] + .as_str() + .map(|s| s.to_string()) + } + + fn get_team_name(&self) -> Option { + self.metadata.namespace.clone() + } + + fn get_tags(&self) -> Option> { + self.data["spec"]["tags"].as_object().map(|o| { + o.iter() + .map(|(k, v)| (k.to_owned(), v.as_str().unwrap_or("").to_string())) + .collect() + }) + } + + fn get_termination_protection(&self) -> Option { + self.data["spec"]["terminationProtection"] + .as_bool() + .map(|b| b.to_owned()) + } + + fn get_project_vpc_id(&self) -> Option { + self.data["spec"]["projectVpcId"] + .as_str() + .map(|s| s.to_string()) + } +} + impl AivenObject for Redis { fn get_cloud_name(&self) -> Option { self.spec.cloud_name.clone() diff --git a/src/web.rs b/src/web.rs index 4fdac7b..de05bab 100644 --- a/src/web.rs +++ b/src/web.rs @@ -12,8 +12,6 @@ use kube::core::DynamicObject; use kube::ResourceExt; use tracing::{debug, error, info, info_span, instrument, warn}; -use crate::aiven_types::aiven_opensearches::OpenSearch; -use crate::aiven_types::aiven_redis::Redis; use crate::aiven_types::AivenObject; use crate::mutators; use crate::settings::AppConfig; @@ -93,33 +91,7 @@ async fn mutate_handler( let _resource_guard = resource_span.enter(); info!("Processing {} resource", req.kind.kind); - let resource: Box = match req.kind.kind.as_str() { - "Redis" => { - let redis: Redis = match obj.clone().try_parse() { - Ok(redis) => redis, - Err(err) => { - error!("Unable to parse Redis object: {}", err.to_string()); - return bad_request("unable to parse Redis object"); - }, - }; - Box::new(redis) - }, - "OpenSearch" => { - let open_search: OpenSearch = match obj.clone().try_parse() { - Ok(open_search) => open_search, - Err(err) => { - error!("Unable to parse OpenSearch object: {}", err.to_string()); - return bad_request("unable to parse OpenSearch object"); - }, - }; - Box::new(open_search) - }, - _ => { - return bad_request("unsupported resource type"); - }, - }; - - res = match mutate(res.clone(), resource, &config) { + res = match mutate(res.clone(), Box::new(obj.to_owned()), &config) { Ok(res) => { info!("Processing complete"); res