From 74a0c4845ade1e8caa799cc16642160e74242e18 Mon Sep 17 00:00:00 2001 From: Brian May Date: Tue, 14 May 2024 12:45:28 +1000 Subject: [PATCH] feat: Refactor release filter command line Update the command line so that all commands filter releases in exactly the same way. BREAKING CHANGE: Command line is different; probably shouldn't affect anything other then my scripts. --- src/main.rs | 121 +++++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 54 deletions(-) diff --git a/src/main.rs b/src/main.rs index 89f90b5..c91d5aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -251,6 +251,9 @@ struct Args { #[clap(long, value_enum)] output: Vec, + #[clap(long)] + release_filter: Vec, + /// Should we process releases that have auto set to false? #[clap(long, value_enum, default_value_t=AutoState::Yes)] auto: AutoState, @@ -259,48 +262,79 @@ struct Args { #[derive(Subcommand, Debug, Clone)] enum Request { /// Upgrade/install releases. - Upgrade { - #[clap()] - releases: Vec, - }, + Upgrade {}, /// Diff releases with current state. - Diff { - #[clap()] - releases: Vec, - }, + Diff {}, /// Test releases. - Test { - #[clap()] - releases: Vec, - }, + Test {}, /// Generate template of releases. - Template { - #[clap()] - releases: Vec, - }, + Template {}, /// Generate outdated report of releases. - Outdated { - #[clap()] - releases: Vec, - }, + Outdated {}, /// Update helm charts. Update { - /// The expected chart type - chart_type: String, - - /// The expected chart name - chart_name: String, - /// List of changes updates: Vec, }, } +#[derive(Clone, Debug)] +enum ReleaseFilter { + ChartType(String), + ChartName(String), + ReleaseName(String), +} + +impl FromStr for ReleaseFilter { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut split = s.splitn(2, '='); + let key = split + .next() + .ok_or_else(|| anyhow!("invalid filter: {}", s))? + .to_string(); + let value = split + .next() + .ok_or_else(|| anyhow!("invalid filter: {}", s))? + .to_string(); + match key.as_str() { + "chart_type" => Ok(ReleaseFilter::ChartType(value)), + "chart_name" => Ok(ReleaseFilter::ChartName(value)), + "release_name" => Ok(ReleaseFilter::ReleaseName(value)), + _ => Err(anyhow!("invalid filter key: {}", key)), + } + } +} + +impl ReleaseFilter { + fn matches(&self, release: &Release) -> bool { + #[allow(clippy::match_same_arms)] + match self { + Self::ChartType(chart_type) => match &release.config.release_chart { + ChartReference::Helm { .. } => chart_type == "helm", + ChartReference::Oci { .. } => chart_type == "oci", + ChartReference::Local { .. } => chart_type == "local", + }, + Self::ChartName(chart_name) => match &release.config.release_chart { + ChartReference::Helm { + chart_name: name, .. + } => chart_name == name, + ChartReference::Oci { + chart_name: name, .. + } => chart_name == name, + ChartReference::Local { .. } => false, + }, + Self::ReleaseName(release_name) => release.name == *release_name, + } + } +} + impl Request { const fn do_depends(&self) -> bool { matches!(self, Self::Upgrade { .. }) @@ -317,31 +351,6 @@ impl Request { Self::Update { .. } => false, } } - - fn do_release(&self, release: &Release) -> bool { - match self { - Request::Upgrade { releases } - | Request::Diff { releases } - | Request::Test { releases } - | Request::Template { releases } - | Request::Outdated { releases } => { - releases.is_empty() || releases.contains(&release.name) - } - Request::Update { - chart_type, - chart_name, - .. - } => match &release.config.release_chart { - ChartReference::Helm { - chart_name: name, .. - } => chart_type == "helm" && *chart_name == *name, - ChartReference::Oci { - chart_name: name, .. - } => chart_type == "oci" && *chart_name == *name, - ChartReference::Local { .. } => false, - }, - } - } } fn get_output(output_format: OutputFormat) -> Result<(Box, Sender)> { @@ -450,7 +459,7 @@ async fn main() -> Result<()> { async fn do_task(command: Arc, args: &Args, output: &output::MultiOutput) -> Result<()> { // let mut helm_repos = HelmRepos::new(); - let (skipped_list, todo) = generate_todo(args, &command)?; + let (skipped_list, todo) = generate_todo(args)?; let mut skipped = InstallationSet::new(); for item in skipped_list { @@ -467,7 +476,6 @@ type SkippedResult = Arc; #[allow(clippy::cognitive_complexity)] fn generate_todo( args: &Args, - command: &Request, ) -> Result<(Vec, Vec>), anyhow::Error> { let vdir = PathBuf::from(&args.vdir); let envs = Env::list_all_env(&vdir) @@ -538,7 +546,12 @@ fn generate_todo( }; // We also do skip entries if the install is to be skipped, these will be shown - let skip = !command.do_release(&release) || release.config.locked || auto_skip; + let skip = args + .release_filter + .iter() + .any(|filter| !filter.matches(&release)) + || release.config.locked + || auto_skip; let installation = create_installation(&env, &cluster, release, next_id); next_id = installation.id + 1;