lean_ctx_patterns/
linkerd.rs1use crate::ansi::strip_ansi;
11
12pub fn compress(command: &str, output: &str) -> Option<String> {
13 let sub = command
14 .trim()
15 .strip_prefix("linkerd")
16 .map_or("", str::trim_start)
17 .split_whitespace()
18 .next()
19 .unwrap_or("");
20 if sub != "check" {
21 return None;
22 }
23 Some(compress_check(output))
24}
25
26fn compress_check(output: &str) -> String {
27 let mut kept: Vec<String> = Vec::new();
28 let mut passed = 0usize;
29 let mut failed = 0usize;
30 let mut in_failure = false;
31
32 for raw in output.lines() {
33 let line = strip_ansi(raw);
34 let t = line.trim_end();
35 let probe = t.trim();
36 if probe.is_empty() {
37 in_failure = false;
38 continue;
39 }
40 if probe.chars().all(|c| c == '-') {
42 continue;
43 }
44 if probe.starts_with('√') || probe.starts_with('✓') {
45 passed += 1;
46 in_failure = false;
47 continue;
48 }
49 if probe.starts_with('×') || probe.starts_with('✗') {
50 failed += 1;
51 in_failure = true;
52 kept.push(probe.to_string());
53 continue;
54 }
55 if in_failure && (t.starts_with(' ') || t.starts_with('\t')) {
57 kept.push(probe.to_string());
58 continue;
59 }
60 let pl = probe.to_ascii_lowercase();
61 if pl.starts_with("status check results") {
62 kept.push(probe.to_string());
63 in_failure = false;
64 }
65 }
66
67 let tally = format!("linkerd check: {passed} passed, {failed} failed");
68 if kept.is_empty() {
69 return tally;
70 }
71 format!("{tally}\n{}", kept.join("\n"))
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 const CHECK: &str = "kubernetes-api\n--------------\n√ can initialize the client\n√ can query the Kubernetes API\n\nlinkerd-existence\n-----------------\n√ 'linkerd-config' config map exists\n× control plane pods are ready\n some pods are not ready: linkerd-destination-abc\n see https://linkerd.io/2/checks/#l5d-api-control-ready for hints\n\nStatus check results are ×\n";
79
80 #[test]
81 fn keeps_failures_and_verdict_drops_passing() {
82 let r = compress("linkerd check", CHECK).unwrap();
83 assert!(r.contains("× control plane pods are ready"), "{r}");
84 assert!(r.contains("some pods are not ready"), "keeps hint: {r}");
85 assert!(r.contains("Status check results are ×"), "{r}");
86 assert!(r.contains("3 passed, 1 failed"), "tally: {r}");
87 assert!(
88 !r.contains("can initialize the client"),
89 "drops passing: {r}"
90 );
91 }
92
93 #[test]
94 fn non_check_subcommand_passes_through() {
95 assert!(compress("linkerd viz stat deploy", "some table").is_none());
96 }
97}