netdox_plugin_rs/
get.rs

1use redis::{self, cmd, AsyncCommands};
2use std::collections::{HashMap, HashSet};
3
4use crate::{
5    error::{FCallError, FCallResult},
6    model::{NetdoxReader, Node},
7};
8
9const QUALIFY_DNS_NAME_FN: &str = "netdox_qualify_dns_names";
10
11const META_KEY: &str = "meta";
12const DNS_KEY: &str = "dns";
13const NODES_KEY: &str = "nodes";
14const PROC_NODES_KEY: &str = "proc_nodes";
15const DEFAULT_NETWORK_KEY: &str = "default_network";
16
17impl NetdoxReader for redis::aio::MultiplexedConnection {
18    async fn get_default_network(&mut self) -> FCallResult<String> {
19        Ok(self.get(DEFAULT_NETWORK_KEY).await?)
20    }
21
22    async fn qualify_dns_names(&mut self, names: Vec<String>) -> FCallResult<Vec<String>> {
23        Ok(cmd("FCALL")
24            .arg(QUALIFY_DNS_NAME_FN)
25            .arg(names.len() as u32)
26            .arg(&names)
27            .query_async(self)
28            .await?)
29    }
30
31    async fn get_dns_names(&mut self) -> FCallResult<HashSet<String>> {
32        Ok(self.smembers(DNS_KEY).await?)
33    }
34
35    async fn get_nodes(&mut self) -> FCallResult<Vec<Node>> {
36        let mut nodes = Vec::new();
37        let link_ids: Vec<String> = self.smembers(PROC_NODES_KEY).await?;
38        for link_id in link_ids {
39            nodes.push(self.get_node(&link_id).await?);
40        }
41        Ok(nodes)
42    }
43
44    async fn get_node(&mut self, link_id: &str) -> FCallResult<Node> {
45        let name: String = self.get(format!("{PROC_NODES_KEY};{link_id}")).await?;
46        let alt_names: HashSet<String> = self
47            .smembers(format!("{PROC_NODES_KEY};{link_id};alt_names"))
48            .await?;
49        let dns_names: HashSet<String> = self
50            .smembers(format!("{PROC_NODES_KEY};{link_id};dns_names"))
51            .await?;
52        let raw_ids: HashSet<String> = self
53            .smembers(format!("{PROC_NODES_KEY};{link_id};raw_ids"))
54            .await?;
55        let plugins: HashSet<String> = self
56            .smembers(format!("{PROC_NODES_KEY};{link_id};plugins"))
57            .await?;
58
59        Ok(Node {
60            name,
61            link_id: link_id.to_string(),
62            alt_names,
63            dns_names,
64            raw_ids,
65            plugins,
66        })
67    }
68
69    async fn get_dns_metadata(&mut self, name: &str) -> FCallResult<HashMap<String, String>> {
70        let qualified_name = match self
71            .qualify_dns_names(vec![name.to_string()])
72            .await?
73            .into_iter()
74            .next()
75        {
76            Some(qn) => qn,
77            None => {
78                return Err(FCallError::Logic(
79                    "Tried to qualify one DNS name but got zero back.",
80                ))
81            }
82        };
83
84        Ok(self
85            .hgetall(format!("{META_KEY};{DNS_KEY};{qualified_name}"))
86            .await?)
87    }
88
89    async fn get_node_metadata(&mut self, node: &Node) -> FCallResult<HashMap<String, String>> {
90        let mut meta = HashMap::new();
91        for raw_id in &node.raw_ids {
92            let raw_meta: HashMap<String, String> = self
93                .hgetall(format!("{META_KEY};{NODES_KEY};{raw_id}"))
94                .await?;
95            meta.extend(raw_meta);
96        }
97        let proc_meta: HashMap<String, String> = self
98            .hgetall(format!("{META_KEY};{PROC_NODES_KEY};{}", node.link_id))
99            .await?;
100        meta.extend(proc_meta);
101        Ok(meta)
102    }
103}