1#![cfg_attr(coverage, feature(coverage_attribute))]
2mod config;
3mod event_list;
4mod filter;
5mod index;
6mod pod_owners_map;
7mod store;
8pub mod watchers;
9
10use std::collections::HashMap;
11
12use kube::api::DynamicObject;
13use serde::{
14 Deserialize,
15 Serialize,
16};
17use sk_core::errors::*;
18use sk_core::k8s::{
19 PodLifecycleData,
20 GVK,
21};
22use sk_core::prelude::*;
23
24pub use crate::config::{
25 TracerConfig,
26 TrackedObjectConfig,
27};
28pub use crate::event_list::TraceEventList;
29pub use crate::index::TraceIndex;
30use crate::pod_owners_map::PodLifecyclesMap;
31pub use crate::store::TraceStore;
32
33#[derive(Clone, Copy, Debug)]
34pub enum TraceAction {
35 ObjectApplied,
36 ObjectDeleted,
37}
38
39#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
40pub struct TraceEvent {
41 pub ts: i64,
42 pub applied_objs: Vec<DynamicObject>,
43 pub deleted_objs: Vec<DynamicObject>,
44}
45
46impl TraceEvent {
47 pub fn len(&self) -> usize {
48 self.applied_objs.len() + self.deleted_objs.len()
49 }
50
51 pub fn is_empty(&self) -> bool {
52 self.applied_objs.is_empty() && self.deleted_objs.is_empty()
53 }
54}
55
56pub struct TraceIterator<'a> {
57 events: &'a TraceEventList,
58 idx: usize,
59}
60
61const CURRENT_TRACE_FORMAT_VERSION: u16 = 2;
62
63pub trait TraceStorable {
64 fn create_or_update_obj(&mut self, obj: &DynamicObject, ts: i64, maybe_old_hash: Option<u64>) -> EmptyResult;
65 fn delete_obj(&mut self, obj: &DynamicObject, ts: i64) -> EmptyResult;
66 fn update_all_objs_for_gvk(&mut self, gvk: &GVK, objs: &[DynamicObject], ts: i64) -> EmptyResult;
67 fn lookup_pod_lifecycle(&self, gvk: &GVK, owner_ns_name: &str, pod_hash: u64, seq: usize) -> PodLifecycleData;
68 fn record_pod_lifecycle(
69 &mut self,
70 ns_name: &str,
71 maybe_pod: Option<corev1::Pod>,
72 owners: Vec<metav1::OwnerReference>,
73 lifecycle_data: &PodLifecycleData,
74 ) -> EmptyResult;
75 fn config(&self) -> &TracerConfig;
76 fn has_obj(&self, gvk: &GVK, ns_name: &str) -> bool;
77 fn start_ts(&self) -> Option<i64>;
78 fn end_ts(&self) -> Option<i64>;
79 fn iter(&self) -> TraceIterator<'_>;
80}
81
82#[derive(Deserialize, Serialize)]
83pub struct ExportedTrace {
84 version: u16,
85 config: TracerConfig,
86 events: Vec<TraceEvent>,
87 index: TraceIndex,
88 pod_lifecycles: HashMap<(GVK, String), PodLifecyclesMap>,
89}
90
91impl ExportedTrace {
92 pub fn append_event(&mut self, event: TraceEvent) {
93 self.events.push(event);
94 }
95
96 pub fn prepend_event(&mut self, event: TraceEvent) {
97 let mut tmp = vec![event];
98 tmp.append(&mut self.events);
99 self.events = tmp;
100 }
101
102 pub fn events(&self) -> Vec<TraceEvent> {
103 self.events.clone()
104 }
105}
106
107#[cfg(test)]
108mod tests;
109
110#[cfg(feature = "mock")]
111#[cfg_attr(coverage, coverage(off))]
112pub mod mock {
113 use mockall::mock;
114
115 use super::*;
116
117 mock! {
118 pub TraceStore {}
119
120 impl TraceStorable for TraceStore {
121 fn create_or_update_obj(&mut self, obj: &DynamicObject, ts: i64, maybe_old_hash: Option<u64>) -> EmptyResult;
122 fn delete_obj(&mut self, obj: &DynamicObject, ts: i64) -> EmptyResult;
123 fn update_all_objs_for_gvk(&mut self, gvk: &GVK, objs: &[DynamicObject], ts: i64) -> EmptyResult;
124 fn lookup_pod_lifecycle(&self, owner_gvk: &GVK, owner_ns_name: &str, pod_hash: u64, seq: usize) -> PodLifecycleData;
125 fn record_pod_lifecycle(
126 &mut self,
127 ns_name: &str,
128 maybe_pod: Option<corev1::Pod>,
129 owners: Vec<metav1::OwnerReference>,
130 lifecycle_data: &PodLifecycleData,
131 ) -> EmptyResult;
132 fn config(&self) -> &TracerConfig;
133 fn has_obj(&self, gvk: &GVK, ns_name: &str) -> bool;
134 fn start_ts(&self) -> Option<i64>;
135 fn end_ts(&self) -> Option<i64>;
136 fn iter<'a>(&'a self) -> TraceIterator<'a>;
137 }
138 }
139}