mirror of
https://github.com/jlengrand/engine.git
synced 2026-03-10 08:11:21 +00:00
Feat: handle helm breaking changes upgrade (#414)
* feat: handle helm deploy version with breaking changes * feat: set promtail breaking change version
This commit is contained in:
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -2065,6 +2065,7 @@ dependencies = [
|
||||
"rusoto_sts",
|
||||
"rust-crypto",
|
||||
"scaleway_api_rs",
|
||||
"semver 1.0.4",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
@@ -2720,7 +2721,7 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
"semver 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2799,6 +2800,12 @@ dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
|
||||
@@ -18,6 +18,7 @@ rust-crypto = "0.2.36"
|
||||
retry = "1.2.1"
|
||||
trust-dns-resolver = "0.20.3"
|
||||
rand = "0.8.3"
|
||||
semver = "1.0.4"
|
||||
gethostname = "0.2.1"
|
||||
reqwest = { version = "0.11.3", features = ["blocking", "json"] }
|
||||
futures = "0.3.15"
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::cloud_provider::helm::{
|
||||
use crate::cloud_provider::qovery::{get_qovery_app_version, QoveryAgent, QoveryAppName, QoveryEngine};
|
||||
use crate::cmd::kubectl::{kubectl_exec_get_daemonset, kubectl_exec_with_output};
|
||||
use crate::error::{SimpleError, SimpleErrorKind};
|
||||
use semver::Version;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
@@ -365,6 +366,7 @@ pub fn aws_helm_charts(
|
||||
let promtail = CommonChart {
|
||||
chart_info: ChartInfo {
|
||||
name: "promtail".to_string(),
|
||||
last_breaking_version_requiring_restart: Some(Version::new(0, 24, 0)),
|
||||
path: chart_path("common/charts/promtail"),
|
||||
// because of priorityClassName, we need to add it to kube-system
|
||||
namespace: HelmChartNamespaces::KubeSystem,
|
||||
|
||||
@@ -1318,6 +1318,7 @@ impl<'a> Kubernetes for EKS<'a> {
|
||||
vec![HelmChart {
|
||||
name: "metrics-server".to_string(),
|
||||
namespace: "kube-system".to_string(),
|
||||
version: None,
|
||||
}],
|
||||
self.cloud_provider().credentials_environment_variables(),
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::cloud_provider::helm::{
|
||||
};
|
||||
use crate::cloud_provider::qovery::{get_qovery_app_version, QoveryAgent, QoveryAppName, QoveryEngine};
|
||||
use crate::error::{SimpleError, SimpleErrorKind};
|
||||
use semver::Version;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
@@ -206,6 +207,7 @@ pub fn do_helm_charts(
|
||||
let promtail = CommonChart {
|
||||
chart_info: ChartInfo {
|
||||
name: "promtail".to_string(),
|
||||
last_breaking_version_requiring_restart: Some(Version::new(0, 24, 0)),
|
||||
path: chart_path("common/charts/promtail"),
|
||||
// because of priorityClassName, we need to add it to kube-system
|
||||
namespace: HelmChartNamespaces::KubeSystem,
|
||||
|
||||
@@ -843,6 +843,7 @@ impl<'a> Kubernetes for DOKS<'a> {
|
||||
vec![HelmChart {
|
||||
name: "metrics-server".to_string(),
|
||||
namespace: "kube-system".to_string(),
|
||||
version: None,
|
||||
}],
|
||||
self.cloud_provider().credentials_environment_variables(),
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::cloud_provider::helm::HelmAction::Deploy;
|
||||
use crate::cloud_provider::helm::HelmChartNamespaces::KubeSystem;
|
||||
use crate::cmd::helm::{
|
||||
helm_exec_uninstall_with_chart_info, helm_exec_upgrade_with_chart_info, helm_upgrade_diff_with_chart_info,
|
||||
is_chart_deployed,
|
||||
helm_destroy_chart_if_breaking_changes_version_detected, helm_exec_uninstall_with_chart_info,
|
||||
helm_exec_upgrade_with_chart_info, helm_upgrade_diff_with_chart_info, is_chart_deployed,
|
||||
};
|
||||
use crate::cmd::kubectl::{
|
||||
kubectl_exec_delete_crd, kubectl_exec_get_configmap, kubectl_exec_get_events,
|
||||
@@ -11,6 +11,7 @@ use crate::cmd::kubectl::{
|
||||
use crate::cmd::structs::HelmHistoryRow;
|
||||
use crate::error::{SimpleError, SimpleErrorKind};
|
||||
use crate::utilities::calculate_hash;
|
||||
use semver::Version;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::{fs, thread};
|
||||
@@ -54,6 +55,7 @@ pub struct ChartInfo {
|
||||
pub action: HelmAction,
|
||||
pub atomic: bool,
|
||||
pub force_upgrade: bool,
|
||||
pub last_breaking_version_requiring_restart: Option<Version>,
|
||||
pub timeout: String,
|
||||
pub dry_run: bool,
|
||||
pub wait: bool,
|
||||
@@ -71,6 +73,7 @@ impl Default for ChartInfo {
|
||||
action: Deploy,
|
||||
atomic: true,
|
||||
force_upgrade: false,
|
||||
last_breaking_version_requiring_restart: None,
|
||||
timeout: "180s".to_string(),
|
||||
dry_run: false,
|
||||
wait: true,
|
||||
@@ -153,10 +156,22 @@ pub trait HelmChart: Send {
|
||||
envs: &[(String, String)],
|
||||
payload: Option<ChartPayload>,
|
||||
) -> Result<Option<ChartPayload>, SimpleError> {
|
||||
let environment_variables = envs.iter().map(|x| (x.0.as_str(), x.1.as_str())).collect();
|
||||
match self.get_chart_info().action {
|
||||
let environment_variables: Vec<(&str, &str)> = envs.iter().map(|x| (x.0.as_str(), x.1.as_str())).collect();
|
||||
let chart_info = self.get_chart_info();
|
||||
match chart_info.action {
|
||||
HelmAction::Deploy => {
|
||||
helm_exec_upgrade_with_chart_info(kubernetes_config, &environment_variables, self.get_chart_info())?
|
||||
if let Err(e) = helm_destroy_chart_if_breaking_changes_version_detected(
|
||||
kubernetes_config,
|
||||
&environment_variables,
|
||||
chart_info,
|
||||
) {
|
||||
warn!(
|
||||
"error while trying to destroy chart if breaking change is detected: {:?}",
|
||||
e.message
|
||||
);
|
||||
}
|
||||
|
||||
helm_exec_upgrade_with_chart_info(kubernetes_config, &environment_variables, chart_info)?
|
||||
}
|
||||
HelmAction::Destroy => {
|
||||
let chart_info = self.get_chart_info();
|
||||
@@ -508,10 +523,22 @@ impl HelmChart for PrometheusOperatorConfigChart {
|
||||
envs: &[(String, String)],
|
||||
payload: Option<ChartPayload>,
|
||||
) -> Result<Option<ChartPayload>, SimpleError> {
|
||||
let environment_variables = envs.iter().map(|x| (x.0.as_str(), x.1.as_str())).collect();
|
||||
match self.get_chart_info().action {
|
||||
let environment_variables: Vec<(&str, &str)> = envs.iter().map(|x| (x.0.as_str(), x.1.as_str())).collect();
|
||||
let chart_info = self.get_chart_info();
|
||||
match chart_info.action {
|
||||
HelmAction::Deploy => {
|
||||
helm_exec_upgrade_with_chart_info(kubernetes_config, &environment_variables, self.get_chart_info())?
|
||||
if let Err(e) = helm_destroy_chart_if_breaking_changes_version_detected(
|
||||
kubernetes_config,
|
||||
&environment_variables,
|
||||
chart_info,
|
||||
) {
|
||||
warn!(
|
||||
"error while trying to destroy chart if breaking change is detected: {:?}",
|
||||
e.message
|
||||
);
|
||||
}
|
||||
|
||||
helm_exec_upgrade_with_chart_info(kubernetes_config, &environment_variables, chart_info)?
|
||||
}
|
||||
HelmAction::Destroy => {
|
||||
let chart_info = self.get_chart_info();
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::cloud_provider::qovery::{get_qovery_app_version, QoveryAgent, QoveryA
|
||||
use crate::cloud_provider::scaleway::application::Zone;
|
||||
use crate::cloud_provider::scaleway::kubernetes::KapsuleOptions;
|
||||
use crate::error::{SimpleError, SimpleErrorKind};
|
||||
use semver::Version;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
@@ -191,6 +192,7 @@ pub fn scw_helm_charts(
|
||||
let promtail = CommonChart {
|
||||
chart_info: ChartInfo {
|
||||
name: "promtail".to_string(),
|
||||
last_breaking_version_requiring_restart: Some(Version::new(0, 24, 0)),
|
||||
path: chart_path("common/charts/promtail"),
|
||||
// because of priorityClassName, we need to add it to kube-system
|
||||
namespace: HelmChartNamespaces::KubeSystem,
|
||||
|
||||
@@ -764,6 +764,7 @@ impl<'a> Kubernetes for Kapsule<'a> {
|
||||
vec![HelmChart {
|
||||
name: "metrics-server".to_string(),
|
||||
namespace: "kube-system".to_string(),
|
||||
version: None,
|
||||
}],
|
||||
self.cloud_provider().credentials_environment_variables(),
|
||||
);
|
||||
|
||||
@@ -14,7 +14,9 @@ use core::time;
|
||||
use retry::delay::Fixed;
|
||||
use retry::Error::Operation;
|
||||
use retry::OperationResult;
|
||||
use semver::Version;
|
||||
use std::fs::File;
|
||||
use std::str::FromStr;
|
||||
use std::thread;
|
||||
|
||||
const HELM_DEFAULT_TIMEOUT_IN_SECONDS: u32 = 300;
|
||||
@@ -66,6 +68,37 @@ where
|
||||
.map(|helm_history_row| helm_history_row.clone()))
|
||||
}
|
||||
|
||||
pub fn helm_destroy_chart_if_breaking_changes_version_detected(
|
||||
kubernetes_config: &Path,
|
||||
environment_variables: &Vec<(&str, &str)>,
|
||||
chart_info: &ChartInfo,
|
||||
) -> Result<(), SimpleError> {
|
||||
// If there is a breaking version set for the current helm chart,
|
||||
// then we compare this breaking version with the currently installed version if any.
|
||||
// If current installed version is older than breaking change one, then we delete
|
||||
// the chart before applying it.
|
||||
if let Some(breaking_version) = &chart_info.last_breaking_version_requiring_restart {
|
||||
let chart_namespace = get_chart_namespace(chart_info.namespace.clone());
|
||||
if let Some(installed_version) = helm_get_chart_version(
|
||||
kubernetes_config,
|
||||
environment_variables.to_owned(),
|
||||
Some(chart_namespace.as_str()),
|
||||
chart_info.name.clone(),
|
||||
) {
|
||||
if installed_version.le(breaking_version) {
|
||||
return helm_exec_uninstall(
|
||||
kubernetes_config,
|
||||
chart_namespace.as_str(),
|
||||
chart_info.name.as_str(),
|
||||
environment_variables.to_owned(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn helm_exec_upgrade_with_chart_info<P>(
|
||||
kubernetes_config: P,
|
||||
envs: &Vec<(&str, &str)>,
|
||||
@@ -706,6 +739,29 @@ where
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub fn helm_get_chart_version<P>(
|
||||
kubernetes_config: P,
|
||||
envs: Vec<(&str, &str)>,
|
||||
namespace: Option<&str>,
|
||||
chart_name: String,
|
||||
) -> Option<Version>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
match helm_list(kubernetes_config, envs, namespace) {
|
||||
Ok(deployed_charts) => {
|
||||
for chart in deployed_charts {
|
||||
if chart.name == chart_name {
|
||||
return chart.version;
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// List deployed helm charts
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -754,7 +810,13 @@ where
|
||||
match values {
|
||||
Ok(all_helms) => {
|
||||
for helm in all_helms {
|
||||
helms_charts.push(HelmChart::new(helm.name, helm.namespace))
|
||||
let raw_version = helm.chart.replace(format!("{}-", helm.name).as_str(), "");
|
||||
let version = match Version::from_str(raw_version.as_str()) {
|
||||
Ok(v) => Some(v),
|
||||
Err(_) => None,
|
||||
};
|
||||
|
||||
helms_charts.push(HelmChart::new(helm.name, helm.namespace, version))
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use semver::Version;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
|
||||
@@ -261,11 +262,16 @@ pub struct Helm {
|
||||
pub struct HelmChart {
|
||||
pub name: String,
|
||||
pub namespace: String,
|
||||
pub version: Option<Version>,
|
||||
}
|
||||
|
||||
impl HelmChart {
|
||||
pub fn new(name: String, namespace: String) -> HelmChart {
|
||||
HelmChart { name, namespace }
|
||||
pub fn new(name: String, namespace: String, version: Option<Version>) -> HelmChart {
|
||||
HelmChart {
|
||||
name,
|
||||
namespace,
|
||||
version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user