sk_core/k8s/
pod_ext.rs

1use super::*;
2use crate::prelude::*;
3
4const KUBE_SVC_ACCOUNT_VOLUME_NAME_PREFIX: &str = "kube-api-access";
5
6macro_rules! filter_volumes {
7    ($vols:expr) => {
8        $vols
9            .as_ref()
10            .unwrap_or(&vec![])
11            .iter()
12            .filter(|v| !v.name.starts_with(KUBE_SVC_ACCOUNT_VOLUME_NAME_PREFIX))
13            .cloned()
14            .collect()
15    };
16}
17
18// Helper functions to get references to a pod's spec and status objects
19impl PodExt for corev1::Pod {
20    fn labels_contains_key(&self, key: &str) -> bool {
21        self.metadata.labels.as_ref().unwrap_or(&Default::default()).contains_key(key)
22    }
23
24    fn spec(&self) -> anyhow::Result<&corev1::PodSpec> {
25        match self.spec.as_ref() {
26            None => bail!(KubernetesError::field_not_found("pod spec")),
27            Some(ps) => Ok(ps),
28        }
29    }
30
31    fn stable_spec(&self) -> anyhow::Result<corev1::PodSpec> {
32        let mut spec = self.spec()?.clone();
33        spec.volumes = Some(filter_volumes!(spec.volumes));
34        spec.node_name = None;
35        spec.service_account = None;
36        spec.service_account_name = None;
37
38        if let Some(containers) = spec.init_containers.as_mut() {
39            for container in containers {
40                container.volume_mounts = Some(filter_volumes!(container.volume_mounts));
41            }
42        }
43
44        for container in &mut spec.containers {
45            container.volume_mounts = Some(filter_volumes!(container.volume_mounts));
46
47            // We strip ports when running the simulation (see note in driver/mutation.rs)
48            // so we also need to strip them when computing the pod hash
49            //
50            // A reasonable question might be, why don't we just strip the ports when we collect
51            // the trace?  My current hypothesis is that saving as much data as possible during
52            // the trace, and then allowing the things processing the trace to do whatever they
53            // need with it is a "better" option, but it results in us having to modify things
54            // in two places at once, which could cause problems in the future.
55            //
56            // TODO is it possible to write a test to check for this somehow?
57            container.ports = None
58        }
59
60        Ok(spec)
61    }
62
63    fn status(&self) -> anyhow::Result<&corev1::PodStatus> {
64        match self.status.as_ref() {
65            None => bail!(KubernetesError::field_not_found("pod status")),
66            Some(ps) => Ok(ps),
67        }
68    }
69}