use k8s_openapi::api::core::v1::Container as KubeContainer;
use oci_distribution::Reference;
use std::convert::TryInto;
use std::fmt::Display;
mod handle;
pub mod state;
mod status;
pub use handle::{Handle, HandleMap};
pub use status::{make_initial_container_status, patch_container_status, Status};
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum PullPolicy {
Always,
IfNotPresent,
Never,
}
impl PullPolicy {
pub fn parse_effective(policy: Option<&str>, image: Option<Reference>) -> anyhow::Result<Self> {
match PullPolicy::parse(policy)? {
Some(policy) => Ok(policy),
None => match image {
Some(image) => match image.tag() {
Some("latest") | None => Ok(PullPolicy::Always),
_ => Ok(PullPolicy::IfNotPresent),
},
None => Ok(PullPolicy::IfNotPresent),
},
}
}
pub fn parse(name: Option<&str>) -> anyhow::Result<Option<Self>> {
match name {
None => Ok(None),
Some(s) => Self::parse_str(s),
}
}
fn parse_str(name: &str) -> anyhow::Result<Option<Self>> {
match name {
"Always" => Ok(Some(Self::Always)),
"IfNotPresent" => Ok(Some(Self::IfNotPresent)),
"Never" => Ok(Some(Self::Never)),
other => Err(anyhow::anyhow!("unrecognized pull policy {}", other)),
}
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum ContainerKey {
Init(String),
App(String),
}
impl ContainerKey {
pub fn name(&self) -> String {
match self {
Self::Init(name) | Self::App(name) => name.to_string(),
}
}
pub fn is_app(&self) -> bool {
matches!(self, Self::App(_))
}
pub fn is_init(&self) -> bool {
matches!(self, Self::Init(_))
}
}
impl Display for ContainerKey {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
self.name().fmt(formatter)
}
}
pub type ContainerMap<V> = std::collections::HashMap<ContainerKey, V>;
pub trait ContainerMapByName<V> {
fn get_mut_by_name(&mut self, name: String) -> Option<&mut V>;
fn contains_key_name(&self, name: &str) -> bool;
}
impl<V> ContainerMapByName<V> for ContainerMap<V> {
fn get_mut_by_name(&mut self, name: String) -> Option<&mut V> {
let app_key = ContainerKey::App(name.clone());
if self.contains_key(&app_key) {
self.get_mut(&app_key)
} else {
self.get_mut(&ContainerKey::Init(name))
}
}
fn contains_key_name(&self, name: &str) -> bool {
self.contains_key(&ContainerKey::App(name.to_owned()))
|| self.contains_key(&ContainerKey::Init(name.to_owned()))
}
}
#[derive(Default, Debug, Clone)]
pub struct Container(KubeContainer);
impl Container {
pub fn new(container: &KubeContainer) -> Self {
Container(container.clone())
}
pub fn args(&self) -> &Option<Vec<String>> {
&self.0.args
}
pub fn command(&self) -> &Option<Vec<String>> {
&self.0.command
}
pub fn env(&self) -> &Option<Vec<k8s_openapi::api::core::v1::EnvVar>> {
&self.0.env
}
pub fn env_from(&self) -> &Option<Vec<k8s_openapi::api::core::v1::EnvFromSource>> {
&self.0.env_from
}
pub fn image(&self) -> anyhow::Result<Option<Reference>> {
match self.0.image.as_ref() {
Some(s) => Ok(Some(s.clone().try_into()?)),
None => Ok(None),
}
}
pub fn effective_pull_policy(&self) -> anyhow::Result<PullPolicy> {
PullPolicy::parse_effective(self.0.image_pull_policy.as_deref(), self.image()?)
}
pub fn lifecycle(&self) -> Option<&k8s_openapi::api::core::v1::Lifecycle> {
self.0.lifecycle.as_ref()
}
pub fn liveness_probe(&self) -> Option<&k8s_openapi::api::core::v1::Probe> {
self.0.liveness_probe.as_ref()
}
pub fn name(&self) -> &str {
&self.0.name
}
pub fn ports(&self) -> &Option<Vec<k8s_openapi::api::core::v1::ContainerPort>> {
&self.0.ports
}
pub fn readiness_probe(&self) -> Option<&k8s_openapi::api::core::v1::Probe> {
self.0.readiness_probe.as_ref()
}
pub fn resources(&self) -> Option<&k8s_openapi::api::core::v1::ResourceRequirements> {
self.0.resources.as_ref()
}
pub fn security_context(&self) -> Option<&k8s_openapi::api::core::v1::SecurityContext> {
self.0.security_context.as_ref()
}
pub fn startup_probe(&self) -> Option<&k8s_openapi::api::core::v1::Probe> {
self.0.startup_probe.as_ref()
}
pub fn stdin(&self) -> Option<bool> {
self.0.stdin
}
pub fn stdin_once(&self) -> Option<bool> {
self.0.stdin_once
}
pub fn termination_message_path(&self) -> Option<&String> {
self.0.termination_message_path.as_ref()
}
pub fn termination_message_policy(&self) -> Option<&String> {
self.0.termination_message_policy.as_ref()
}
pub fn tty(&self) -> Option<bool> {
self.0.tty
}
pub fn volume_devices(&self) -> &Option<Vec<k8s_openapi::api::core::v1::VolumeDevice>> {
&self.0.volume_devices
}
pub fn volume_mounts(&self) -> &Option<Vec<k8s_openapi::api::core::v1::VolumeMount>> {
&self.0.volume_mounts
}
pub fn working_dir(&self) -> Option<&String> {
self.0.working_dir.as_ref()
}
}