rkubectl_kubeapi/
cache.rs1use indexmap::IndexMap;
2
3use super::*;
4
5#[derive(Clone, Debug, Default)]
6pub struct Cache {
7 groups: Option<metav1::APIGroupList>,
8 resources: IndexMap<String, metav1::APIResourceList>,
9 took: time::Duration,
10 _pad: (),
11}
12
13impl Cache {
14 pub(super) fn try_load(self, path: impl AsRef<Path>) -> Self {
15 let start = time::Instant::now();
16 let cached_resources = CachedResources::new(path);
17 let groups = cached_resources.load_server_groups().ok();
18 let resources = groups
19 .as_ref()
20 .map(|groups| cached_resources.load_groups_resources(groups))
21 .unwrap_or_default();
22 let took = start.elapsed();
23 Self {
24 groups,
25 resources,
26 took,
27 ..self
28 }
29 }
30
31 pub(super) fn api_groups(&self) -> Option<metav1::APIGroupList> {
32 self.groups.clone()
33 }
34
35 pub(super) fn api_resources(&self) -> Option<Vec<metav1::APIResourceList>> {
36 let resources = self.resources.values().cloned().collect::<Vec<_>>();
37 if resources.is_empty() {
38 None
39 } else {
40 Some(resources)
41 }
42 }
43
44 pub fn took(&self) -> time::Duration {
45 self.took
46 }
47}
48
49struct CachedResources {
50 path: PathBuf,
51}
52
53impl CachedResources {
54 const SERVER_GROUPS: &'static str = "servergroups.json";
55 const SERVER_RESOURCES: &'static str = "serverresources.json";
56
57 fn new(path: impl AsRef<Path>) -> Self {
58 let path = path.as_ref().to_path_buf();
59 trace!(from = %path.display(), "Loading cached resources");
60 Self { path }
61 }
62
63 fn load_server_groups(&self) -> io::Result<metav1::APIGroupList> {
64 let path = self.path.join(Self::SERVER_GROUPS);
65 load_json(path)
66 }
67
68 fn load_groups_resources(
69 &self,
70 groups: &metav1::APIGroupList,
71 ) -> IndexMap<String, metav1::APIResourceList> {
72 groups
73 .groups
74 .iter()
75 .flat_map(|group| group.versions.iter())
76 .filter_map(|version| self.load_server_group_version_resources(version).ok())
77 .map(|arl| (arl.group_version.clone(), arl))
78 .collect()
79 }
80
81 fn load_server_group_version_resources(
82 &self,
83 version: &metav1::GroupVersionForDiscovery,
84 ) -> io::Result<metav1::APIResourceList> {
85 let path = self
86 .path
87 .join(&version.group_version)
88 .join(Self::SERVER_RESOURCES);
89 load_json(path)
90 }
91}
92
93#[tracing::instrument(level = "trace", err)]
94fn load_json<T>(path: PathBuf) -> io::Result<T>
95where
96 T: serde::de::DeserializeOwned,
97{
98 trace!("Loading cached data");
99 let text = fs::read_to_string(path)?;
100 let data = json::from_str(&text)?;
101 Ok(data)
102}