#[macro_use]
extern crate duct;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde_derive;
#[macro_use]
mod output;
extern crate atomicwrites;
extern crate base64;
extern crate chrono;
#[macro_use]
extern crate clap;
extern crate comfy_table;
extern crate crossterm;
extern crate ctrlc;
extern crate derivative;
extern crate dirs;
extern crate duct_sh;
extern crate humantime;
extern crate os_pipe;
extern crate regex;
extern crate rustls;
extern crate rustyline;
extern crate serde;
extern crate serde_json;
extern crate serde_with;
extern crate serde_yaml;
extern crate strfmt;
extern crate tempdir;
extern crate bytes;
#[macro_use]
extern crate k8s_openapi;
extern crate reqwest;
extern crate url;
extern crate yasna;
#[macro_use]
mod command;
#[macro_use]
mod completer;
mod command_processor;
mod config;
mod crd;
mod describe;
mod env;
mod error;
mod k8s;
mod k8s_table;
mod kobj;
mod parser;
mod styles;
mod table;
mod values;
#[cfg(test)]
mod duct_mock;
use clap::{Arg, Command as ClapCommand};
use std::path::PathBuf;
use crate::command_processor::CommandProcessor;
use crate::config::{ClickConfig, Config};
use crate::env::Env;
use crate::output::ClickWriter;
fn main() {
env_logger::init();
let matches = ClapCommand::new("Click")
.version(crate_version!())
.author("Nick Lanham <nick@databricks.com>")
.about("Command Line Interactive Contoller for Kubernetes")
.arg(
Arg::new("config_dir")
.short('c')
.long("config_dir")
.value_name("DIR")
.help("Specify the directory to find kubernetes and click configs")
.takes_value(true),
)
.arg(
Arg::new("exec")
.long("exec")
.value_name("COMMAND")
.help("Execute the specified command then exit")
.takes_value(true),
)
.arg(
Arg::new("context")
.short('C')
.long("context")
.help("Start in the specified context")
.takes_value(true),
)
.arg(
Arg::new("namespace")
.short('n')
.long("namespace")
.help("Start in the specified namespace")
.takes_value(true),
)
.get_matches();
let conf_dir = if let Some(dir) = matches.value_of("config_dir") {
PathBuf::from(dir)
} else {
match dirs::home_dir() {
Some(mut path) => {
path.push(".kube");
path
}
None => {
println!("Can't get your home dir, please specify --config_dir");
std::process::exit(-2);
}
}
};
let mut click_path = conf_dir.clone();
click_path.push("click.config");
let click_conf = match ClickConfig::from_file(click_path.as_path().to_str().unwrap()) {
Ok(conf) => conf,
Err(e) => {
println!("Could not load click config: {}\nUsing default values.", e);
ClickConfig::default()
}
};
let config_paths = std::env::var_os("KUBECONFIG")
.map(|paths| {
let split_paths = std::env::split_paths(&paths);
split_paths.collect::<Vec<PathBuf>>()
})
.unwrap_or_else(|| {
let mut config_path = conf_dir.clone();
config_path.push("config");
vec![config_path]
})
.into_iter()
.map(|config_file| {
config_file
.as_path()
.to_str()
.unwrap_or("[CONFIG_PATH_EMPTY]")
.to_owned()
})
.collect::<Vec<_>>();
let config = match Config::from_files(&config_paths) {
Ok(c) => c,
Err(e) => {
println!(
"Could not load kubernetes config. Cannot continue. Error was: {}",
e
);
return;
}
};
let mut hist_path = conf_dir;
hist_path.push("click.history");
let mut env = Env::new(config, click_conf, click_path);
if let Some(context) = matches.value_of("context") {
env.set_context(Some(context));
}
if let Some(namespace) = matches.value_of("namespace") {
env.set_namespace(Some(namespace));
}
let mut processor = CommandProcessor::new(env, hist_path);
if let Some(command) = matches.value_of("exec") {
let writer = ClickWriter::new();
processor.process_line(command, writer);
} else {
processor.run_repl();
}
}