init
This commit is contained in:
commit
4d683e9201
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Cargo.lock
|
||||||
|
target/
|
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "ykre"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["a-Sansara <dev]at[pluie]dot[org>"]
|
||||||
|
edition = "2018"
|
||||||
|
description = "Ykre is Yaml Kubernetes Resource Extractor"
|
||||||
|
license = "MIT"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = ["cli", "yaml", "kubernetes", "kustomize"]
|
||||||
|
categories = ["command-line-utilities"]
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
yaml-rust = "0.4"
|
31
README.md
Normal file
31
README.md
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Ykre
|
||||||
|
|
||||||
|
**Ykre** is a small cli program written in rust wich purpose is to extract from a list
|
||||||
|
of yaml documents, documents matching a specified condition. **Ykre** goal is to find
|
||||||
|
specific Kubernetes Resource from the kustomize output.
|
||||||
|
**Ykre** stands for **Y**aml **K**ubernetes **R**esources **E**ctractor.
|
||||||
|
|
||||||
|
## usage
|
||||||
|
```
|
||||||
|
ykre SEARCH [DEF]
|
||||||
|
```
|
||||||
|
|
||||||
|
## examples
|
||||||
|
|
||||||
|
display content of the kubernetes resource 'myResourceName'
|
||||||
|
```
|
||||||
|
cat kubresources.yaml | ykre 'myResourceName'
|
||||||
|
```
|
||||||
|
write content of the kubernetes resource 'pv-dump' into a file
|
||||||
|
```
|
||||||
|
kustomize build ./config/volumes/local | ykre 'pv-dump' > ./tmp.yaml
|
||||||
|
```
|
||||||
|
retriew kubernetes pv resources matching 2Gi disk capacity
|
||||||
|
```
|
||||||
|
kustomize build ./config/volumes/dev | ykre 2Gi spec.capacity.storage
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
BIN
dist/ykre_0.1.0_amd64.deb
vendored
Normal file
BIN
dist/ykre_0.1.0_amd64.deb
vendored
Normal file
Binary file not shown.
29
src/main.rs
Normal file
29
src/main.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
extern crate yaml_rust;
|
||||||
|
pub mod ykre;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
use std::panic;
|
||||||
|
|
||||||
|
const PANIC_BYPASS_FILE : &str = "src/ykre/pipin.rs";
|
||||||
|
const PANIC_BYPASS_LINE : u32 = 9;
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
|
||||||
|
panic::set_hook(Box::new(|_info| {
|
||||||
|
let mut bypass :bool = false;
|
||||||
|
if let Some(location) = &_info.location() {
|
||||||
|
bypass = location.file() == PANIC_BYPASS_FILE && location.line() == PANIC_BYPASS_LINE;
|
||||||
|
}
|
||||||
|
if !bypass {
|
||||||
|
//~ println!("{:?}", &_info);
|
||||||
|
if let Some(s) = &_info.payload().downcast_ref::<&str>() {
|
||||||
|
if s.len() > 1 {
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
ykre::run();
|
||||||
|
Ok(())
|
||||||
|
}
|
56
src/ykre.rs
Normal file
56
src/ykre.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
mod yaml;
|
||||||
|
mod pipin;
|
||||||
|
mod app;
|
||||||
|
|
||||||
|
pub use self::yaml::YamlDocument;
|
||||||
|
pub use self::pipin::{spawn_stdin, sleep};
|
||||||
|
pub use self::app::{run};
|
||||||
|
|
||||||
|
const YKRE_LIMIT_ATTEMPT : u64 = 900;
|
||||||
|
const YKRE_SLEEP_START : u64 = 50;
|
||||||
|
const YKRE_SLEEP_DATA : u64 = 1;
|
||||||
|
const YKRE_SLEEP_NODATA : u64 = 1;
|
||||||
|
const YKRE_DEFAULT_DEF : &str = "metadata.name";
|
||||||
|
const YKRE_ERROR_NOTFOUND : &str = r"
|
||||||
|
:: Ykre ::
|
||||||
|
|
||||||
|
error : no match found for specified pattern
|
||||||
|
";
|
||||||
|
const YKRE_ERROR_INVALID : &str = r"
|
||||||
|
:: Ykre ::
|
||||||
|
|
||||||
|
error : invalid parameter. type ykre for usage
|
||||||
|
";
|
||||||
|
const YKRE_ERROR_NOPIPE : &str = r"
|
||||||
|
:: Ykre ::
|
||||||
|
|
||||||
|
error : you must send data using pipe
|
||||||
|
";
|
||||||
|
const YKRE_HELP : &str = r"
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
:: Ykre :: v0.1 license : MIT - author : a-Sansara
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Ykre is a small program written in `rust` wich purpose is to extract from a list
|
||||||
|
of yaml documents, documents matching a specified condition. Ykre goal is to find
|
||||||
|
specific Kubernetes Resource from the kustomize output.
|
||||||
|
Ykre stands for Yaml Kubernetes Resources Ectractor.
|
||||||
|
|
||||||
|
Usage :
|
||||||
|
|
||||||
|
ykre SEARCH [DEF]
|
||||||
|
|
||||||
|
you MUST use pipe with ykre command
|
||||||
|
|
||||||
|
SEARCH - value of kubernetes resource name
|
||||||
|
DEF - the yaml node to look for
|
||||||
|
(default : 'metadata.name', dot is the separator for embed nodes)
|
||||||
|
|
||||||
|
ex :
|
||||||
|
# display content of the kubernetes resource 'myResourceName'
|
||||||
|
cat kubresources.yaml | ykre 'myResourceName'
|
||||||
|
# write content of the kubernetes resource 'pv-dump' into a file
|
||||||
|
kustomize build ./config/volumes/local | ykre 'pv-dump' > ./tmp.yaml
|
||||||
|
# retriew kubernetes pv resources matching 2Gi disk capacity
|
||||||
|
kustomize build ./config/volumes/dev | ykre 2Gi spec.capacity.storage
|
||||||
|
";
|
67
src/ykre/app.rs
Normal file
67
src/ykre/app.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use std::panic;
|
||||||
|
use std::env;
|
||||||
|
use std::sync::mpsc::TryRecvError;
|
||||||
|
|
||||||
|
use crate::ykre::*;
|
||||||
|
|
||||||
|
pub fn find(search: &str, def: &str, data:String) {
|
||||||
|
let doc = YamlDocument::load_str(data);
|
||||||
|
let rs = doc.match_docs(&def, &search);
|
||||||
|
if !rs.is_empty() {
|
||||||
|
for i in rs.iter() {
|
||||||
|
println!("{}", doc.dump(*i));
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
panic!(YKRE_ERROR_NOTFOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_data(buf :&mut String, limit :u32) -> bool {
|
||||||
|
let stdin = spawn_stdin();
|
||||||
|
let mut attempt = 0;
|
||||||
|
let mut has_data :bool = false;
|
||||||
|
sleep(YKRE_SLEEP_START);
|
||||||
|
while attempt < limit {
|
||||||
|
let rs = match stdin.try_recv() {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(TryRecvError::Empty) => String::from(""),
|
||||||
|
Err(TryRecvError::Disconnected) => String::from(""),
|
||||||
|
};
|
||||||
|
if !rs.is_empty() {
|
||||||
|
*buf += &rs;
|
||||||
|
has_data = true;
|
||||||
|
}
|
||||||
|
else if has_data {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
attempt += 1;
|
||||||
|
sleep(match has_data {
|
||||||
|
true => YKRE_SLEEP_DATA,
|
||||||
|
_ => YKRE_SLEEP_NODATA,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return has_data
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run() {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() == 1 {
|
||||||
|
println!("{}", YKRE_HELP);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else if args.len() > 1 && args.len() <= 3 {
|
||||||
|
|
||||||
|
let mut buf :String = String::from("");
|
||||||
|
let search :&str = &args[1];
|
||||||
|
let def :&str = match args.len() {
|
||||||
|
3 => &args[2],
|
||||||
|
_ => YKRE_DEFAULT_DEF,
|
||||||
|
};
|
||||||
|
let limit : u32 = env::var("YKRE_LIMIT_ATTEMPT").unwrap_or(format!("{}", YKRE_LIMIT_ATTEMPT).to_owned()).parse::<u32>().unwrap();
|
||||||
|
if get_data(&mut buf, limit) {
|
||||||
|
return find(search, def, buf);
|
||||||
|
}
|
||||||
|
panic!(YKRE_ERROR_NOPIPE)
|
||||||
|
}
|
||||||
|
panic!(YKRE_ERROR_INVALID)
|
||||||
|
}
|
17
src/ykre/pipin.rs
Normal file
17
src/ykre/pipin.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
use std::{io, thread, time, sync::mpsc};
|
||||||
|
use std::sync::mpsc::Receiver;
|
||||||
|
|
||||||
|
pub fn spawn_stdin() -> Receiver<String> {
|
||||||
|
let (tx, rx) = mpsc::channel::<String>();
|
||||||
|
let _child = thread::spawn(move || loop {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
io::stdin().read_line(&mut buffer).unwrap();
|
||||||
|
tx.send(buffer).unwrap()
|
||||||
|
});
|
||||||
|
rx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sleep(millis: u64) {
|
||||||
|
let duration = time::Duration::from_millis(millis);
|
||||||
|
thread::sleep(duration);
|
||||||
|
}
|
68
src/ykre/yaml.rs
Normal file
68
src/ykre/yaml.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
use yaml_rust::{YamlLoader, Yaml, YamlEmitter};
|
||||||
|
use std::vec::Vec;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct YamlDocument {
|
||||||
|
path: String,
|
||||||
|
content: String,
|
||||||
|
docs: Vec<yaml_rust::Yaml>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl YamlDocument {
|
||||||
|
|
||||||
|
fn loaded_from(content: String, source: Option<String>) -> YamlDocument {
|
||||||
|
let docs = YamlLoader::load_from_str(&content).unwrap();
|
||||||
|
let path = source.unwrap_or("".to_owned());
|
||||||
|
YamlDocument { path, content, docs }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_str(content: String) -> YamlDocument {
|
||||||
|
Self::loaded_from(content, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_str(&self, path: &str, index: usize) -> Option<&str> {
|
||||||
|
let search = path.to_string();
|
||||||
|
let v: Vec<&str> = search.split(".").collect();
|
||||||
|
let mut node: &Yaml = &self.docs[index];
|
||||||
|
for key in &v {
|
||||||
|
node = &node[*key];
|
||||||
|
}
|
||||||
|
node.as_str().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump(&self, index: usize) -> String {
|
||||||
|
let doc = &self.docs[index];
|
||||||
|
let mut out_str = String::new();
|
||||||
|
{
|
||||||
|
let mut emitter = YamlEmitter::new(&mut out_str);
|
||||||
|
emitter.dump(doc).unwrap();
|
||||||
|
}
|
||||||
|
out_str
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn match_doc(&self, search: &str, matched: &str) -> Option<usize> {
|
||||||
|
let mut index = 0;
|
||||||
|
let mut rs: Option<usize> = None;
|
||||||
|
while index < self.docs.len() {
|
||||||
|
match &self.find_str(search, index) {
|
||||||
|
Some(ref s) if s == &matched => rs = Some(index),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
rs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn match_docs(&self, search: &str, matched: &str) -> Vec<usize> {
|
||||||
|
let mut v: Vec<usize> = Vec::new();
|
||||||
|
let mut index = 0;
|
||||||
|
while index < self.docs.len() {
|
||||||
|
match &self.find_str(search, index) {
|
||||||
|
Some(ref s) if s == &matched => v.push(index),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
v
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user