From 60723896730db99ab56ff6ec5aac440ad16b01b7 Mon Sep 17 00:00:00 2001 From: Abhilash Shetty Date: Thu, 23 Jan 2025 13:59:35 +0000 Subject: [PATCH] feat(plugin): add support to fetch ns from kubeconfig context If '--namespace-from-context' flag is set then we fetch ns from the kubeconfig context. Its hidden to users now. Incase user has not given -n flag and --namespace-from-context we default to "mayastor". If they have used --namespace-from-context flag then we get ns from kubeconfig. If kubeconfig path is specified then we use client of that kubeconfig or else we get default kubeconfig client. Signed-off-by: Abhilash Shetty --- Cargo.lock | 1 + constants/src/lib.rs | 2 ++ k8s/plugin/Cargo.toml | 1 + k8s/plugin/src/main.rs | 64 +++++++++++++++++++++++++++--------------- 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ef7d11cc..c2845a43e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2234,6 +2234,7 @@ dependencies = [ "console-logger", "constants", "humantime", + "kube 0.94.2", "kube-forward", "kube-proxy", "openapi", diff --git a/constants/src/lib.rs b/constants/src/lib.rs index f608b1e39..832428bb6 100644 --- a/constants/src/lib.rs +++ b/constants/src/lib.rs @@ -24,6 +24,8 @@ pub fn upgrade_job_container_name() -> String { pub fn upgrade_event_reason() -> String { format!("{}Upgrade", product_train()) } +/// Default namespace for plugin. +pub const DEFAULT_PLUGIN_NAMESPACE: &str = "mayastor"; /// Upgrade job container image repository. pub const UPGRADE_JOB_IMAGE_REPO: &str = "openebs"; /// This is the user docs URL for the Umbrella chart. diff --git a/k8s/plugin/Cargo.toml b/k8s/plugin/Cargo.toml index e53a41748..4b4e67651 100644 --- a/k8s/plugin/Cargo.toml +++ b/k8s/plugin/Cargo.toml @@ -24,6 +24,7 @@ rest-plugin = { path = "../../dependencies/control-plane/control-plane/plugin", console-logger = { path = "../../console-logger" } supportability = { path = "../supportability" } upgrade = { path = "../upgrade" } +kube = { version = "0.94.2", features = ["derive", "runtime"] } kube-proxy = { path = "../../dependencies/control-plane/k8s/proxy" } kube-forward = { path = "../../dependencies/control-plane/k8s/forward" } tokio = { version = "1.41.0" } diff --git a/k8s/plugin/src/main.rs b/k8s/plugin/src/main.rs index c4af5c6a3..0baa00e74 100644 --- a/k8s/plugin/src/main.rs +++ b/k8s/plugin/src/main.rs @@ -1,11 +1,10 @@ use clap::Parser; use plugin::ExecuteOperation; use resources::{init_rest, Error, Operations}; +pub mod resources; use std::{env, ops::Deref}; -pub mod resources; - #[derive(Parser, Debug)] #[clap(name = utils::package_description!(), version = utils::version_info_str!())] #[group(skip)] @@ -14,19 +13,32 @@ struct CliArgs { #[clap(subcommand)] operations: Operations, - /// Kubernetes namespace of mayastor service - #[clap(global = true, long, short = 'n', default_value = "mayastor")] - namespace: String, + /// Kubernetes namespace of mayastor service [default: mayastor]. + #[clap(global = true, long, short = 'n')] + namespace: Option, #[clap(flatten)] args: resources::CliArgs, + + /// Use namespace from the current `kubeconfig` context. + #[clap(global = true, long, hide = true, default_value = "false")] + namespace_from_context: bool, } impl CliArgs { - fn args() -> Self { + async fn args() -> Result { let mut args = CliArgs::parse(); - args.args.namespace = args.namespace.clone(); - args + args.args.namespace = if let Some(namespace) = &args.namespace { + namespace.to_string() + } else if args.namespace_from_context { + let client = kube_proxy::client_from_kubeconfig(args.args.kube_config_path.clone()) + .await + .map_err(|err| anyhow::anyhow!("{err}"))?; + client.default_namespace().to_string() + } else { + constants::DEFAULT_PLUGIN_NAMESPACE.to_string() + }; + Ok(args) } } @@ -40,23 +52,29 @@ impl Deref for CliArgs { #[tokio::main] async fn main() { - let cli_args = CliArgs::args(); - let _tracer_flusher = cli_args.init_tracing(); - - if let Err(error) = cli_args.execute().await { - let mut exit_code = 1; - match error { - Error::RestPlugin(error) => eprintln!("{error}"), - Error::RestClient(error) => { - eprintln!("Failed to initialise the REST client. Error {error}") - } - Error::Upgrade(error) => { - eprintln!("{error}"); - exit_code = error.into(); + let mut exit_code = 1; + match CliArgs::args().await { + Ok(cli_args) => { + let _tracer_flusher = cli_args.init_tracing(); + if let Err(error) = cli_args.execute().await { + match error { + Error::RestPlugin(error) => eprintln!("{error}"), + Error::RestClient(error) => { + eprintln!("Failed to initialise the REST client. Error {error}") + } + Error::Upgrade(error) => { + eprintln!("{error}"); + exit_code = error.into(); + } + Error::Generic(error) => eprintln!("{error}"), + } + std::process::exit(exit_code); } - Error::Generic(error) => eprintln!("{error}"), } - std::process::exit(exit_code); + Err(e) => { + eprintln!("{e}"); + std::process::exit(exit_code) + } } }