elasticctl_api/compose/
exception_coverage.rs1use crate::{
2 Rule, exceptions,
3 model::{ListKey, exception_refs},
4};
5use elasticctl_core::{Error, Result, Transport};
6#[derive(Debug)]
7pub struct ListFacts {
8 pub name: Option<String>,
9 pub list_type: Option<String>,
10 pub item_count: u64,
11}
12#[derive(Debug)]
13pub struct ListCoverage {
14 pub key: ListKey,
15 pub ref_type: String,
16 pub facts: std::result::Result<ListFacts, Error>,
17}
18#[derive(Debug)]
19pub struct ExceptionCoverage {
20 pub referenced: usize,
21 pub truncated: bool,
22 pub lists: Vec<ListCoverage>,
23}
24pub async fn exception_coverage(t: &Transport, rule: &Rule) -> Result<ExceptionCoverage> {
25 let refs = exception_refs(rule);
26 let referenced = refs.len();
27 let mut lists = Vec::new();
28 for r in refs.into_iter().take(super::MAX_EXCEPTION_LISTS) {
29 let key = ListKey {
30 list_id: r.list_id,
31 namespace_type: r.namespace_type,
32 };
33 let facts: Result<ListFacts> = async {
34 let list = exceptions::get_list(t, &key).await?;
35 let item_count = exceptions::count_items(t, &key).await?;
36 let field = |k| -> Result<Option<String>> {
37 list.as_map()
38 .get(k)
39 .map(|v| {
40 v.as_str().map(str::to_owned).ok_or_else(|| {
41 Error::new(
42 elasticctl_core::ErrorKind::Http,
43 "invalid exception list field",
44 )
45 })
46 })
47 .transpose()
48 };
49 Ok(ListFacts {
50 name: field("name")?,
51 list_type: field("type")?,
52 item_count,
53 })
54 }
55 .await;
56 if let Err(e) = &facts
57 && super::is_fatal(e.kind)
58 {
59 return Err(facts.unwrap_err());
60 }
61 lists.push(ListCoverage {
62 key,
63 ref_type: r.ref_type,
64 facts,
65 });
66 }
67 Ok(ExceptionCoverage {
68 referenced,
69 truncated: referenced > super::MAX_EXCEPTION_LISTS,
70 lists,
71 })
72}