helm_schema_k8s/diagnostic/
format_text.rs1use std::fmt::Write;
2
3use super::diagnostic::Diagnostic;
4
5#[must_use]
9#[expect(
10 clippy::too_many_lines,
11 reason = "one exhaustive match keeps every diagnostic's user-facing rendering auditable"
12)]
13pub fn format_diagnostic_text(diagnostic: &Diagnostic) -> String {
14 match diagnostic {
15 Diagnostic::MissingSchema {
16 kind,
17 api_version,
18 k8s_versions_tried,
19 available_in_cache_versions,
20 suggested_k8s_version,
21 hint,
22 ..
23 } => {
24 let mut out = String::new();
25 let _ = if api_version.trim().is_empty() {
26 write!(
27 out,
28 "warning: no upstream Kubernetes JSON schema found for {kind} (apiVersion unknown)"
29 )
30 } else {
31 write!(
32 out,
33 "warning: no upstream Kubernetes JSON schema found for {kind} ({api_version})"
34 )
35 };
36 if !k8s_versions_tried.is_empty() {
37 let _ = write!(out, " in {}", k8s_versions_tried.join(", "));
38 }
39 if !available_in_cache_versions.is_empty() {
40 let _ = write!(
41 out,
42 "; available in local cache for: {}",
43 available_in_cache_versions.join(", ")
44 );
45 }
46 if let Some(s) = suggested_k8s_version {
47 let _ = write!(out, "; try --k8s-version {s}");
48 }
49 if let Some(h) = hint {
50 let _ = write!(out, "; {h}");
51 }
52 out
53 }
54 Diagnostic::ResolvedFromFallbackVersion {
55 kind,
56 api_version,
57 primary_version,
58 resolved_version,
59 } => format!(
60 "info: {kind} ({api_version}) resolved from K8s {resolved_version} (not in primary {primary_version})"
61 ),
62 Diagnostic::InferredApiVersion {
63 kind,
64 inferred_api_version,
65 source,
66 ..
67 } => format!(
68 "info: inferred apiVersion {inferred_api_version} for {kind} (source: {source:?})"
69 ),
70 Diagnostic::AmbiguousApiVersion { kind, candidates } => {
71 let list = candidates
72 .iter()
73 .map(|c| c.api_version.as_str())
74 .collect::<Vec<_>>()
75 .join(", ");
76 format!("warning: ambiguous apiVersion inference for {kind}: candidates [{list}]")
77 }
78 Diagnostic::CrdVersionNotFound {
79 group,
80 kind,
81 requested_version,
82 locations_tried,
83 } => {
84 let mut out = format!(
85 "warning: CRD schema not found for {group}/{kind} version {requested_version}"
86 );
87 if !locations_tried.is_empty() {
88 let _ = write!(out, "; tried: {}", locations_tried.join(", "));
89 }
90 out
91 }
92 Diagnostic::CrdVersionAvailableAtOtherVersions {
93 group,
94 kind,
95 requested_version,
96 available_versions,
97 } => format!(
98 "info: {group}/{kind} {requested_version} not found, but cached at versions: {}",
99 available_versions.join(", ")
100 ),
101 Diagnostic::LocalOverrideUnreadable {
102 kind,
103 api_version,
104 override_path,
105 io_error,
106 } => format!(
107 "warning: local override for {kind} ({api_version}) at {override_path} is unreadable: {io_error}"
108 ),
109 Diagnostic::CacheLayoutInvalidated {
110 cache_root,
111 previous_marker,
112 current_marker,
113 } => {
114 let prev = previous_marker
115 .map(|n| n.to_string())
116 .unwrap_or_else(|| "none".to_string());
117 format!(
118 "info: cache layout for {cache_root} invalidated (previous: {prev}, current: {current_marker})"
119 )
120 }
121 Diagnostic::CacheLayoutForwardIncompatible {
122 cache_root,
123 on_disk_marker,
124 compiled_marker,
125 } => format!(
126 "warning: cache at {cache_root} was written by a newer helm-schema (on-disk: {on_disk_marker}, this binary: {compiled_marker}); refusing to mutate"
127 ),
128 Diagnostic::InputChannelNumericRangeAmbiguity { value_path } => format!(
129 "warning: {value_path} has input-channel-dependent integer range semantics: Helm can iterate an integer from --set but rejects the same JSON number from a values file or --set-json; JSON Schema cannot distinguish those inputs"
130 ),
131 }
132}