Our own Helm Command/Resource/Executor #13
| @ -42,7 +42,7 @@ pub struct HelmChartScore { | |||||||
|     pub values_yaml: Option<String>, |     pub values_yaml: Option<String>, | ||||||
|     pub create_namespace: bool, |     pub create_namespace: bool, | ||||||
| 
 | 
 | ||||||
|     /// Wether to run `helm upgrade --install` under the hood or only install when not present
 |     /// Whether to run `helm upgrade --install` under the hood or only install when not present
 | ||||||
|     pub install_only: bool, |     pub install_only: bool, | ||||||
|     pub repository: Option<HelmRepository>, |     pub repository: Option<HelmRepository>, | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,68 +1,215 @@ | |||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
|  | use std::ffi::OsStr; | ||||||
|  | use std::io::ErrorKind; | ||||||
| use std::path::{Path, PathBuf}; | use std::path::{Path, PathBuf}; | ||||||
| use std::process::{Command, Output}; | use std::process::{Command, Output}; | ||||||
| 
 | 
 | ||||||
| pub struct HelmCommand { | #[derive(Clone)] | ||||||
|  | pub struct HelmCommandExecutor { | ||||||
|     pub env: HashMap<String, String>, |     pub env: HashMap<String, String>, | ||||||
|     pub path: PathBuf, |     pub path: PathBuf, | ||||||
|     pub args: Vec<String>, |     pub args: Vec<String>, | ||||||
|     pub api_versions: Vec<String>, |     pub api_versions: Option<Vec<String>>, | ||||||
|     pub kube_version: String, |     pub kube_version: String, | ||||||
|     pub debug: bool, |     pub debug: Option<bool>, | ||||||
|     pub globals: HelmGlobals, |     pub globals: HelmGlobals, | ||||||
|     pub chart: HelmChart, |     pub chart: HelmChart, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Clone)] | ||||||
| pub struct HelmGlobals { | pub struct HelmGlobals { | ||||||
|     chart_home: PathBuf, |     chart_home: PathBuf, | ||||||
|     config_home: PathBuf, |     config_home: PathBuf, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum MergeMode { | #[derive(Clone)] | ||||||
|     Merge, |  | ||||||
|     Override, |  | ||||||
|     Replace, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub struct HelmChart { | pub struct HelmChart { | ||||||
|     name: String, |     pub name: String, | ||||||
|     version: String, |     pub version: Option<String>, | ||||||
|     repo: String, |     pub repo: Option<String>, | ||||||
|     release_name: String, |     pub release_name: Option<String>, | ||||||
|     namespace: String, |     pub namespace: Option<String>, | ||||||
|     additional_values_files: Vec<PathBuf>, |     pub additional_values_files: Vec<PathBuf>, | ||||||
|     values_file: PathBuf, |     pub values_file: Option<PathBuf>, | ||||||
|     values_inline: serde_yaml::Mapping, |     pub values_inline: HashMap<String, String>, | ||||||
|     values_merge: MergeMode, |     pub include_crds: Option<bool>, | ||||||
|     include_crds: bool, |     pub skip_hooks: Option<bool>, | ||||||
|     skip_hooks: bool, |     pub api_versions: Option<Vec<String>>, | ||||||
|     api_versions: Vec<String>, |     pub kube_version: Option<String>, | ||||||
|     kube_version: String, |     pub name_template: String, | ||||||
|     name_template: String, |     pub skip_tests: Option<bool>, | ||||||
|     skip_tests: bool, |     pub debug: Option<bool>, | ||||||
|     debug: bool, |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl HelmCommand { | impl HelmCommandExecutor { | ||||||
|     pub fn generate(self) -> Result<Output, std::io::Error> { |     pub fn generate(&self) -> Result<Output, std::io::Error> { | ||||||
|         self.run_command(vec![]) |         if self | ||||||
|  |             .clone() | ||||||
|  |             .chart | ||||||
|  |             .clone() | ||||||
|  |             .chart_exists_locally(self.clone().globals.chart_home) | ||||||
|  |             .is_none() | ||||||
|  |         { | ||||||
|  |             if self.chart.repo.is_none() { | ||||||
|  |                 return Err(std::io::Error::new( | ||||||
|  |                     ErrorKind::Other, | ||||||
|  |                     "Chart doesn't exist locally and no repo specified", | ||||||
|  |                 )); | ||||||
|  |             } | ||||||
|  |             self.clone().run_command( | ||||||
|  |                 self.chart | ||||||
|  |                     .clone() | ||||||
|  |                     .pull_command(self.globals.chart_home.clone()), | ||||||
|  |             )?; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         self.clone().run_command( | ||||||
|  |             self.chart | ||||||
|  |                 .clone() | ||||||
|  |                 .helm_args(self.globals.chart_home.clone()), | ||||||
|  |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn version(self) -> Result<Output, std::io::Error> { |     pub fn version(self) -> Result<Output, std::io::Error> { | ||||||
|         self.run_command(vec!["version", "-c", "--short"]) |         self.run_command(vec![ | ||||||
|  |             "version".to_string(), | ||||||
|  |             "-c".to_string(), | ||||||
|  |             "--short".to_string(), | ||||||
|  |         ]) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn run_command(self, mut args: Vec<&str>) -> Result<Output, std::io::Error> { |     pub fn run_command(mut self, mut args: Vec<String>) -> Result<Output, std::io::Error> { | ||||||
|         if self.debug { |         if let Some(d) = self.debug { | ||||||
|             args.push("--debug"); |             if d { | ||||||
|  |                 args.push("--debug".to_string()); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Command::new(self.path) |         self.env.insert( | ||||||
|             .envs(self.env) |             "HELM_CONFIG_HOME".to_string(), | ||||||
|             .env("HELM_CONFIG_HOME", &self.globals.config_home) |             self.globals.config_home.to_str().unwrap().to_string(), | ||||||
|             .env("HELM_CACHE_HOME", &self.globals.config_home) |         ); | ||||||
|             .env("HELM_DATA_HOME", &self.globals.config_home) |         self.env.insert( | ||||||
|             .args(args) |             "HELM_CACHE_HOME".to_string(), | ||||||
|             .output() |             self.globals.config_home.to_str().unwrap().to_string(), | ||||||
|  |         ); | ||||||
|  |         self.env.insert( | ||||||
|  |             "HELM_DATA_HOME".to_string(), | ||||||
|  |             self.globals.config_home.to_str().unwrap().to_string(), | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         Command::new(self.path).envs(self.env).args(args).output() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl HelmChart { | ||||||
|  |     pub fn chart_exists_locally(self, chart_home: PathBuf) -> Option<PathBuf> { | ||||||
|  |         let chart_path = | ||||||
|  |             PathBuf::from(chart_home.to_str().unwrap().to_string() + "/" + &self.name.to_string()); | ||||||
|  | 
 | ||||||
|  |         if chart_path.exists() { | ||||||
|  |             Some(chart_path) | ||||||
|  |         } else { | ||||||
|  |             None | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn pull_command(self, chart_home: PathBuf) -> Vec<String> { | ||||||
|  |         let mut args = vec![ | ||||||
|  |             "pull".to_string(), | ||||||
|  |             "--untar".to_string(), | ||||||
|  |             "--untardir".to_string(), | ||||||
|  |             chart_home.to_str().unwrap().to_string(), | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         match self.repo { | ||||||
|  |             Some(r) => { | ||||||
|  |                 if r.starts_with("oci://") { | ||||||
|  |                     args.push(String::from( | ||||||
|  |                         r.trim_end_matches("/").to_string() + "/" + self.name.clone().as_str(), | ||||||
|  |                     )); | ||||||
|  |                 } else { | ||||||
|  |                     args.push("--repo".to_string()); | ||||||
|  |                     args.push(r); | ||||||
|  | 
 | ||||||
|  |                     args.push(self.name); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             None => args.push(self.name), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         match self.version { | ||||||
|  |             Some(v) => { | ||||||
|  |                 args.push("--version".to_string()); | ||||||
|  |                 args.push(v); | ||||||
|  |             } | ||||||
|  |             None => (), | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         args | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn helm_args(self, chart_home: PathBuf) -> Vec<String> { | ||||||
|  |         let mut args = vec![]; | ||||||
|  | 
 | ||||||
|  |         match self.release_name { | ||||||
|  |             Some(rn) => args.push(rn), | ||||||
|  |             None => args.push("--generate-name".to_string()), | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         args.push( | ||||||
|  |             PathBuf::from(chart_home.to_str().unwrap().to_string() + "/" + self.name.as_str()) | ||||||
|  |                 .to_str() | ||||||
|  |                 .unwrap() | ||||||
|  |                 .to_string(), | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         if let Some(n) = self.namespace { | ||||||
|  |             args.push("--namespace".to_string()); | ||||||
|  |             args.push(n); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(f) = self.values_file { | ||||||
|  |             args.push("-f".to_string()); | ||||||
|  |             args.push(f.to_str().unwrap().to_string()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(vv) = self.api_versions { | ||||||
|  |             for v in vv { | ||||||
|  |                 args.push("--api-versions".to_string()); | ||||||
|  |                 args.push(v); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(kv) = self.kube_version { | ||||||
|  |             args.push("--kube-version".to_string()); | ||||||
|  |             args.push(kv); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(crd) = self.include_crds { | ||||||
|  |             if crd { | ||||||
|  |                 args.push("--include-crds".to_string()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(st) = self.skip_tests { | ||||||
|  |             if st { | ||||||
|  |                 args.push("--skip-tests".to_string()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(sh) = self.skip_hooks { | ||||||
|  |             if sh { | ||||||
|  |                 args.push("--no-hooks".to_string()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(d) = self.debug { | ||||||
|  |             if d { | ||||||
|  |                 args.push("--debug".to_string()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         args | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user