summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas O'Donnell <andytom@users.noreply.github.com>2019-10-01 20:58:24 +0200
committerKevin Song <chipbuster@users.noreply.github.com>2019-10-01 13:58:24 -0500
commit9fc5a43355bb89e06db99322269b7cc09d7a36e9 (patch)
treeb8e9b2b2335b65b4875af5baef36abcbd45c7398
parent6888f3619a099ed63c54d0fa4a46bce056951f58 (diff)
feat: Add Kubernetes Module (#404)
Adds a Kubernetes module, which works by parsing kubeconfig.
-rw-r--r--Cargo.lock16
-rw-r--r--README.md1
-rw-r--r--docs/config/README.md30
-rw-r--r--starship/Cargo.toml1
-rw-r--r--starship/src/module.rs1
-rw-r--r--starship/src/modules/kubernetes.rs182
-rw-r--r--starship/src/modules/mod.rs2
7 files changed, 233 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 607c8d976..c42e9c014 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -403,6 +403,11 @@ dependencies = [
]
[[package]]
+name = "linked-hash-map"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -772,6 +777,7 @@ dependencies = [
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1002,6 +1008,14 @@ dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "yaml-rust"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[metadata]
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
@@ -1051,6 +1065,7 @@ dependencies = [
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum libgit2-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a30f8637eb59616ee3b8a00f6adff781ee4ddd8343a615b8238de756060cc1b3"
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
+"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
@@ -1126,3 +1141,4 @@ dependencies = [
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9"
+"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"
diff --git a/README.md b/README.md
index 4943206ba..79e7dfc31 100644
--- a/README.md
+++ b/README.md
@@ -85,6 +85,7 @@ The prompt shows information you need while you're working, while staying sleek
- `✘` — deleted files
- Execution time of the last command if it exceeds the set threshold
- Indicator for jobs in the background (`✦`)
+- Current Kubernetes Cluster and Namespace (`☸`)
## 🚀 Installation
diff --git a/docs/config/README.md b/docs/config/README.md
index be29f2bc4..5e2cf8de6 100644
--- a/docs/config/README.md
+++ b/docs/config/README.md
@@ -85,6 +85,7 @@ The default `prompt_order` is used to define the order in which modules are show
prompt_order = [
"username",
"hostname",
+ "kubernetes",
"directory",
"git_branch",
"git_state",
@@ -528,6 +529,35 @@ symbol = "+ "
threshold = 4
```
+
+## Kubernetes
+
+Displays the current Kubernetes context name and, if set, the namespace from
+the kubeconfig file. The namespace needs to be set in the kubeconfig file, this
+can be done via `kubectl config set-context starship-cluster --namespace
+astronaut`. If the `$KUBECONFIG` env var is set the module will use that if
+not it will use the `~/.kube/config`.
+
+### Options
+
+| Variable | Default | Description |
+| ---------- | ------------- | --------------------------------------------------- |
+| `symbol` | `"☸ "` | The symbol used before displaying the Cluster info. |
+| `style` | `"bold blue"` | The style for the module. |
+| `disabled` | `false` | Disables the `kubernetes` module |
+
+### Example
+
+```toml
+# ~/.config/starship.toml
+
+[kubernetes]
+symbol = "⛵ "
+style = "dim green"
+disabled = true
+```
+
+
## Line Break
The `line_break` module separates the prompt into two lines.
diff --git a/starship/Cargo.toml b/starship/Cargo.toml
index 4c4c27215..66fbacc2e 100644
--- a/starship/Cargo.toml
+++ b/starship/Cargo.toml
@@ -45,6 +45,7 @@ chrono = "0.4"
sysinfo = "0.9.5"
byte-unit = "3.0.3"
starship_module_config_derive = { version = "0.20", path = "../starship_module_config_derive" }
+yaml-rust = "0.4"
[dev-dependencies]
tempfile = "3.1.0"
diff --git a/starship/src/module.rs b/starship/src/module.rs
index e1bfb97ff..8ebb89fd3 100644
--- a/starship/src/module.rs
+++ b/starship/src/module.rs
@@ -20,6 +20,7 @@ pub const ALL_MODULES: &[&str] = &[
"hostname",
"java",
"jobs",
+ "kubernetes",
"line_break",
"memory_usage",
"nix_shell",
diff --git a/starship/src/modules/kubernetes.rs b/starship/src/modules/kubernetes.rs
new file mode 100644
index 000000000..5142c7dd6
--- /dev/null
+++ b/starship/src/modules/kubernetes.rs
@@ -0,0 +1,182 @@
+use ansi_term::Color;
+use dirs;
+use yaml_rust::YamlLoader;
+
+use std::env;
+use std::path;
+
+use super::{Context, Module};
+use crate::utils;
+
+const KUBE_CHAR: &str = "☸ ";
+
+fn get_kube_context(contents: &str) -> Option<(String, String)> {
+ let yaml_docs = YamlLoader::load_from_str(&contents).ok()?;
+ if yaml_docs.is_empty() {
+ return None;
+ }
+ let conf = &yaml_docs[0];
+
+ let current_ctx = conf["current-context"].as_str()?;
+
+ if current_ctx.is_empty() {
+ return None;
+ }
+
+ let ns = conf["contexts"]
+ .as_vec()
+ .and_then(|contexts| {
+ contexts
+ .iter()
+ .filter_map(|ctx| Some((ctx, ctx["name"].as_str()?)))
+ .find(|(_, name)| *name == current_ctx)
+ .and_then(|(ctx, _)| ctx["context"]["namespace"].as_str())
+ })
+ .unwrap_or("");
+
+ Some((current_ctx.to_string(), ns.to_string()))
+}
+
+pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
+ let filename = match env::var("KUBECONFIG") {
+ Ok(path) => path::PathBuf::from(path),
+ Err(_) => dirs::home_dir()?.join(".kube").join("config"),
+ };
+
+ let contents = utils::read_file(filename).ok()?;
+
+ match get_kube_context(&contents) {
+ Some(kube_cfg) => {
+ let (kube_ctx, kube_ns) = kube_cfg;
+
+ let mut module = context.new_module("kubernetes");
+
+ let module_style = module
+ .config_value_style("style")
+ .unwrap_or_else(|| Color::Cyan.bold());
+ module.set_style(module_style);
+ module.get_prefix().set_value("on ");
+
+ module.new_segment("symbol", KUBE_CHAR);
+ module.new_segment("context", &kube_ctx);
+ if kube_ns != "" {
+ module.new_segment("namespace", &format!(" ({})", kube_ns));
+ }
+ Some(module)
+ }
+ None => None,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn parse_empty_config() {
+ let input = "";
+ let result = get_kube_context(&input);
+ let expected = None;
+
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ fn parse_no_config() {
+ let input = r#"
+apiVersion: v1
+clusters: []
+contexts: []
+current-context: ""
+kind: Config
+preferences: {}
+users: []
+"#;
+ let result = get_kube_context(&input);
+ let expected = None;
+
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ fn parse_only_context() {
+ let input = r#"
+apiVersion: v1
+clusters: []
+contexts:
+- context:
+ cluster: test_cluster
+ user: test_user
+ name: test_context
+current-context: test_context
+kind: Config
+preferences: {}
+users: []
+"#;
+ let result = get_kube_context(&input);
+ let expected = Some(("test_context".to_string(), "".to_string()));
+
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ fn parse_context_and_ns() {
+ let input = r#"
+apiVersion: v1
+clusters: []
+contexts:
+- context:
+ cluster: test_cluster
+ user: test_user
+ namespace: test_namespace
+ name: test_context
+current-context: test_context
+kind: Config
+preferences: {}
+users: []
+"#;
+ let result = get_kube_context(&input);
+ let expected = Some(("test_context".to_string(), "test_namespace".to_string()));
+
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ fn parse_multiple_contexts() {
+ let input = r#"
+apiVersion: v1
+clusters: []
+contexts:
+- context:
+ cluster: another_cluster
+ user: another_user
+ namespace: another_namespace
+ name: another_context
+- context:
+ cluster: test_cluster
+ user: test_user
+ namespace: test_namespace
+ name: test_context
+current-context: test_context
+kind: Config
+preferences: {}
+users: []
+"#;
+ let result = get_kube_context(&input);
+ let expected = Some(("test_context".to_string(), "test_namespace".to_string()));
+
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ fn parse_broken_config() {
+ let input = r#"
+---
+dummy_string
+"#;
+ let result = get_kube_context(&input);
+ let expected = None;
+
+ assert_eq!(result, expected);
+ }
+}
diff --git a/starship/src/modules/mod.rs b/starship/src/modules/mod.rs
index f073c5a6c..d5174ada2 100644
--- a/starship/src/modules/mod.rs
+++ b/starship/src/modules/mod.rs
@@ -11,6 +11,7 @@ mod golang;
mod hostname;
mod java;
mod jobs;
+mod kubernetes;
mod line_break;
mod memory_usage;
mod nix_shell;
@@ -44,6 +45,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
"git_branch" => git_branch::module(context),
"git_state" => git_state::module(context),
"git_status" => git_status::module(context),
+ "kubernetes" => kubernetes::module(context),
"username" => username::module(context),
#[cfg(feature = "battery")]
"battery" => battery::module(context),