spacegate-config 0.2.0-alpha.4

A library-first, lightweight, high-performance, cloud-native supported API gateway
Documentation
use k8s_gateway_api::{Gateway, HttpRoute};
use k8s_openapi::api::core::v1::Secret;
use kube::{api::DeleteParams, Api, ResourceExt as _};
use spacegate_model::ext::k8s::crd::{http_spaceroute::HttpSpaceroute, sg_filter::SgFilter};

use crate::{
    service::{Delete, Retrieve as _},
    BoxResult,
};

use super::{
    convert::{filter_k8s_conv::PluginIdConv, gateway_k8s_conv::SgGatewayConv as _, route_k8s_conv::SgHttpRouteConv as _, ToTarget as _},
    K8s,
};

impl Delete for K8s {
    async fn delete_config_item_gateway(&self, gateway_name: &str) -> BoxResult<()> {
        let gateway_api: Api<Gateway> = self.get_namespace_api();

        if let Some(sg_gateway) = self.retrieve_config_item_gateway(gateway_name).await? {
            let (gateway, secret, delete_plugin_ids) = sg_gateway.to_kube_gateway(&self.namespace);

            if let Some(secret) = secret {
                let secret_api: Api<Secret> = self.get_namespace_api();
                secret_api.delete(&secret.name_any(), &DeleteParams::default()).await?;
            }

            for delete_plugin_id in delete_plugin_ids {
                delete_plugin_id.remove_filter_target(gateway.to_target_ref(), self).await?;
            }

            gateway_api.delete(gateway_name, &DeleteParams::default()).await?;
        }
        Ok(())
    }

    async fn delete_config_item_route(&self, gateway_name: &str, route_name: &str) -> BoxResult<()> {
        let http_spaceroute_api: Api<HttpSpaceroute> = self.get_namespace_api();
        let httproute_api: Api<HttpRoute> = self.get_namespace_api();

        if let Some(sg_http_route) = self.retrieve_config_item_route(gateway_name, route_name).await? {
            let (route, delete_plugin_ids) = sg_http_route.to_kube_httproute(gateway_name, route_name, &self.namespace);
            for delete_plugin_id in delete_plugin_ids {
                delete_plugin_id.remove_filter_target(route.to_target_ref(), self).await?;
            }
            match http_spaceroute_api.delete(route_name, &DeleteParams::default()).await {
                Ok(_) => Ok(()),
                Err(f_e) => match httproute_api.delete(route_name, &DeleteParams::default()).await {
                    Ok(_) => Ok(()),
                    Err(s_e) => Err(format!("Failed to delete route {}: httpspaceroute: {}, httproute: {}", route_name, f_e, s_e).into()),
                },
            }
        } else {
            Ok(())
        }
    }

    async fn delete_plugin(&self, id: &spacegate_model::PluginInstanceId) -> BoxResult<()> {
        let filter_api: Api<SgFilter> = self.get_namespace_api();
        if let Ok(filter) = filter_api.get(&id.name.to_raw_str()).await {
            if filter.spec.target_refs.is_empty() {
                filter_api.delete(&filter.name_any(), &DeleteParams::default()).await?;
            } else {
                return Err(format!(
                    "The filter have references [{}]",
                    filter.spec.target_refs.iter().map(|t| format!("{}", t)).collect::<Vec<String>>().join(", ")
                )
                .into());
            }
        }
        Ok(())
    }
}