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:
parent
7adb5f0a4a
commit
1c29b32407
26
.drone.yml
Normal file
26
.drone.yml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: kubernetes
|
||||||
|
name: Tests
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Prepare helm and helmfile
|
||||||
|
image: ghcr.io/helmfile/helmfile:canary
|
||||||
|
commands:
|
||||||
|
- mkdir -p bin
|
||||||
|
- cp $(which helm) ./bin/helm
|
||||||
|
- cp $(which helmfile) ./bin/helmfile
|
||||||
|
|
||||||
|
- name: Unit tests
|
||||||
|
image: rust:slim
|
||||||
|
environment:
|
||||||
|
CARGO_BUILD_JOBS: 1
|
||||||
|
commands:
|
||||||
|
- export PATH=$PWD/bin:$PATH
|
||||||
|
- helm
|
||||||
|
- helmfile
|
||||||
|
- cargo test
|
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -57,6 +57,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"tabled",
|
"tabled",
|
||||||
|
"tempfile",
|
||||||
"version-compare",
|
"version-compare",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -175,6 +176,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -242,6 +252,15 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-lifetimes"
|
name = "io-lifetimes"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -406,6 +425,15 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
@ -539,6 +567,19 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"fastrand",
|
||||||
|
"redox_syscall",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -17,3 +17,5 @@ tabled = "0.10.0"
|
|||||||
handlebars = "4.3.1"
|
handlebars = "4.3.1"
|
||||||
clap_complete = "4.0.6"
|
clap_complete = "4.0.6"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tempfile = "3.4.0"
|
||||||
|
18
examples/argocd/application.yaml
Normal file
18
examples/argocd/application.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: sealed-secrets
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
chart: argo-cd
|
||||||
|
repoURL: https://argoproj.github.io/argo-helm
|
||||||
|
targetRevision: 5.23.3
|
||||||
|
helm:
|
||||||
|
releaseName: sealed-secrets
|
||||||
|
syncPolicy:
|
||||||
|
automated: {}
|
||||||
|
destination:
|
||||||
|
server: "https://kubernetes.default.svc"
|
||||||
|
namespace: argocd
|
@ -1,14 +1,15 @@
|
|||||||
repositories:
|
repositories:
|
||||||
- name: keel
|
- name: argo
|
||||||
url: https://charts.keel.sh
|
url: https://argoproj.github.io/argo-helm
|
||||||
|
|
||||||
releases:
|
releases:
|
||||||
# -----------------------------
|
- name: argocd
|
||||||
# -- Keel
|
|
||||||
# -----------------------------
|
|
||||||
- name: keel
|
|
||||||
installed: true
|
installed: true
|
||||||
namespace: keel-system
|
namespace: argocd
|
||||||
createNamespace: true
|
createNamespace: true
|
||||||
chart: keel/keel
|
chart: argo/argo-cd
|
||||||
version: 0.9.10
|
version: 5.23.3
|
||||||
|
values:
|
||||||
|
- server:
|
||||||
|
extraArgs:
|
||||||
|
- --insecure
|
||||||
|
@ -15,7 +15,7 @@ impl Connector for Argo {
|
|||||||
type ConnectorType = Argo;
|
type ConnectorType = Argo;
|
||||||
|
|
||||||
fn get_app(&self) -> Result<Vec<types::HelmChart>> {
|
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);
|
debug!("executing '${}'", cmd);
|
||||||
let output = Command::new("bash")
|
let output = Command::new("bash")
|
||||||
@ -27,7 +27,7 @@ impl Connector for Argo {
|
|||||||
|
|
||||||
match from_str::<Vec<types::HelmChart>>(Borrow::borrow(&helm_stdout)) {
|
match from_str::<Vec<types::HelmChart>>(Borrow::borrow(&helm_stdout)) {
|
||||||
Ok(mut charts) => {
|
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)
|
Ok(charts)
|
||||||
}
|
}
|
||||||
Err(err) => Err(err.into()),
|
Err(err) => Err(err.into()),
|
||||||
|
@ -14,7 +14,7 @@ pub(crate) struct Helmfile {
|
|||||||
impl Connector for Helmfile {
|
impl Connector for Helmfile {
|
||||||
fn get_app(&self) -> Result<Vec<types::HelmChart>> {
|
fn get_app(&self) -> Result<Vec<types::HelmChart>> {
|
||||||
let cmd: String = format!(
|
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.path,
|
||||||
self.env
|
self.env
|
||||||
)
|
)
|
||||||
@ -48,8 +48,48 @@ impl Connector for Helmfile {
|
|||||||
|
|
||||||
type ConnectorType = Helmfile;
|
type ConnectorType = Helmfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Helmfile {
|
impl Helmfile {
|
||||||
pub(crate) fn init(path: String, env: String) -> Self {
|
pub(crate) fn init(path: String, env: String) -> Self {
|
||||||
Self {path, env}
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22
src/main.rs
22
src/main.rs
@ -109,6 +109,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
charts.iter().for_each(|a| {
|
charts.iter().for_each(|a| {
|
||||||
|
debug!("{:?}", a);
|
||||||
check_chart(&mut result, a).unwrap();
|
check_chart(&mut result, a).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -128,9 +129,9 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_chart(result: &mut Vec<ExecResult>, local_chart: &types::HelmChart) -> Result<()> {
|
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 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() {
|
return match version.is_empty() {
|
||||||
true => {
|
true => {
|
||||||
warn!(
|
warn!(
|
||||||
@ -142,8 +143,8 @@ fn check_chart(result: &mut Vec<ExecResult>, local_chart: &types::HelmChart) ->
|
|||||||
false => {
|
false => {
|
||||||
info!("checking {} - {}", chart, version);
|
info!("checking {} - {}", chart, version);
|
||||||
let cmd = format!(
|
let cmd = format!(
|
||||||
"helm search repo {}/{} --versions --output json",
|
"helm search repo {} --versions --output json",
|
||||||
chart, chart
|
chart,
|
||||||
);
|
);
|
||||||
debug!("executing '${}'", cmd);
|
debug!("executing '${}'", cmd);
|
||||||
let output = Command::new("bash")
|
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
|
// Remove "v" from version definitions
|
||||||
let mut versions: Vec<HelmChart> = from_str(helm_stdout.borrow()).unwrap();
|
let mut versions: Vec<HelmChart> = from_str(helm_stdout.borrow()).unwrap();
|
||||||
versions.iter_mut().for_each(|f| {
|
versions.iter_mut().for_each(|f| {
|
||||||
|
f.name = local_chart.name.clone();
|
||||||
|
f.chart = local_chart.chart.clone();
|
||||||
if f.version.is_some() {
|
if f.version.is_some() {
|
||||||
f.version = Some(f.version.as_ref().unwrap().replace('v', ""));
|
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();
|
let remote = Version::from(current_version.as_str()).unwrap();
|
||||||
|
debug!("{:?}", versions);
|
||||||
let status: Status = if versions.contains(&HelmChart {
|
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()),
|
version: Some(version.clone()),
|
||||||
}) {
|
}) {
|
||||||
match local.compare(remote.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(
|
result.push(ExecResult::new(
|
||||||
|
local_chart.name.clone().unwrap(),
|
||||||
chart.clone(),
|
chart.clone(),
|
||||||
current_version.clone(),
|
current_version.clone(),
|
||||||
version.clone(),
|
version.clone(),
|
||||||
@ -214,21 +220,21 @@ fn handle_result(
|
|||||||
}
|
}
|
||||||
for r in result.clone() {
|
for r in result.clone() {
|
||||||
match r.status {
|
match r.status {
|
||||||
Status::Uptodate => info!("{} is up-to-date", r.name),
|
Status::Uptodate => info!("{} is up-to-date", r.chart),
|
||||||
Status::Outdated => {
|
Status::Outdated => {
|
||||||
if outdated_fail {
|
if outdated_fail {
|
||||||
failed = true
|
failed = true
|
||||||
}
|
}
|
||||||
warn!(
|
warn!(
|
||||||
"{} is outdated. Current version is {}, but the latest is {}",
|
"{} 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 => {
|
Status::Missing => {
|
||||||
failed = true;
|
failed = true;
|
||||||
error!(
|
error!(
|
||||||
"{} is broken. Current version is {}, but it can't be found in the repo",
|
"{} is broken. Current version is {}, but it can't be found in the repo",
|
||||||
r.name, r.current_version
|
r.chart, r.current_version
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,10 @@ 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)]
|
||||||
pub(crate) struct HelmChart {
|
pub(crate) struct HelmChart {
|
||||||
#[serde(alias = "name", alias = "chart")]
|
// #[serde(alias = "name", alias = "chart")]
|
||||||
pub(crate) name: Option<String>,
|
pub(crate) name: Option<String>,
|
||||||
|
// #[serde(alias = "name", alias = "chart")]
|
||||||
|
pub(crate) chart: Option<String>,
|
||||||
pub(crate) version: Option<String>,
|
pub(crate) version: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +38,7 @@ impl fmt::Display for Status {
|
|||||||
#[derive(Clone, Tabled, Serialize, Deserialize)]
|
#[derive(Clone, Tabled, Serialize, Deserialize)]
|
||||||
pub(crate) struct ExecResult {
|
pub(crate) struct ExecResult {
|
||||||
pub(crate) name: String,
|
pub(crate) name: String,
|
||||||
|
pub(crate) chart: String,
|
||||||
pub(crate) latest_version: String,
|
pub(crate) latest_version: String,
|
||||||
pub(crate) current_version: String,
|
pub(crate) current_version: String,
|
||||||
pub(crate) status: Status,
|
pub(crate) status: Status,
|
||||||
@ -44,12 +47,14 @@ pub(crate) struct ExecResult {
|
|||||||
impl ExecResult {
|
impl ExecResult {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
name: String,
|
name: String,
|
||||||
|
chart: String,
|
||||||
latest_version: String,
|
latest_version: String,
|
||||||
current_version: String,
|
current_version: String,
|
||||||
status: Status,
|
status: Status,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
|
chart,
|
||||||
latest_version,
|
latest_version,
|
||||||
current_version,
|
current_version,
|
||||||
status,
|
status,
|
||||||
|
Reference in New Issue
Block a user