mod handle;
pub mod state;
mod status;
#[allow(deprecated)]
pub use handle::{key_from_pod, pod_key, Handle};
pub(crate) use status::initialize_pod_container_statuses;
pub use status::{
make_registered_status, make_status, make_status_with_containers, patch_status, Phase, Status,
};
use crate::container::{Container, ContainerKey};
use chrono::{DateTime, Utc};
use k8s_openapi::api::core::v1::{
Container as KubeContainer, Pod as KubePod, Volume as KubeVolume,
};
use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
use kube::api::Meta;
use serde::Deserialize;
use serde::Serialize;
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
pub struct Pod {
#[serde(flatten)]
kube_pod: KubePod,
}
impl Pod {
pub fn name(&self) -> &str {
self.kube_pod
.metadata
.name
.as_deref()
.expect("Pod name should always be set but was not")
}
pub fn namespace(&self) -> &str {
self.kube_pod
.metadata
.namespace
.as_deref()
.unwrap_or("default")
}
pub fn node_selector(&self) -> Option<&std::collections::BTreeMap<String, String>> {
self.kube_pod.spec.as_ref()?.node_selector.as_ref()
}
pub fn service_account_name(&self) -> Option<&str> {
let spec = self.kube_pod.spec.as_ref()?;
spec.service_account_name.as_deref()
}
pub fn volumes(&self) -> Option<&Vec<KubeVolume>> {
let spec = self.kube_pod.spec.as_ref()?;
spec.volumes.as_ref()
}
pub fn host_ip(&self) -> Option<&str> {
let status = self.kube_pod.status.as_ref()?;
status.host_ip.as_deref()
}
pub fn pod_ip(&self) -> Option<&str> {
let status = self.kube_pod.status.as_ref()?;
status.pod_ip.as_deref()
}
pub fn labels(&self) -> &std::collections::BTreeMap<String, String> {
self.kube_pod.meta().labels.as_ref().unwrap_or(&EMPTY_MAP)
}
pub fn annotations(&self) -> &std::collections::BTreeMap<String, String> {
self.kube_pod
.meta()
.annotations
.as_ref()
.unwrap_or(&EMPTY_MAP)
}
pub fn image_pull_secrets(&self) -> Vec<String> {
match self.kube_pod.spec.as_ref() {
None => vec![],
Some(spec) => match spec.image_pull_secrets.as_ref() {
None => vec![],
Some(objrefs) => objrefs
.iter()
.filter_map(|objref| objref.name.clone())
.collect(),
},
}
}
pub fn is_static(&self) -> bool {
self.kube_pod.meta().owner_references.is_none()
}
pub fn is_daemonset(&self) -> bool {
if let Some(owners) = &self.kube_pod.meta().owner_references {
for owner in owners {
if owner.kind == "DaemonSet" {
return true;
}
}
}
false
}
pub fn get_annotation(&self, key: &str) -> Option<&str> {
Some(self.annotations().get(key)?.as_str())
}
pub fn deletion_timestamp(&self) -> Option<&DateTime<Utc>> {
self.kube_pod
.meta()
.deletion_timestamp
.as_ref()
.map(|t| &t.0)
}
pub fn find_container(&self, key: &ContainerKey) -> Option<Container> {
let containers: Vec<Container> = if key.is_init() {
self.init_containers()
} else {
self.containers()
};
containers
.into_iter()
.find(|container| container.name() == key.name())
}
pub fn container_status_index(&self, key: &ContainerKey) -> Option<usize> {
match self.kube_pod.status.as_ref() {
Some(status) => {
match if key.is_init() {
status.init_container_statuses.as_ref()
} else {
status.container_statuses.as_ref()
} {
Some(statuses) => statuses
.iter()
.enumerate()
.find(|(_, status)| status.name == key.name())
.map(|(idx, _)| idx),
None => None,
}
}
None => None,
}
}
pub fn containers(&self) -> Vec<Container> {
self.kube_pod
.spec
.as_ref()
.map(|s| &s.containers)
.unwrap_or_else(|| &EMPTY_VEC)
.iter()
.map(|c| Container::new(c))
.collect()
}
pub fn init_containers(&self) -> Vec<Container> {
self.kube_pod
.spec
.as_ref()
.and_then(|s| s.init_containers.as_ref())
.unwrap_or(&EMPTY_VEC)
.iter()
.map(|c| Container::new(c))
.collect()
}
pub fn all_containers(&self) -> Vec<Container> {
let mut app_containers = self.containers();
let init_containers = self.init_containers();
app_containers.extend(init_containers);
app_containers
}
pub fn into_kube_pod(self) -> KubePod {
self.kube_pod
}
pub fn as_kube_pod(&self) -> &KubePod {
&self.kube_pod
}
}
impl k8s_openapi::Metadata for Pod {
type Ty = ObjectMeta;
fn metadata(&self) -> &ObjectMeta {
self.kube_pod.metadata()
}
fn metadata_mut(&mut self) -> &mut ObjectMeta {
self.kube_pod.metadata_mut()
}
}
impl k8s_openapi::Resource for Pod {
const API_VERSION: &'static str = "v1";
const GROUP: &'static str = "";
const KIND: &'static str = "Pod";
const VERSION: &'static str = "v1";
}
impl std::convert::From<KubePod> for Pod {
fn from(api_pod: KubePod) -> Self {
Self { kube_pod: api_pod }
}
}
impl<'a> std::convert::From<&'a Pod> for &'a KubePod {
fn from(pod: &'a Pod) -> Self {
&pod.kube_pod
}
}
impl std::convert::From<Pod> for KubePod {
fn from(pod: Pod) -> Self {
pod.kube_pod
}
}
#[derive(Hash, Ord, Eq, PartialOrd, PartialEq, Debug, Clone, Default)]
pub struct PodKey {
name: String,
namespace: String,
}
impl PodKey {
pub fn new<N: AsRef<str>, T: AsRef<str>>(namespace: N, pod_name: T) -> Self {
PodKey {
name: pod_name.as_ref().to_owned(),
namespace: namespace.as_ref().to_owned(),
}
}
pub fn name(&self) -> String {
self.name.clone()
}
pub fn namespace(&self) -> String {
self.namespace.clone()
}
}
impl From<Pod> for PodKey {
fn from(p: Pod) -> Self {
PodKey {
name: p.name().to_owned(),
namespace: p.namespace().to_owned(),
}
}
}
impl From<&Pod> for PodKey {
fn from(p: &Pod) -> Self {
PodKey {
name: p.name().to_owned(),
namespace: p.namespace().to_owned(),
}
}
}
impl From<KubePod> for PodKey {
fn from(p: KubePod) -> Self {
PodKey {
name: p.name(),
namespace: p.namespace().unwrap_or_else(|| "default".to_string()),
}
}
}
impl From<&KubePod> for PodKey {
fn from(p: &KubePod) -> Self {
PodKey {
name: p.name(),
namespace: p.namespace().unwrap_or_else(|| "default".to_string()),
}
}
}
lazy_static::lazy_static! {
static ref EMPTY_MAP: std::collections::BTreeMap<String, String> = std::collections::BTreeMap::new();
static ref EMPTY_VEC: Vec<KubeContainer> = Vec::new();
}