helm_schema/
provider_builder.rs1use std::path::PathBuf;
2use std::sync::Arc;
3
4use helm_schema_k8s::{
5 Chain, ChartLocalCrdSchemaProvider, CrdsCatalogSchemaProvider, DiagnosticSink,
6 K8sSchemaProvider, K8sVersionChain, KubernetesJsonSchemaProvider, LayoutChecker,
7 LocalSchemaProvider, LocalSchemaUniverse, NegativeCache,
8};
9use tracing::instrument;
10
11#[derive(Debug, Clone, Default)]
14pub struct ProviderOptions {
15 pub k8s_versions: Vec<String>,
17 pub k8s_version_fallback_window: Option<u32>,
19 pub k8s_schema_mirrors: Vec<String>,
21 pub k8s_schema_cache_dir: Option<PathBuf>,
23 pub no_cache: bool,
25
26 pub allow_net: bool,
28 pub disable_k8s_schemas: bool,
30
31 pub crd_lookup_loose: bool,
34 pub crd_catalog_mirrors: Vec<String>,
36 pub crd_catalog_cache_dir: Option<PathBuf>,
38 pub crd_override_dir: Option<PathBuf>,
40 pub local_schema_universe: LocalSchemaUniverse,
42 pub crd_cache_record_source: bool,
44
45 pub api_version_guess: bool,
47}
48
49#[instrument(skip_all)]
50pub fn build_provider(opts: &ProviderOptions, diagnostic_sink: Option<&DiagnosticSink>) -> Chain {
51 let mut providers: Vec<Box<dyn K8sSchemaProvider>> = Vec::new();
52 let negative_cache = Arc::new(NegativeCache::new());
53 let layout_checker = Arc::new(LayoutChecker::new());
54
55 if let Some(dir) = &opts.crd_override_dir {
56 providers.push(Box::new(
57 LocalSchemaProvider::new(dir.clone()).with_api_version_guess(opts.api_version_guess),
58 ));
59 }
60
61 let chart_local_provider = ChartLocalCrdSchemaProvider::new(opts.local_schema_universe.clone())
62 .with_api_version_guess(opts.api_version_guess);
63 if !chart_local_provider.is_empty() {
64 providers.push(Box::new(chart_local_provider));
65 }
66
67 let mut crds_catalog = CrdsCatalogSchemaProvider::new()
68 .with_allow_download(opts.allow_net)
69 .with_mirrors(opts.crd_catalog_mirrors.clone())
70 .with_loose(opts.crd_lookup_loose)
71 .with_api_version_guess(opts.api_version_guess)
72 .with_negative_cache(Arc::clone(&negative_cache))
73 .with_layout_checker(Arc::clone(&layout_checker))
74 .with_record_source(opts.crd_cache_record_source);
75 if let Some(dir) = &opts.crd_catalog_cache_dir {
76 crds_catalog = crds_catalog.with_cache_dir(dir.clone());
77 }
78 if let Some(sink) = diagnostic_sink {
79 crds_catalog = crds_catalog.with_diagnostic_sink(sink.clone());
80 }
81 providers.push(Box::new(crds_catalog));
82
83 if !opts.disable_k8s_schemas {
84 let versions =
85 K8sVersionChain::new(opts.k8s_versions.clone(), opts.k8s_version_fallback_window);
86 let mut k8s = KubernetesJsonSchemaProvider::with_versions(versions)
87 .with_allow_download(opts.allow_net)
88 .with_use_cache(!opts.no_cache)
89 .with_mirrors(opts.k8s_schema_mirrors.clone())
90 .with_api_version_guess(opts.api_version_guess)
91 .with_negative_cache(Arc::clone(&negative_cache))
92 .with_layout_checker(Arc::clone(&layout_checker));
93 if let Some(dir) = &opts.k8s_schema_cache_dir {
94 k8s = k8s.with_cache_dir(dir.clone());
95 }
96 if let Some(sink) = diagnostic_sink {
97 k8s = k8s.with_diagnostic_sink(sink.clone());
98 }
99 providers.push(Box::new(k8s));
100 }
101
102 let mut chain = Chain::new(providers).with_inference_enabled(opts.api_version_guess);
103 if let Some(sink) = diagnostic_sink {
104 chain = chain.with_diagnostic_sink(sink.clone());
105 }
106 chain
107}