use chrono::offset::Utc;
use clap::{Arg, Command as ClapCommand};
use comfy_table::Table;
use rustyline::completion::Pair as RustlinePair;
use crate::{
command::command_def::{exec_match, identity, start_clap, Cmd},
completer, config,
env::Env,
output::ClickWriter,
table::CellSpec,
};
use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{stderr, Write};
command!(
Clear,
"clear",
"Clear the currently selected kubernetes object",
identity,
vec!["clear"],
noop_complete!(),
no_named_complete!(),
|_, env, _| {
env.clear_current();
Ok(())
}
);
fn print_contexts(env: &Env, writer: &mut ClickWriter) {
let mut contexts: Vec<&String> = env.config.contexts.keys().collect();
contexts.sort();
let ctxs = contexts
.iter()
.map(|context| {
let mut row: Vec<CellSpec> = Vec::new();
let cluster = match env.config.clusters.get(*context) {
Some(c) => c.server.as_str(),
None => "[no cluster for context]",
};
row.push(CellSpec::with_colors(
(*context).clone().into(),
Some(env.styles.context_table_color().into()),
None,
));
row.push(cluster.into());
row
})
.collect();
crate::table::print_table(vec!["Context", "Api Server Address"], ctxs, env, writer);
}
command!(
Context,
"context",
"Set the current context (will clear any selected pod). \
With no argument, lists available contexts.",
|clap: ClapCommand<'static>| clap.arg(
Arg::new("context")
.help("The name of the context")
.required(false)
.index(1)
),
vec!["ctx", "context"],
vec![&completer::context_complete],
no_named_complete!(),
|matches, env, writer| {
if matches.is_present("context") {
let context = matches.value_of("context");
if let (&Some(ref cur), Some(c)) = (&env.context, context) {
if cur.name == c {
return Ok(());
}
}
env.set_context(context);
env.clear_current();
} else {
print_contexts(env, writer);
}
Ok(())
}
);
command!(
Contexts,
"contexts",
"List available contexts",
identity,
vec!["contexts", "ctxs"],
noop_complete!(),
no_named_complete!(),
|_, env, writer| {
print_contexts(env, writer);
Ok(())
}
);
command!(
EnvCmd,
"env",
"Print information about the current environment",
identity,
vec!["env"],
noop_complete!(),
no_named_complete!(),
|_matches, env, writer| {
clickwriteln!(writer, "{}", env);
Ok(())
}
);
command!(
Quit,
"quit",
"Quit click",
identity,
vec!["q", "quit", "exit"],
noop_complete!(),
no_named_complete!(),
|_, env, _| {
env.quit = true;
Ok(())
}
);
command!(
Range,
"range",
"List the objects that are in the currently selected range (see 'help ranges' for general \
information about ranges)",
identity,
vec!["range"],
noop_complete!(),
no_named_complete!(),
|_, env, writer| {
let mut table = Table::new();
table.set_header(vec!["Name", "Type", "Namespace"]);
env.apply_to_selection(writer, None, |obj, _| {
table.add_row(vec![
obj.name(),
obj.type_str(),
obj.namespace.as_deref().unwrap_or(""),
]);
Ok(())
})?;
crate::table::print_filled_table(&mut table, writer);
Ok(())
}
);
pub const SET_OPTS: &[&str] = &[
"completion_type",
"edit_mode",
"editor",
"kubectl_binary",
"terminal",
"range_separator",
"describe_include_events",
];
command!(
SetCmd,
"set",
"Set click options. (See 'help completion' and 'help edit_mode' for more information",
|clap: ClapCommand<'static>| {
clap.arg(
Arg::new("option")
.help("The click option to set")
.required(true)
.index(1)
.possible_values(SET_OPTS),
)
.arg(
Arg::new("value")
.help("The value to set the option to")
.required(true)
.index(2),
)
.after_help(
"Note that if your value contains a -, you'll need to tell click it's not an option by
passing '--' before.
Example:
# Set the range_separator (needs the '--' after set since the value contains a -)
set -- range_separator \"---- {name} [{namespace}] ----\"
# set edit_mode
set edit_mode emacs",
)
},
vec!["set"],
vec![&completer::setoptions_values_completer],
no_named_complete!(),
|matches, env, writer| {
let option = matches.value_of("option").unwrap(); let value = matches.value_of("value").unwrap(); let mut failed = false;
match option {
"completion_type" => match value {
"circular" => env.set_completion_type(config::CompletionType::Circular),
"list" => env.set_completion_type(config::CompletionType::List),
_ => {
clickwriteln!(
writer,
"Invalid completion type. Possible values are: [circular, list]"
);
failed = true;
}
},
"edit_mode" => match value {
"vi" => env.set_edit_mode(config::EditMode::Vi),
"emacs" => env.set_edit_mode(config::EditMode::Emacs),
_ => {
clickwriteln!(
writer,
"Invalid edit_mode. Possible values are: [emacs, vi]"
);
failed = true;
}
},
"editor" => {
env.set_editor(Some(value));
}
"terminal" => {
env.set_terminal(Some(value));
}
"kubectl_binary" => {
env.set_kubectl_binary(Some(value));
}
"range_separator" => {
env.click_config.range_separator = value.to_string();
}
"describe_include_events" => match value.parse() {
Ok(b) => env.click_config.describe_include_events = b,
Err(_) => {
clickwriteln!(
writer,
"describe_include_events must be set to 'true' or 'false'"
);
failed = true;
}
},
_ => {
write!(stderr(), "Invalid option\n").unwrap_or(());
failed = true;
}
}
if !failed {
clickwriteln!(writer, "Set {} to '{}'", option, value);
}
Ok(())
}
);
pub const UNSET_OPTS: &[&str] = &["editor", "kubectl_binary", "terminal", "range_separator"];
command!(
UnSetCmd,
"unset",
"Unset a click option. This returns to option to its default value.",
|clap: ClapCommand<'static>| {
clap.arg(
Arg::new("option")
.help("The click option to unset")
.required(true)
.index(1)
.possible_values(UNSET_OPTS),
)
},
vec!["unset"],
vec![&completer::unsetoptions_values_completer],
no_named_complete!(),
|matches, env, writer| {
let option = matches.value_of("option").unwrap(); let mut failed = false;
match option {
"editor" => {
env.set_editor(None);
}
"terminal" => {
env.set_terminal(None);
}
"kubectl_binary" => {
env.set_kubectl_binary(None);
}
"range_separator" => {
env.click_config.range_separator = crate::config::default_range_sep();
}
_ => {
write!(stderr(), "Invalid option\n").unwrap_or(());
failed = true;
}
}
if !failed {
clickwriteln!(writer, "Unset {}", option);
}
Ok(())
}
);
command!(
UtcCmd,
"utc",
"Print current time in UTC",
identity,
vec!["utc"],
noop_complete!(),
no_named_complete!(),
|_, _, writer| {
clickwriteln!(writer, "{}", Utc::now());
Ok(())
}
);