Make CDH great (...not again) #3
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -56,6 +56,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"build_html",
|
"build_html",
|
||||||
"clap",
|
"clap",
|
||||||
|
"clap_complete",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"handlebars",
|
"handlebars",
|
||||||
"log",
|
"log",
|
||||||
@ -87,6 +88,15 @@ dependencies = [
|
|||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_complete"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce8955d4e8cd4f28f9a01c93a050194c4d131e73ca02f6636bcddbed867014d7"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.1.0"
|
version = "4.1.0"
|
||||||
|
@ -16,3 +16,5 @@ serde_yaml = "0.9.16"
|
|||||||
tabled = "0.10.0"
|
tabled = "0.10.0"
|
||||||
build_html = "2.1.0"
|
build_html = "2.1.0"
|
||||||
handlebars = "4.3.1"
|
handlebars = "4.3.1"
|
||||||
|
clap_complete = "4.0.6"
|
||||||
|
|
||||||
|
83
src/main.rs
83
src/main.rs
@ -1,10 +1,10 @@
|
|||||||
mod connectors;
|
mod connectors;
|
||||||
|
mod output;
|
||||||
mod types;
|
mod types;
|
||||||
|
use clap::{arg, command, Parser, Subcommand, ValueEnum};
|
||||||
use clap::{Parser, ValueEnum};
|
|
||||||
use connectors::{Argo, Connector, Helm, Helmfile};
|
use connectors::{Argo, Connector, Helm, Helmfile};
|
||||||
use handlebars::Handlebars;
|
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
|
use output::Output;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::from_str;
|
use serde_json::from_str;
|
||||||
use std::{
|
use std::{
|
||||||
@ -12,7 +12,7 @@ use std::{
|
|||||||
io::Result,
|
io::Result,
|
||||||
process::{exit, Command},
|
process::{exit, Command},
|
||||||
};
|
};
|
||||||
use tabled::Tabled;
|
use types::ExecResult;
|
||||||
use version_compare::{Cmp, Version};
|
use version_compare::{Cmp, Version};
|
||||||
|
|
||||||
use crate::types::{HelmChart, Status};
|
use crate::types::{HelmChart, Status};
|
||||||
@ -24,13 +24,22 @@ enum Kinds {
|
|||||||
Helmfile,
|
Helmfile,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
||||||
|
enum Outputs {
|
||||||
|
Yaml,
|
||||||
|
HTML,
|
||||||
|
}
|
||||||
|
|
||||||
/// Check you helm releaseas managed by Argo
|
/// Check you helm releaseas managed by Argo
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(author, version, about, long_about = None)]
|
#[clap(author, version, about, long_about = None)]
|
||||||
struct Args {
|
struct Args {
|
||||||
/// Type of the
|
/// How do you install your helm charts
|
||||||
#[clap(long, value_enum)]
|
#[clap(long, value_enum)]
|
||||||
kind: Kinds,
|
kind: Kinds,
|
||||||
|
/// What kind of output would you like to receive?
|
||||||
|
#[clap(long, value_enum, default_value = "yaml")]
|
||||||
|
output: Outputs,
|
||||||
/// Path to the helmfile
|
/// Path to the helmfile
|
||||||
#[clap(short, long, value_parser, default_value = "./")]
|
#[clap(short, long, value_parser, default_value = "./")]
|
||||||
path: String,
|
path: String,
|
||||||
@ -42,6 +51,14 @@ struct Args {
|
|||||||
no_sync: bool,
|
no_sync: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
enum Commands {
|
||||||
|
#[command(arg_required_else_help = true)]
|
||||||
|
Generate {
|
||||||
|
#[arg(value_name = "SHELL", default_missing_value = "zsh")]
|
||||||
|
shell: clap_complete::shells::Shell,
|
||||||
|
},
|
||||||
|
}
|
||||||
/// A struct to write helm repo description to
|
/// A struct to write helm repo description to
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||||
struct Repo {
|
struct Repo {
|
||||||
@ -57,25 +74,7 @@ struct LocalCharts {
|
|||||||
version: Option<String>,
|
version: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Tabled, Serialize)]
|
|
||||||
struct ExecResult {
|
|
||||||
name: String,
|
|
||||||
latest_version: String,
|
|
||||||
current_version: String,
|
|
||||||
status: Status,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation for the ExecResult struct
|
// Implementation for the ExecResult struct
|
||||||
impl ExecResult {
|
|
||||||
fn new(name: String, latest_version: String, current_version: String, status: Status) -> Self {
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
latest_version,
|
|
||||||
current_version,
|
|
||||||
status,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Preparations step
|
// Preparations step
|
||||||
@ -109,7 +108,7 @@ fn main() {
|
|||||||
|
|
||||||
// Parse the helmfile
|
// Parse the helmfile
|
||||||
// Handling the result
|
// Handling the result
|
||||||
match handle_result(&result, args.outdated_fail) {
|
match handle_result(&result, args.outdated_fail, args.output) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
if result {
|
if result {
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -197,7 +196,11 @@ fn check_chart(result: &mut Vec<ExecResult>, local_chart: &types::HelmChart) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Handle result
|
/// Handle result
|
||||||
fn handle_result(result: &Vec<ExecResult>, outdated_fail: bool) -> Result<bool> {
|
fn handle_result(
|
||||||
|
result: &Vec<ExecResult>,
|
||||||
|
outdated_fail: bool,
|
||||||
|
output_kind: Outputs,
|
||||||
|
) -> Result<bool> {
|
||||||
let mut failed = false;
|
let mut failed = false;
|
||||||
for r in result.clone() {
|
for r in result.clone() {
|
||||||
match r.status {
|
match r.status {
|
||||||
@ -220,34 +223,12 @@ fn handle_result(result: &Vec<ExecResult>, outdated_fail: bool) -> Result<bool>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let template = r#"
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Chart Name</th>
|
|
||||||
<th>Current Version</th>
|
|
||||||
<th>Latest Version</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
{{#each this as |tr|}}
|
|
||||||
<tr>
|
|
||||||
<th>{{tr.name}}</th>
|
|
||||||
<th>{{tr.current_version}}</th>
|
|
||||||
<th>{{tr.latest_version}}</th>
|
|
||||||
<th>{{tr.status}}</th>
|
|
||||||
</tr>
|
|
||||||
{{/each}}
|
|
||||||
</table>
|
|
||||||
"#;
|
|
||||||
let mut reg = Handlebars::new();
|
|
||||||
|
|
||||||
// TODO: Handle this error
|
match output_kind {
|
||||||
reg.register_template_string("html_table", template)
|
Outputs::Yaml => print!("{}", output::YAML::print(result)?),
|
||||||
.unwrap();
|
Outputs::HTML => print!("{}", output::HTML::print(result)?),
|
||||||
|
|
||||||
match reg.render("html_table", &result) {
|
|
||||||
Ok(res) => println!("{}", res),
|
|
||||||
Err(err) => error!("{}", err),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(failed)
|
Ok(failed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
src/output/mod.rs
Normal file
61
src/output/mod.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use std::io::{Result, Error, ErrorKind};
|
||||||
|
|
||||||
|
use handlebars::Handlebars;
|
||||||
|
use log::error;
|
||||||
|
|
||||||
|
use crate::types::ExecResult;
|
||||||
|
|
||||||
|
pub(crate) trait Output {
|
||||||
|
fn print(data: &Vec<ExecResult>) -> Result<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct HTML;
|
||||||
|
|
||||||
|
impl Output for HTML {
|
||||||
|
fn print(data: &Vec<ExecResult>) -> Result<String> {
|
||||||
|
// To generate htlm output, I have to use templates because I haven't found any other good
|
||||||
|
// solution
|
||||||
|
let template = r#"
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Chart Name</th>
|
||||||
|
<th>Current Version</th>
|
||||||
|
<th>Latest Version</th>
|
||||||
|
<th>Status</th>
|
||||||
|
</tr>
|
||||||
|
{{#each this as |tr|}}
|
||||||
|
<tr>
|
||||||
|
<th>{{tr.name}}</th>
|
||||||
|
<th>{{tr.current_version}}</th>
|
||||||
|
<th>{{tr.latest_version}}</th>
|
||||||
|
<th>{{tr.status}}</th>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</table>
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let mut reg = Handlebars::new();
|
||||||
|
// TODO: Handle this error
|
||||||
|
reg.register_template_string("html_table", template)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
match reg.render("html_table", &data) {
|
||||||
|
Ok(res) => Ok(res),
|
||||||
|
Err(err) => {
|
||||||
|
error!("{}", err);
|
||||||
|
return Err(Error::new(ErrorKind::InvalidInput, err.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct YAML;
|
||||||
|
|
||||||
|
impl Output for YAML {
|
||||||
|
fn print(data: &Vec<ExecResult>) -> Result<String> {
|
||||||
|
match serde_yaml::to_string(&data) {
|
||||||
|
Ok(res) => return Ok(res),
|
||||||
|
Err(err) => return Err(Error::new(ErrorKind::InvalidData, err.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use tabled::Tabled;
|
||||||
|
|
||||||
/// Struct for parsing charts info from helmfile
|
/// Struct for parsing charts info from helmfile
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||||
@ -15,7 +16,7 @@ pub(crate) struct HelmRepo {
|
|||||||
pub(crate) url: String,
|
pub(crate) url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub(crate) enum Status {
|
pub(crate) enum Status {
|
||||||
Uptodate,
|
Uptodate,
|
||||||
Outdated,
|
Outdated,
|
||||||
@ -31,3 +32,22 @@ impl fmt::Display for Status {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Tabled, Serialize, Deserialize)]
|
||||||
|
pub(crate) struct ExecResult {
|
||||||
|
pub(crate) name: String,
|
||||||
|
pub(crate) latest_version: String,
|
||||||
|
pub(crate) current_version: String,
|
||||||
|
pub(crate) status: Status,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExecResult {
|
||||||
|
pub(crate) fn new(name: String, latest_version: String, current_version: String, status: Status) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
latest_version,
|
||||||
|
current_version,
|
||||||
|
status,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user