1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
//! Simple helpers for building and parsing k8s paths.
//!
//! Loosely based on <https://github.com/kubernetes/kubernetes/blob/31305966789525fca49ec26c289e565467d1f1c4/pkg/kubelet/kuberuntime/helpers.go>.
#![deny(missing_docs)]
use std::path::PathBuf;
/// The root directory for pod logs.
const K8S_LOGS_DIR: &str = "/var/log/pods";
/// The delimiter used in the log path.
const LOG_PATH_DELIMITER: &str = "_";
/// Builds absolute log directory path for a pod sandbox.
///
/// Based on <https://github.com/kubernetes/kubernetes/blob/31305966789525fca49ec26c289e565467d1f1c4/pkg/kubelet/kuberuntime/helpers.go#L178>
pub(super) fn build_pod_logs_directory(
pod_namespace: &str,
pod_name: &str,
pod_uid: &str,
) -> PathBuf {
[
K8S_LOGS_DIR,
&[pod_namespace, pod_name, pod_uid].join(LOG_PATH_DELIMITER),
]
.join("/")
.into()
}
/// Parses pod log file path and returns the log file info.
///
/// Assumes the input is a valid pod log file name.
///
/// Inspired by <https://github.com/kubernetes/kubernetes/blob/31305966789525fca49ec26c289e565467d1f1c4/pkg/kubelet/kuberuntime/helpers.go#L186>
pub(super) fn parse_log_file_path(path: &str) -> Option<LogFileInfo<'_>> {
let mut components = path.rsplit(std::path::MAIN_SEPARATOR);
let _log_file_name = components.next()?;
let container_name = components.next()?;
let pod_dir = components.next()?;
let mut pod_dir_components = pod_dir.rsplit(LOG_PATH_DELIMITER);
let pod_uid = pod_dir_components.next()?;
let pod_name = pod_dir_components.next()?;
let pod_namespace = pod_dir_components.next()?;
Some(LogFileInfo {
pod_namespace,
pod_name,
pod_uid,
container_name,
})
}
/// Contains the information extracted from the pod log file path.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct LogFileInfo<'a> {
pub pod_namespace: &'a str,
pub pod_name: &'a str,
pub pod_uid: &'a str,
pub container_name: &'a str,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_build_pod_logs_directory() {
let path = format!(
"{}{}",
std::path::MAIN_SEPARATOR,
[
"var",
"log",
"pods",
"sandbox0-ns_sandbox0-name_sandbox0-uid",
]
.iter()
.collect::<PathBuf>()
.into_os_string()
.into_string()
.unwrap()
);
let s_path = path.as_str();
let cases = vec![
// Valid inputs.
(("sandbox0-ns", "sandbox0-name", "sandbox0-uid"), s_path),
// Invalid inputs.
(("", "", ""), "/var/log/pods/__"),
];
for ((in_namespace, in_name, in_uid), expected) in cases.into_iter() {
assert_eq!(
build_pod_logs_directory(in_namespace, in_name, in_uid),
PathBuf::from(expected)
);
}
}
#[test]
fn test_parse_log_file_path() {
let path = format!(
"{}{}",
std::path::MAIN_SEPARATOR,
[
"var",
"log",
"pods",
"sandbox0-ns_sandbox0-name_sandbox0-uid",
"sandbox0-container0-name",
"1.log",
]
.iter()
.collect::<PathBuf>()
.into_os_string()
.into_string()
.unwrap()
);
let s_path = path.as_str();
let cases = vec![
// Valid inputs.
(
s_path,
Some(LogFileInfo {
pod_namespace: "sandbox0-ns",
pod_name: "sandbox0-name",
pod_uid: "sandbox0-uid",
container_name: "sandbox0-container0-name",
}),
),
// Invalid inputs.
("/var/log/pods/other", None),
("qwe", None),
("", None),
];
for (input, expected) in cases.into_iter() {
assert_eq!(parse_log_file_path(input), expected);
}
}
}