rkubectl-kubeapi 0.0.0-alpha.5

Kubernetes API wrapper for rkubectl, a Kubernetes CLI tool
Documentation
use kube::config::KubeConfigOptions;
use kube::config::Kubeconfig;
use kube::config::KubeconfigError;
use kube::config::NamedAuthInfo;
use kube::config::NamedCluster;
use kube::config::NamedContext;

use super::*;

impl Kubeapi {
    pub async fn kubeconfig(
        options: KubeConfigOptions,
        debug: bool,
    ) -> Result<(kube::Config, Kubeconfig), KubeconfigError> {
        let kubeconfig = Kubeconfig::read()
            .map(sanitize_kubeconfig)
            .inspect(|kubeconfig| {
                if debug {
                    debug!(kubeconfig = kubeconfig.debug())
                }
            })?;

        kube::Config::from_custom_kubeconfig(kubeconfig.clone(), &options)
            .await
            .inspect(|config| {
                if debug {
                    debug!(?config)
                }
            })
            .inspect_err(|err| error!(%err, "from_kubeconfig"))
            .map(|config| (config, kubeconfig))
    }

    pub fn current_context(&self) -> Option<&str> {
        self.kubeconfig.current_context.as_deref()
    }

    pub fn get_clusters(&self) -> &[kube::config::NamedCluster] {
        self.clusters()
    }

    pub fn get_contexts(&self) -> &[kube::config::NamedContext] {
        self.contexts()
    }

    pub fn get_users(&self) -> &[kube::config::NamedAuthInfo] {
        self.authinfo()
    }

    pub fn view(&self) -> yaml::Result<String> {
        yaml::to_string(&self.kubeconfig)
    }

    fn clusters(&self) -> &[NamedCluster] {
        &self.kubeconfig.clusters
    }

    fn contexts(&self) -> &[NamedContext] {
        &self.kubeconfig.contexts
    }

    fn authinfo(&self) -> &[NamedAuthInfo] {
        &self.kubeconfig.auth_infos
    }
}

fn sanitize_kubeconfig(mut kubeconfig: Kubeconfig) -> Kubeconfig {
    if kubeconfig.current_context().is_none() {
        let context = kubeconfig.contexts.first().map(|ctx| ctx.name.clone());
        debug!(
            first = context,
            "Using first context instead of invalid current_context"
        );
        kubeconfig.current_context = context;
    }
    kubeconfig
}

trait KubeconfigExt {
    fn debug(&self) -> String;
    fn get_context(&self, context: &str) -> Option<&NamedContext>;
    fn current_context(&self) -> Option<&NamedContext>;
}

impl KubeconfigExt for Kubeconfig {
    fn debug(&self) -> String {
        yaml::to_string(self).unwrap_or_default()
    }

    fn get_context(&self, context: &str) -> Option<&NamedContext> {
        self.contexts.iter().find(|ctx| ctx.name == context)
    }

    fn current_context(&self) -> Option<&NamedContext> {
        let context = self.current_context.as_deref()?;
        self.get_context(context)
    }
}