fix: helmfile and argocd are working again

- The tool was totally broken, not it works again
- Development has been moved to my Gitea server
- A basic test for helmfile is added
- A basic drone pipeline is added
This commit is contained in:
Nikolai Rodionov
2023-03-05 22:28:46 +01:00
committed by Nikolai Rodionov
parent 7adb5f0a4a
commit 1c29b32407
9 changed files with 160 additions and 21 deletions

View File

@ -15,7 +15,7 @@ impl Connector for Argo {
type ConnectorType = Argo;
fn get_app(&self) -> Result<Vec<types::HelmChart>> {
let cmd: String = "argocd app list -o json | jq '[.[] | {chart: .spec.source.chart, version: .spec.source.targetRevision}]'".to_string();
let cmd: String = "argocd app list -o json | jq '[.[] | {chart: .spec.source.chart, version: .spec.source.targetRevision, name: .spec.source.helm.releaseName}]'".to_string();
debug!("executing '${}'", cmd);
let output = Command::new("bash")
@ -27,7 +27,7 @@ impl Connector for Argo {
match from_str::<Vec<types::HelmChart>>(Borrow::borrow(&helm_stdout)) {
Ok(mut charts) => {
charts.dedup();
charts.iter_mut().for_each(|chart| {chart.chart = Some(format!("{}/{}", chart.chart.clone().unwrap(), chart.chart.clone().unwrap()))});
Ok(charts)
}
Err(err) => Err(err.into()),

View File

@ -14,7 +14,7 @@ pub(crate) struct Helmfile {
impl Connector for Helmfile {
fn get_app(&self) -> Result<Vec<types::HelmChart>> {
let cmd: String = format!(
"helmfile -f {} -e {} list --output json | jq '[.[] | {{chart: .name, version: .version}}]'",
"helmfile -f {} -e {} list --output json | jq '[.[] | {{chart: .chart, version: .version, name: .name}}]'",
self.path,
self.env
)
@ -48,8 +48,48 @@ impl Connector for Helmfile {
type ConnectorType = Helmfile;
}
impl Helmfile {
pub(crate) fn init(path: String, env: String) -> Self {
Self {path, env}
}
}
#[cfg(test)]
mod tests {
use tempfile::NamedTempFile;
use std::io::Write;
use crate::connectors::{Helmfile, Connector};
use crate::types;
static HELMFILE_EXAMPLE: &str = "repositories:\n
- name: argo\n
url: https://argoproj.github.io/argo-helm\n
releases:\n
- name: argocd\n
installed: true\n
namespace: argocd\n
createNamespace: true\n
chart: argo/argo-cd\n
version: 5.23.3\n
values:\n
- server:\n
extraArgs:\n
- --insecure";
#[test]
fn test_helmfile() {
let mut file = NamedTempFile::new().unwrap();
writeln!(file, "{}", HELMFILE_EXAMPLE.clone()).unwrap();
let path = file.into_temp_path();
let helmfile_app = Helmfile::init(path.to_string_lossy().to_string(), "default".to_string()).get_app().unwrap();
let app = types::HelmChart{
chart: Some("argo/argo-cd".to_string()),
name: Some("argocd".to_string()),
version: Some("5.23.3".to_string()),
};
let apps: Vec<types::HelmChart> = vec![app];
assert_eq!(apps, helmfile_app);
path.close().unwrap();
}
}

View File

@ -109,6 +109,7 @@ fn main() {
}
charts.iter().for_each(|a| {
debug!("{:?}", a);
check_chart(&mut result, a).unwrap();
});
@ -128,9 +129,9 @@ fn main() {
}
fn check_chart(result: &mut Vec<ExecResult>, local_chart: &types::HelmChart) -> Result<()> {
if local_chart.name.is_some() {
if local_chart.chart.is_some() {
let version = local_chart.version.clone().unwrap();
let chart = local_chart.name.clone().unwrap();
let chart = local_chart.chart.clone().unwrap();
return match version.is_empty() {
true => {
warn!(
@ -142,8 +143,8 @@ fn check_chart(result: &mut Vec<ExecResult>, local_chart: &types::HelmChart) ->
false => {
info!("checking {} - {}", chart, version);
let cmd = format!(
"helm search repo {}/{} --versions --output json",
chart, chart
"helm search repo {} --versions --output json",
chart,
);
debug!("executing '${}'", cmd);
let output = Command::new("bash")
@ -156,6 +157,8 @@ fn check_chart(result: &mut Vec<ExecResult>, local_chart: &types::HelmChart) ->
// Remove "v" from version definitions
let mut versions: Vec<HelmChart> = from_str(helm_stdout.borrow()).unwrap();
versions.iter_mut().for_each(|f| {
f.name = local_chart.name.clone();
f.chart = local_chart.chart.clone();
if f.version.is_some() {
f.version = Some(f.version.as_ref().unwrap().replace('v', ""));
}
@ -172,8 +175,10 @@ fn check_chart(result: &mut Vec<ExecResult>, local_chart: &types::HelmChart) ->
);
}
let remote = Version::from(current_version.as_str()).unwrap();
debug!("{:?}", versions);
let status: Status = if versions.contains(&HelmChart {
name: Some(format!("{}/{}", chart.clone(), chart.clone())),
chart: Some(chart.clone()),
name: local_chart.name.clone(),
version: Some(version.clone()),
}) {
match local.compare(remote.clone()) {
@ -187,6 +192,7 @@ fn check_chart(result: &mut Vec<ExecResult>, local_chart: &types::HelmChart) ->
};
result.push(ExecResult::new(
local_chart.name.clone().unwrap(),
chart.clone(),
current_version.clone(),
version.clone(),
@ -214,21 +220,21 @@ fn handle_result(
}
for r in result.clone() {
match r.status {
Status::Uptodate => info!("{} is up-to-date", r.name),
Status::Uptodate => info!("{} is up-to-date", r.chart),
Status::Outdated => {
if outdated_fail {
failed = true
}
warn!(
"{} is outdated. Current version is {}, but the latest is {}",
r.name, r.current_version, r.latest_version
r.chart, r.current_version, r.latest_version
);
}
Status::Missing => {
failed = true;
error!(
"{} is broken. Current version is {}, but it can't be found in the repo",
r.name, r.current_version
r.chart, r.current_version
);
}
}

View File

@ -5,8 +5,10 @@ use tabled::Tabled;
/// Struct for parsing charts info from helmfile
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub(crate) struct HelmChart {
#[serde(alias = "name", alias = "chart")]
// #[serde(alias = "name", alias = "chart")]
pub(crate) name: Option<String>,
// #[serde(alias = "name", alias = "chart")]
pub(crate) chart: Option<String>,
pub(crate) version: Option<String>,
}
@ -36,6 +38,7 @@ impl fmt::Display for Status {
#[derive(Clone, Tabled, Serialize, Deserialize)]
pub(crate) struct ExecResult {
pub(crate) name: String,
pub(crate) chart: String,
pub(crate) latest_version: String,
pub(crate) current_version: String,
pub(crate) status: Status,
@ -44,12 +47,14 @@ pub(crate) struct ExecResult {
impl ExecResult {
pub(crate) fn new(
name: String,
chart: String,
latest_version: String,
current_version: String,
status: Status,
) -> Self {
Self {
name,
chart,
latest_version,
current_version,
status,