diff --git a/src/cmd/context.rs b/src/cmd/context.rs index af46f668..fb320a7b 100644 --- a/src/cmd/context.rs +++ b/src/cmd/context.rs @@ -12,26 +12,73 @@ use crate::shell::spawn_shell; use crate::state::State; use crate::vars; -fn enter_context( +fn enter_cloned_context( settings: &Settings, installed: Installed, - context_name: &str, namespace_name: Option<&str>, recursive: bool, ) -> Result<()> { + let session = Session::load()?; + + let previous_ctx = session + .get_last_context() + .context("There is no previous context to switch to.")?; + let namespace_name = namespace_name.or(previous_ctx.namespace.as_deref()); + let kubeconfig = installed.make_kubeconfig_for_context(&previous_ctx.context, namespace_name)?; + + if settings.behavior.validate_namespaces { + if let Some(namespace_name) = namespace_name { + let namespaces = kubectl::get_namespaces(Some(&kubeconfig))?; + if !namespaces.iter().any(|x| x == namespace_name) { + eprintln!("Warning: namespace {} does not exist.", namespace_name); + } + } + } + + if vars::is_kubie_active() && !recursive { + let path = kubeconfig::get_kubeconfig_path()?; + let file = File::create(&path).context("could not write in temporary KUBECONFIG file")?; + kubeconfig.write_to(file)?; + session.save(None)?; + } else { + spawn_shell(settings, kubeconfig, &session)?; + } + + Ok(()) +} + +fn enter_context( + settings: &Settings, + skim_optons: &SkimOptions, + mut installed: Installed, + context_name: Option, + mut namespace_name: Option<&str>, + recursive: bool, +) -> Result<()> { + let context_name = match context_name { + Some(context_name) => context_name, + None => match select_or_list_context(skim_optons, &mut installed)? { + SelectResult::Selected(x) => { + namespace_name = None; + x + } + _ => return Ok(()), + }, + }; + let state = State::load()?; let mut session = Session::load()?; let namespace_name = - namespace_name.or_else(|| state.namespace_history.get(context_name).and_then(|s| s.as_deref())); + namespace_name.or_else(|| state.namespace_history.get(&context_name).and_then(|s| s.as_deref())); - let kubeconfig = if context_name == "-" { + let kubeconfig = if &context_name == "-" { let previous_ctx = session - .get_last_context() + .get_previous_context() .context("There is no previous context to switch to.")?; installed.make_kubeconfig_for_context(&previous_ctx.context, previous_ctx.namespace.as_deref())? } else { - installed.make_kubeconfig_for_context(context_name, namespace_name)? + installed.make_kubeconfig_for_context(&context_name, namespace_name)? }; session.add_history_entry( @@ -64,26 +111,20 @@ pub fn context( settings: &Settings, skim_options: &SkimOptions, context_name: Option, - mut namespace_name: Option, + namespace_name: Option, kubeconfigs: Vec, + clone: bool, recursive: bool, ) -> Result<()> { - let mut installed = if kubeconfigs.is_empty() { + let installed = if kubeconfigs.is_empty() { kubeconfig::get_installed_contexts(settings)? } else { kubeconfig::get_kubeconfigs_contexts(&kubeconfigs)? }; - let context_name = match context_name { - Some(context_name) => context_name, - None => match select_or_list_context(skim_options, &mut installed)? { - SelectResult::Selected(x) => { - namespace_name = None; - x - } - _ => return Ok(()), - }, - }; - - enter_context(settings, installed, &context_name, namespace_name.as_deref(), recursive) + if clone { + enter_cloned_context(settings, installed, namespace_name.as_deref(), recursive) + } else { + enter_context(settings, skim_options, installed, context_name, namespace_name.as_deref(), recursive) + } } diff --git a/src/cmd/meta.rs b/src/cmd/meta.rs index 177bc569..fe352825 100644 --- a/src/cmd/meta.rs +++ b/src/cmd/meta.rs @@ -21,6 +21,10 @@ pub enum Kubie { #[clap(short = 'r', long = "recursive")] recursive: bool, + /// Spawn a new shell by cloning current shell context + #[structopt(short = 'c', long = "clone")] + clone: bool, + /// Name of the context to enter. Use '-' to switch back to the previous context. context_name: Option, }, diff --git a/src/main.rs b/src/main.rs index 5d419ee7..97303d92 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ fn main() -> Result<()> { namespace_name, context_name, kubeconfigs, + clone, recursive, } => { cmd::context::context( @@ -33,6 +34,7 @@ fn main() -> Result<()> { context_name, namespace_name, kubeconfigs, + clone, recursive, )?; } diff --git a/src/session.rs b/src/session.rs index f201a59c..5ccc7aa0 100644 --- a/src/session.rs +++ b/src/session.rs @@ -45,7 +45,7 @@ impl Session { }) } - pub fn get_last_context(&self) -> Option<&HistoryEntry> { + pub fn get_previous_context(&self) -> Option<&HistoryEntry> { let current_context = self.history.last()?; for entry in self.history.iter().rev().skip(1) { if current_context.context != entry.context { @@ -55,6 +55,10 @@ impl Session { None } + pub fn get_last_context(&self) -> Option<&HistoryEntry> { + return self.history.last() + } + pub fn get_last_namespace(&self) -> Option<&str> { let current_context = self.history.last()?; for entry in self.history.iter().rev().skip(1) {