Skip to content

Commit

Permalink
Merge pull request #12 from Ramilito/feature/batch-diffs
Browse files Browse the repository at this point in the history
[Feature] Add multithreaded execution
  • Loading branch information
Ramilito authored Dec 3, 2023
2 parents 7fb5d6f + 46466c1 commit 240c446
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 39 deletions.
19 changes: 13 additions & 6 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
use std::{
io::{Error, ErrorKind},
io::{Error, ErrorKind, Write},
process::{Child, Command, Stdio},

Check warning on line 3 in src/commands.rs

View workflow job for this annotation

GitHub Actions / Rust project (armv7-unknown-linux-musleabi)

unused import: `Child`

Check warning on line 3 in src/commands.rs

View workflow job for this annotation

GitHub Actions / Rust project (x86_64-pc-windows-gnu)

unused import: `Child`

Check warning on line 3 in src/commands.rs

View workflow job for this annotation

GitHub Actions / Rust project (x86_64-unknown-linux-gnu)

unused import: `Child`
sync::{Arc, Mutex},
};

use crate::logger::Logger;

pub struct Commands {}

impl Commands {
pub fn get_diff() -> Child {
Command::new("kubectl")
pub fn get_diff(input: &String) -> anyhow::Result<String> {
let mut diff = Command::new("kubectl")
.env("KUBECTL_EXTERNAL_DIFF", format!("{}", get_script()))
.arg("diff")
.arg("-f")
.arg("-")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap()
.unwrap();
let stdin = diff.stdin.as_mut().unwrap().write_all(input.as_bytes());
drop(stdin);

let diff = diff.wait_with_output().unwrap();
let string = String::from_utf8(diff.stdout.to_owned()).unwrap();
Ok(string)
}

pub fn get_build(logger: &Logger, target: &str) -> anyhow::Result<String> {
pub fn get_build(logger: Arc<Mutex<Logger>>, target: &str) -> anyhow::Result<String> {
let output = Command::new("kustomize")
.arg("build")
.arg(target)
Expand All @@ -33,7 +40,7 @@ impl Commands {
match output.status.success() {
true => Ok(String::from_utf8(output.stdout).expect("Couldn't read stdout of command")),
false => {
logger.log_error(
logger.lock().unwrap().log_error(
String::from_utf8(output.stderr).expect("Couldn't read stderr of command"),
);
Err(Error::new(
Expand Down
23 changes: 13 additions & 10 deletions src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@ impl Logger {
config_log,
}
}
pub fn log(&self, message: String) {
match &self.arg_log {
Some(LogLevel::Info) => Pretty::print_info(message),
Some(LogLevel::Warning) => println!("warning"),
Some(LogLevel::Error) => println!("Error"),
None => match &self.config_log {
LogLevel::Info => Pretty::print_info(message),
LogLevel::Warning => println!("config: warning"),
LogLevel::Error => println!("config error"),
},

pub fn log_info(&self, message: String) {
let level = self.arg_log.unwrap_or(self.config_log);
if level == LogLevel::Info {
Pretty::print_info(message)
};
}

pub fn log_warning(&self, message: String) {
let level = self.arg_log.unwrap_or(self.config_log);

if level == LogLevel::Warning || level == LogLevel::Info {
Pretty::print_warning(message)
};
}

Expand Down
20 changes: 17 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ mod print;
mod processor;
mod settings;

use std::{
path::Path,
sync::{Arc, Mutex},
};

use crate::{enums::LogLevel, logger::Logger, processor::Process, settings::Settings};
use clap::Parser;
use colored::Colorize;

#[derive(Debug, Parser)]
#[clap(author, version, about, long_about = None)]
Expand All @@ -23,14 +29,22 @@ pub struct Cli {

fn main() -> anyhow::Result<()> {
let args = Cli::parse();

let settings = Settings::load().expect("Failed to load config file!");
let logger = Logger::new(args.log, settings.configs.log);
let logger = Arc::new(Mutex::new(Logger::new(args.log, settings.configs.log)));

let targets = Process::get_entries(args, settings);

for target in targets {
Process::process_target(&logger, &target)?;
if Path::new(&target).exists() {
Process::process_target(&logger, &target)?;
} else {
let message = "Must build at directory: not a valid directory ⚠️".yellow().to_string();
logger.lock().unwrap().log_warning(format!(
"\n{}:{}\n",
message,
&target
))
}
}

Ok(())
Expand Down
11 changes: 11 additions & 0 deletions src/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ impl Pretty {
.unwrap();
}

pub fn print_warning(string: String) {
PrettyPrinter::new()
.input(Input::from_bytes(&string.as_bytes()))
.header(false)
.grid(true)
.language("log")
.theme("OneHalfDark")
.print()
.unwrap();
}

pub fn print_error(string: String) {
PrettyPrinter::new()
.header(false)
Expand Down
47 changes: 27 additions & 20 deletions src/processor.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
use serde::Deserialize;
use serde_yaml::Value;

use std::{collections::HashSet, env, io::Write};
use std::{
collections::HashSet,
env,
sync::{Arc, Mutex},
thread,
};

use crate::{commands::Commands, logger::Logger, print::Pretty, settings::Settings, Cli};
pub struct Process {}
Expand All @@ -23,42 +28,44 @@ impl Process {
return targets;
}

pub fn process_target(logger: &Logger, target: &str) -> anyhow::Result<()> {
pub fn process_target(logger: &Arc<Mutex<Logger>>, target: &str) -> anyhow::Result<()> {
Pretty::print_path(format!("Path: {}", target.to_string()));
let mut handles = vec![];
let build = Commands::get_build(logger.clone(), target)?;

let build = Commands::get_build(&logger, target)?;

for document in serde_yaml::Deserializer::from_str(build.as_str()) {
serde_yaml::Deserializer::from_str(build.as_str()).for_each(|document| {
let v_result = Value::deserialize(document);
let logger_clone = Arc::clone(&logger);

match handle_deserialization_result(v_result) {
Ok(v) => {
let string = serde_yaml::to_string(&v).unwrap();
let mut diff = Commands::get_diff();
diff.stdin
.as_mut()
.unwrap()
.write(string.as_bytes())
.unwrap();
let diff = diff.wait_with_output().unwrap();
let string = String::from_utf8(diff.stdout.to_owned()).unwrap();
let handle = thread::spawn(move || {
let string = serde_yaml::to_string(&v).unwrap();
let diff = Commands::get_diff(&string).unwrap();

if string.len() > 0 {
Pretty::print(string);
} else {
handle_no_changes(&logger, &v)
}
if diff.len() > 0 {
Pretty::print(diff);
} else {
let logger = logger_clone.lock().unwrap();
handle_no_changes(&logger, &v);
}
});
handles.push(handle);
}
Err(error) => {
Pretty::print_info(error.to_string());
}
}
});
for handle in handles {
handle.join().expect("Thread panicked");
}
Ok(())
}
}

fn handle_no_changes(logger: &Logger, v: &Value) {
logger.log(format!(
logger.log_info(format!(
"No changes in: {:?} {:?} {:?}\n",
v["apiVersion"].as_str().unwrap(),
v["kind"].as_str().unwrap(),
Expand Down

0 comments on commit 240c446

Please sign in to comment.