use describe;
use kube::Metadata;
use output::ClickWriter;
use values::val_str_opt;
use Env;
use ansi_term::ANSIString;
use ansi_term::Colour::{Blue, Cyan, Green, Purple, Red, Yellow};
use clap::ArgMatches;
use serde::ser::Serialize;
use serde_json::Value;
use std::io::Write;
#[derive(Clone, Debug, PartialEq)]
pub enum ObjType {
Pod { containers: Vec<String> },
Node,
Deployment,
Service,
ReplicaSet,
StatefulSet,
ConfigMap,
Secret,
Job,
}
#[derive(Clone, Debug, PartialEq)]
pub struct KObj {
pub name: String,
pub namespace: Option<String>,
pub typ: ObjType,
}
fn maybe_full_describe_output<T: ?Sized>(
matches: &ArgMatches,
value: &T,
writer: &mut ClickWriter,
) -> bool
where
T: Serialize,
{
if matches.is_present("json") {
writer.pretty_color_json(value).unwrap_or(());
true
} else if matches.is_present("yaml") {
writer.print_yaml(value).unwrap_or(());
true
} else {
false
}
}
static NOTSUPPORTED: &str = "not supported without -j or -y yet\n";
impl KObj {
pub fn from_metadata(metadata: &Metadata, typ: ObjType) -> KObj {
KObj {
name: metadata.name.clone(),
namespace: metadata.namespace.clone(),
typ,
}
}
pub fn from_value(value: &Value, typ: ObjType) -> Option<KObj> {
val_str_opt("/metadata/name", value).map(|name| KObj {
name,
namespace: val_str_opt("/metadata/namespace", value),
typ,
})
}
pub fn name(&self) -> &str {
&self.name
}
pub fn type_str(&self) -> &str {
match self.typ {
ObjType::Pod { .. } => "Pod",
ObjType::Node => "Node",
ObjType::Deployment => "Deployment",
ObjType::Service => "Service",
ObjType::ReplicaSet => "ReplicaSet",
ObjType::StatefulSet => "StatefulSet",
ObjType::ConfigMap => "ConfigMap",
ObjType::Secret => "Secret",
ObjType::Job => "Job",
}
}
pub fn prompt_str(&self) -> ANSIString {
match self.typ {
ObjType::Pod { .. } => Yellow.bold().paint(self.name.as_str()),
ObjType::Node => Blue.bold().paint(self.name.as_str()),
ObjType::Deployment => Purple.bold().paint(self.name.as_str()),
ObjType::Service => Cyan.bold().paint(self.name.as_str()),
ObjType::ReplicaSet => Green.bold().paint(self.name.as_str()),
ObjType::StatefulSet => Green.bold().paint(self.name.as_str()),
ObjType::ConfigMap => Purple.bold().paint(self.name.as_str()),
ObjType::Secret => Red.bold().paint(self.name.as_str()),
ObjType::Job => Purple.bold().paint(self.name.as_str()),
}
}
pub fn is(&self, typ: ObjType) -> bool {
self.typ == typ
}
pub fn is_pod(&self) -> bool {
matches!(self.typ, ObjType::Pod { .. })
}
pub fn url(&self, namespace: &str) -> String {
match self.typ {
ObjType::Pod { .. } => format!("/api/v1/namespaces/{}/pods/{}", namespace, self.name),
ObjType::Node => format!("/api/v1/nodes/{}", self.name),
ObjType::Deployment => format!(
"/apis/extensions/v1beta1/namespaces/{}/deployments/{}",
namespace, self.name
),
ObjType::Service => format!("/api/v1/namespaces/{}/services/{}", namespace, self.name),
ObjType::ReplicaSet => format!(
"/apis/extensions/v1beta1/namespaces/{}/replicasets/{}",
namespace, self.name
),
ObjType::StatefulSet => format!(
"/apis/apps/v1beta1/namespaces/{}/statefulsets/{}",
namespace, self.name
),
ObjType::ConfigMap => {
format!("/api/v1/namespaces/{}/configmaps/{}", namespace, self.name)
}
ObjType::Secret => format!("/api/v1/namespaces/{}/secrets/{}", namespace, self.name),
ObjType::Job => format!("/apis/batch/v1/namespaces/{}/jobs/{}", namespace, self.name),
}
}
pub fn describe(&self, matches: &ArgMatches, env: &Env, writer: &mut ClickWriter) {
let namespace = match self.typ {
ObjType::Node => "",
_ => match self.namespace {
Some(ref ns) => ns,
None => {
clickwriteln!(writer, "Don't know namespace for {}", self.name());
return;
}
},
};
let url = self.url(namespace);
match env.run_on_kluster(|k| k.get_value(url.as_str())) {
Some(val) => {
if !maybe_full_describe_output(matches, &val, writer) {
match self.typ {
ObjType::Pod { .. } => {
clickwriteln!(writer, "{}", describe::describe_format_pod(val))
}
ObjType::Node => {
clickwriteln!(writer, "{}", describe::describe_format_node(val))
}
ObjType::Deployment => {
clickwriteln!(writer, "{}", describe::describe_format_deployment(val))
}
ObjType::Secret => {
clickwriteln!(writer, "{}", describe::describe_format_secret(val))
}
ObjType::Service => {
let url =
format!("/api/v1/namespaces/{}/endpoints/{}", namespace, self.name);
let endpoint_val = env.run_on_kluster(|k| k.get_value(url.as_str()));
clickwriteln!(
writer,
"{}",
describe::describe_format_service(val, endpoint_val)
)
}
_ => clickwriteln!(writer, "{} {}", self.type_str(), NOTSUPPORTED),
}
}
}
None => clickwriteln!(writer, "Failed to fetch info from cluster"),
}
}
}