helm_schema_cli/cli/crd_args.rs
1use std::path::PathBuf;
2
3use clap::{Args, ValueEnum};
4
5/// Policy for resolving CRD versions missing from the configured catalog.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, ValueEnum)]
7pub enum CrdVersionLookup {
8 /// Consult only the exact group, kind, and version.
9 #[default]
10 Strict,
11 /// Scan other versions and emit informational alternatives.
12 Loose,
13}
14
15/// CRD catalog, override, cache, and version-resolution options.
16#[derive(Args, Debug, Clone)]
17pub struct CrdArgs {
18 /// CRD version lookup mode. Default `strict`: only the exact
19 /// `(group, kind, version)` is consulted. `loose` enables cross-scan
20 /// + informational hints; mirrors are available in BOTH modes.
21 #[arg(long = "crd-version-lookup", value_enum, default_value_t = CrdVersionLookup::Strict)]
22 pub crd_version_lookup: CrdVersionLookup,
23
24 /// Short alias for `--crd-version-lookup=strict`. Kept for
25 /// symmetry with `--strict-k8s-version` / `--strict-api-versions`
26 /// and to keep CI opt-out flags short.
27 #[arg(long = "strict-crd-version")]
28 pub strict_crd_version: bool,
29
30 /// Additional upstream CRD catalog mirror URL. Repeatable.
31 /// Per-source cache namespacing keeps mirror entries from masking
32 /// the default.
33 #[arg(long = "crd-catalog-mirror")]
34 pub crd_catalog_mirror: Vec<String>,
35
36 /// Managed cache root for CRD schemas. Subject to the cache
37 /// invalidation contract.
38 #[arg(long = "crd-catalog-cache-dir")]
39 pub crd_catalog_cache_dir: Option<PathBuf>,
40
41 /// Hand-maintained CRD schema overrides. Never wiped, never
42 /// subject to the cache invalidation contract.
43 #[arg(long = "crd-override-dir")]
44 pub crd_override_dir: Option<PathBuf>,
45
46 /// Write a `<schema>.json.meta` sidecar alongside every CRD cache
47 /// entry recording the fetch URL and timestamp.
48 #[arg(long = "crd-cache-record-source")]
49 pub crd_cache_record_source: bool,
50
51 /// Removed in this alpha — use `--crd-override-dir` and/or
52 /// `--crd-catalog-cache-dir` instead.
53 #[arg(long = "crd-catalog-dir", hide = true)]
54 pub crd_catalog_dir_removed: Option<PathBuf>,
55}
56
57impl CrdArgs {
58 /// Resolved version-lookup mode after considering the alias flag.
59 #[must_use]
60 pub fn lookup_mode(&self) -> CrdVersionLookup {
61 if self.strict_crd_version {
62 CrdVersionLookup::Strict
63 } else {
64 self.crd_version_lookup
65 }
66 }
67
68 /// Validate CRD-related flags. Returns a user-facing error string
69 /// on invalid combinations.
70 ///
71 /// # Errors
72 ///
73 /// Returns an error for removed flags or overlapping managed and
74 /// hand-maintained cache directories.
75 pub fn validate(&self) -> Result<(), String> {
76 if self.crd_catalog_dir_removed.is_some() {
77 return Err(
78 "--crd-catalog-dir is removed; use --crd-override-dir (hand-maintained schemas, never wiped) and/or --crd-catalog-cache-dir (managed cache root)".to_string(),
79 );
80 }
81 if let (Some(o), Some(c)) = (&self.crd_override_dir, &self.crd_catalog_cache_dir)
82 && o == c
83 {
84 return Err(
85 "--crd-override-dir and --crd-catalog-cache-dir must point at different paths (override is hand-maintained, cache is wipe-eligible)".to_string(),
86 );
87 }
88 Ok(())
89 }
90}