Init commit

This commit is contained in:
2024-01-10 12:33:05 +01:00
commit 09f81a5899
32 changed files with 2737 additions and 0 deletions

69
src/source/git.rs Normal file
View File

@ -0,0 +1,69 @@
use std::fs::{self, rename};
use crate::helpers::cli::{cli_exec, cli_exec_from_dir};
use base64::{engine::general_purpose, Engine as _};
use super::{ChartLocal, Repo};
pub(crate) struct Git {
git_url: String,
git_ref: String,
path: String,
pub(crate) chart: String,
}
impl From<crate::config::Chart> for Git {
fn from(value: crate::config::Chart) -> Self {
Git {
git_url: value.get_git_repository_url(),
git_ref: value.get_git_repository_ref(),
path: value.get_git_repository_path(),
chart: value.name,
}
}
}
impl Repo for Git {
fn pull(&self, workdir_path: String) -> Result<ChartLocal, Box<dyn std::error::Error>> {
let repo_local_name = general_purpose::STANDARD_NO_PAD.encode(self.git_url.clone());
let cmd = format!(
"git clone {} {}/{}",
self.git_url, workdir_path, repo_local_name
);
cli_exec(cmd)?;
let cmd = format!(
"git -C {}/{} checkout {}",
workdir_path, repo_local_name, self.git_ref
);
cli_exec(cmd)?;
let old_dir_name = format!(
"{}/{}/{}/{}",
workdir_path, repo_local_name, self.path, self.chart
);
let cmd = format!("helm show chart {}", old_dir_name);
let helm_stdout = cli_exec(cmd)?;
let new_dir_name: String;
match serde_yaml::from_str::<super::Version>(&helm_stdout) {
Ok(res) => {
new_dir_name = format!("{}/{}-{}", workdir_path, self.chart, res.version);
rename(old_dir_name, new_dir_name.clone())?;
}
Err(err) => return Err(Box::from(err)),
};
// Cleaning up
fs::remove_dir_all(format!("{}/{}", workdir_path, repo_local_name))?;
// Get the version
let cmd = "helm show chart . | yq '.version'".to_string();
let version = cli_exec_from_dir(cmd, new_dir_name.clone())?;
Ok(ChartLocal {
name: self.chart.clone(),
version,
path: new_dir_name,
repo_url: self.git_url.clone(),
})
}
}

105
src/source/helm.rs Normal file
View File

@ -0,0 +1,105 @@
use super::{ChartLocal, Repo};
use crate::helpers::cli::{cli_exec, cli_exec_from_dir};
use base64::{engine::general_purpose, Engine as _};
use std::fs::rename;
pub(crate) enum RepoKind {
Default,
Oci,
}
const LATEST_VERSION: &str = "latest";
pub(crate) struct Helm {
pub(crate) chart: String,
pub(crate) repository_url: String,
pub(crate) version: String,
}
impl From<crate::config::Chart> for Helm {
fn from(value: crate::config::Chart) -> Self {
Helm {
chart: value.name.clone(),
repository_url: value.get_helm_repository_url(),
version: match value.version {
Some(res) => res,
None => LATEST_VERSION.to_string(),
},
}
}
}
impl Helm {
fn repo_kind_from_url(&self) -> Result<RepoKind, Box<dyn std::error::Error>> {
let prefix = self
.repository_url
.chars()
.take_while(|&ch| ch != ':')
.collect::<String>();
match prefix.as_str() {
"oci" => Ok(RepoKind::Oci),
"https" | "http" => Ok(RepoKind::Default),
_ => Err(Box::from(format!(
"repo kind is not defined by the prefix: {}",
prefix
))),
}
}
fn pull_default(&self, workdir_path: String) -> Result<ChartLocal, Box<dyn std::error::Error>> {
// Add repo and update
let repo_local_name = general_purpose::STANDARD_NO_PAD.encode(self.repository_url.clone());
let cmd = format!("helm repo add {} {}", repo_local_name, self.repository_url);
cli_exec(cmd)?;
cli_exec("helm repo update".to_string())?;
let args = match self.version.as_str() {
LATEST_VERSION => "".to_string(),
_ => format!("--version {}", self.version.clone()),
};
let cmd = format!(
"helm pull {}/{} {} --destination {} --untar",
repo_local_name, &self.chart, args, workdir_path
);
cli_exec(cmd)?;
// Get the version
let cmd = format!("helm show chart {}/{}", workdir_path, &self.chart);
let helm_stdout = cli_exec(cmd)?;
let old_dir_name = format!("{}/{}", workdir_path, &self.chart);
let new_dir_name: String;
match serde_yaml::from_str::<super::Version>(&helm_stdout) {
Ok(res) => {
new_dir_name = format!("{}-{}", old_dir_name, res.version);
rename(old_dir_name, new_dir_name.clone())?;
}
Err(err) => return Err(Box::from(err)),
};
//cleaning up
let cmd = format!("helm repo remove {}", repo_local_name);
cli_exec(cmd)?;
let cmd = "helm show chart . | yq '.version'".to_string();
let version = cli_exec_from_dir(cmd, new_dir_name.clone())?;
Ok(ChartLocal {
name: self.chart.clone(),
version,
path: new_dir_name,
repo_url: self.repository_url.clone(),
})
}
}
impl Repo for Helm {
fn pull(&self, workdir_path: String) -> Result<ChartLocal, Box<dyn std::error::Error>> {
let repository_kind = self.repo_kind_from_url()?;
let path = match repository_kind {
RepoKind::Default => self.pull_default(workdir_path)?,
RepoKind::Oci => {
todo!()
}
};
Ok(path)
}
}

46
src/source/mod.rs Normal file
View File

@ -0,0 +1,46 @@
use crate::config::Chart;
use serde::{Deserialize, Serialize};
pub(crate) mod git;
pub(crate) mod helm;
#[derive(Deserialize, Serialize, Clone)]
pub(crate) struct ChartLocal {
pub(crate) name: String,
pub(crate) version: String,
pub(crate) path: String,
pub(crate) repo_url: String,
}
impl ChartLocal {
pub(crate) fn test(&self) -> String {
"test-me-if-you-can".to_string()
}
}
pub(crate) trait Repo {
fn pull(&self, workdir_path: String) -> Result<ChartLocal, Box<dyn std::error::Error>>;
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub(crate) struct Version {
pub(crate) version: String,
}
pub(crate) fn repo_from_chart(chart: Chart) -> Result<Box<dyn Repo>, Box<dyn std::error::Error>> {
match chart.get_repo_kind() {
Ok(res) => {
return match res {
crate::config::RepositoryKind::Helm => {
let helm: helm::Helm = chart.into();
Ok(Box::new(helm))
}
crate::config::RepositoryKind::Git => {
let git: git::Git = chart.into();
Ok(Box::new(git))
}
}
}
Err(err) => return Err(Box::from(err)),
};
}