diff --git a/README.md b/README.md index 23fb488fc..c20bd8c4c 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Select a version of `kube` along with the generated [k8s-openapi](https://github [dependencies] kube = "0.58.1" kube-runtime = "0.58.1" -k8s-openapi = { version = "0.12.0", default-features = false, features = ["v1_20"] } +k8s-openapi = { version = "0.13.0", default-features = false, features = ["v1_20"] } ``` [Features are available](/~https://github.com/kube-rs/kube-rs/blob/master/kube/Cargo.toml#L18). @@ -159,7 +159,7 @@ Kube has basic support ([with caveats](/~https://github.com/kube-rs/kube-rs/issues [dependencies] kube = { version = "0.58.1", default-features = false, features = ["client", "rustls-tls"] } kube-runtime = { version = "0.58.1" } -k8s-openapi = { version = "0.12.0", default-features = false, features = ["v1_20"] } +k8s-openapi = { version = "0.13.0", default-features = false, features = ["v1_20"] } ``` This will pull in `rustls` and `hyper-rustls`. diff --git a/examples/Cargo.toml b/examples/Cargo.toml index aa37d8046..9e971dc4f 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -32,7 +32,7 @@ kube = { path = "../kube", version = "^0.58.0", default-features = false, featur kube-derive = { path = "../kube-derive", version = "^0.58.0", default-features = false } # only needed to opt out of schema kube-runtime = { path = "../kube-runtime", version = "^0.58.0"} kube-core = { path = "../kube-core", version = "^0.58.0", default-features = false } -k8s-openapi = { version = "0.12.0", features = ["v1_20"], default-features = false } +k8s-openapi = { version = "0.13.0", features = ["v1_20"], default-features = false } log = "0.4.11" serde = { version = "1.0.118", features = ["derive"] } serde_json = "1.0.61" @@ -44,7 +44,7 @@ snafu = { version = "0.6.10", features = ["futures"] } either = "1.6.1" schemars = "0.8.0" static_assertions = "1.1.0" -tar = "0.4.32" +tar = "0.4.35" tracing = "0.1" tracing-subscriber = "0.2" warp = { version = "0.3", features = ["tls"] } diff --git a/examples/configmapgen_controller.rs b/examples/configmapgen_controller.rs index acf7a0b6b..e911ebdce 100644 --- a/examples/configmapgen_controller.rs +++ b/examples/configmapgen_controller.rs @@ -65,13 +65,13 @@ async fn reconcile(generator: ConfigMapGenerator, ctx: Context) -> Result< let cm = ConfigMap { metadata: ObjectMeta { name: generator.metadata.name.clone(), - owner_references: vec![OwnerReference { + owner_references: Some(vec![OwnerReference { controller: Some(true), ..object_to_owner_reference::(generator.metadata.clone())? - }], + }]), ..ObjectMeta::default() }, - data: contents, + data: Some(contents), ..Default::default() }; let cm_api = Api::::namespaced( diff --git a/examples/crd_api.rs b/examples/crd_api.rs index 5b1bcc193..56b7f7309 100644 --- a/examples/crd_api.rs +++ b/examples/crd_api.rs @@ -52,7 +52,7 @@ async fn main() -> anyhow::Result<()> { info!( "Deleting {}: ({:?})", o.name(), - o.status.unwrap().conditions.last() + o.status.unwrap().conditions.unwrap().last() ); }) .map_right(|s| { @@ -213,7 +213,7 @@ async fn main() -> anyhow::Result<()> { info!( "Deleting {} CRD definition: {:?}", o.name(), - o.status.unwrap().conditions.last() + o.status.unwrap().conditions.unwrap().last() ); } Right(status) => { diff --git a/examples/crd_apply.rs b/examples/crd_apply.rs index ab70d350d..32a348195 100644 --- a/examples/crd_apply.rs +++ b/examples/crd_apply.rs @@ -92,10 +92,12 @@ async fn wait_for_crd_ready(crds: &Api) -> anyhow::Res if let WatchEvent::Modified(s) = status { info!("Modify event for {}", s.name()); if let Some(s) = s.status { - if let Some(pcond) = s.conditions.iter().find(|c| c.type_ == "NamesAccepted") { - if pcond.status == "True" { - info!("crd was accepted: {:?}", pcond); - return Ok(()); + if let Some(conds) = s.conditions { + if let Some(pcond) = conds.iter().find(|c| c.type_ == "NamesAccepted") { + if pcond.status == "True" { + info!("crd was accepted: {:?}", pcond); + return Ok(()); + } } } } diff --git a/examples/crd_derive_schema.rs b/examples/crd_derive_schema.rs index b08a8c5d9..22e5316f7 100644 --- a/examples/crd_derive_schema.rs +++ b/examples/crd_derive_schema.rs @@ -235,9 +235,9 @@ async fn create_crd(client: Client) -> Result { let accepted = crd .status .as_ref() - .map(|s| { - s.conditions - .iter() + .and_then(|s| s.conditions.as_ref()) + .map(|sc| { + sc.iter() .any(|c| c.type_ == "NamesAccepted" && c.status == "True") }) .unwrap_or(false); diff --git a/examples/node_watcher.rs b/examples/node_watcher.rs index 6bb22a8cc..f3a5fabad 100644 --- a/examples/node_watcher.rs +++ b/examples/node_watcher.rs @@ -33,6 +33,7 @@ async fn check_for_node_failures(events: &Api, o: Node) -> anyhow::Result .status .unwrap() .conditions + .unwrap() .into_iter() .filter(|c| { // In a failed state either some of the extra conditions are not False diff --git a/examples/pod_watcher.rs b/examples/pod_watcher.rs index 092355c96..2b86e85b8 100644 --- a/examples/pod_watcher.rs +++ b/examples/pod_watcher.rs @@ -29,18 +29,19 @@ async fn main() -> Result<()> { fn pod_unready(p: &Pod) -> Option { let status = p.status.as_ref().unwrap(); - let failed = status - .conditions - .iter() - .filter(|c| c.type_ == "Ready" && c.status == "False") - .map(|c| c.message.clone().unwrap_or_default()) - .collect::>() - .join(","); - if !failed.is_empty() { - if p.metadata.labels.contains_key("job-name") { - return None; // ignore job based pods, they are meant to exit 0 + if let Some(conds) = &status.conditions { + let failed = conds + .into_iter() + .filter(|c| c.type_ == "Ready" && c.status == "False") + .map(|c| c.message.clone().unwrap_or_default()) + .collect::>() + .join(","); + if !failed.is_empty() { + if p.metadata.labels.as_ref().unwrap().contains_key("job-name") { + return None; // ignore job based pods, they are meant to exit 0 + } + return Some(format!("Unready pod {}: {}", p.name(), failed)); } - return Some(format!("Unready pod {}: {}", p.name(), failed)); } None } diff --git a/examples/secret_reflector.rs b/examples/secret_reflector.rs index 95c6291cb..a5abda1de 100644 --- a/examples/secret_reflector.rs +++ b/examples/secret_reflector.rs @@ -20,12 +20,13 @@ enum Decoded { fn decode(secret: &Secret) -> BTreeMap { let mut res = BTreeMap::new(); // Ignoring binary data for now - let data = secret.data.clone(); - for (k, v) in data { - if let Ok(b) = std::str::from_utf8(&v.0) { - res.insert(k, Decoded::Utf8(b.to_string())); - } else { - res.insert(k, Decoded::Bytes(v.0)); + if let Some(data) = secret.data.clone() { + for (k, v) in data { + if let Ok(b) = std::str::from_utf8(&v.0) { + res.insert(k, Decoded::Utf8(b.to_string())); + } else { + res.insert(k, Decoded::Bytes(v.0)); + } } } res diff --git a/kube-core/Cargo.toml b/kube-core/Cargo.toml index 57289164c..aeb746bff 100644 --- a/kube-core/Cargo.toml +++ b/kube-core/Cargo.toml @@ -23,14 +23,15 @@ thiserror = "1.0.23" form_urlencoded = "1.0.1" http = "0.2.2" json-patch = { version = "0.2.6", optional = true } +once_cell = "1.8.0" [dependencies.k8s-openapi] -version = "0.12.0" +version = "0.13.0" default-features = false features = [] [dev-dependencies.k8s-openapi] -version = "0.12.0" +version = "0.13.0" default-features = false features = ["v1_20"] diff --git a/kube-core/src/params.rs b/kube-core/src/params.rs index 0a2f89d94..27379d869 100644 --- a/kube-core/src/params.rs +++ b/kube-core/src/params.rs @@ -193,7 +193,7 @@ impl PostParams { /// use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta; /// let r = Role { /// metadata: ObjectMeta { name: Some("user".into()), ..ObjectMeta::default() }, -/// rules: vec![] +/// rules: Some(vec![]) /// }; /// let patch = Patch::Apply(&r); /// ``` diff --git a/kube-core/src/resource.rs b/kube-core/src/resource.rs index 48da547a0..d92855a9e 100644 --- a/kube-core/src/resource.rs +++ b/kube-core/src/resource.rs @@ -143,6 +143,11 @@ pub trait ResourceExt: Resource { fn finalizers_mut(&mut self) -> &mut Vec; } +// TODO: replace with ordinary static when BTreeMap::new() is no longer +// const-unstable. +use once_cell::sync::Lazy; +static EMPTY_MAP: Lazy> = Lazy::new(BTreeMap::new); + impl ResourceExt for K { fn name(&self) -> String { self.meta().name.clone().expect(".metadata.name missing") @@ -161,34 +166,34 @@ impl ResourceExt for K { } fn labels(&self) -> &BTreeMap { - &self.meta().labels + &self.meta().labels.as_ref().unwrap_or_else(|| &*EMPTY_MAP) } fn labels_mut(&mut self) -> &mut BTreeMap { - &mut self.meta_mut().labels + self.meta_mut().labels.get_or_insert_with(BTreeMap::new) } fn annotations(&self) -> &BTreeMap { - &self.meta().annotations + &self.meta().annotations.as_ref().unwrap_or_else(|| &*EMPTY_MAP) } fn annotations_mut(&mut self) -> &mut BTreeMap { - &mut self.meta_mut().annotations + self.meta_mut().annotations.get_or_insert_with(BTreeMap::new) } fn owner_references(&self) -> &[OwnerReference] { - self.meta().owner_references.as_slice() + self.meta().owner_references.as_deref().unwrap_or_default() } fn owner_references_mut(&mut self) -> &mut Vec { - &mut self.meta_mut().owner_references + self.meta_mut().owner_references.get_or_insert_with(Vec::new) } fn finalizers(&self) -> &[String] { - self.meta().finalizers.as_slice() + self.meta().finalizers.as_deref().unwrap_or_default() } fn finalizers_mut(&mut self) -> &mut Vec { - &mut self.meta_mut().finalizers + self.meta_mut().finalizers.get_or_insert_with(Vec::new) } } diff --git a/kube-derive/Cargo.toml b/kube-derive/Cargo.toml index d2936cccd..475c89472 100644 --- a/kube-derive/Cargo.toml +++ b/kube-derive/Cargo.toml @@ -29,7 +29,7 @@ schema = [] serde = { version = "1.0.118", features = ["derive"] } serde_yaml = "0.8.17" kube = { path = "../kube", default-features = false } -k8s-openapi = { version = "0.12.0", default-features = false, features = ["v1_20"] } +k8s-openapi = { version = "0.13.0", default-features = false, features = ["v1_20"] } schemars = { version = "0.8.0", features = ["chrono"] } chrono = "0.4.19" trybuild = "1.0" diff --git a/kube-runtime/Cargo.toml b/kube-runtime/Cargo.toml index 556358895..d1351c8ff 100644 --- a/kube-runtime/Cargo.toml +++ b/kube-runtime/Cargo.toml @@ -28,7 +28,7 @@ json-patch = "0.2.6" serde_json = "1.0.64" [dependencies.k8s-openapi] -version = "0.12.0" +version = "0.13.0" default-features = false [dev-dependencies] @@ -40,6 +40,6 @@ rand = "0.8.0" schemars = "0.8.0" [dev-dependencies.k8s-openapi] -version = "0.12.0" +version = "0.13.0" default-features = false features = ["v1_20"] diff --git a/kube-runtime/src/controller/mod.rs b/kube-runtime/src/controller/mod.rs index 859e184dd..f8e6d897c 100644 --- a/kube-runtime/src/controller/mod.rs +++ b/kube-runtime/src/controller/mod.rs @@ -120,6 +120,7 @@ where let child_ref = ObjectRef::from_obj_with(&obj, child_type.clone()).erase(); meta.owner_references .into_iter() + .flatten() .filter_map(move |owner| ObjectRef::from_owner_ref(ns.as_deref(), &owner, owner_type.clone())) .map(move |owner_ref| ReconcileRequest { obj_ref: owner_ref, diff --git a/kube-runtime/src/finalizer.rs b/kube-runtime/src/finalizer.rs index 2fbd7b928..66923ce21 100644 --- a/kube-runtime/src/finalizer.rs +++ b/kube-runtime/src/finalizer.rs @@ -3,7 +3,7 @@ use futures::{TryFuture, TryFutureExt}; use json_patch::{AddOperation, PatchOperation, RemoveOperation, TestOperation}; use kube::{ api::{Patch, PatchParams}, - Api, Resource, + Api, Resource, ResourceExt, }; use serde::{de::DeserializeOwned, Serialize}; use snafu::{OptionExt, ResultExt, Snafu}; @@ -35,8 +35,7 @@ impl FinalizerState { fn for_object(obj: &K, finalizer_name: &str) -> Self { Self { finalizer_index: obj - .meta() - .finalizers + .finalizers() .iter() .enumerate() .find(|(_, fin)| *fin == finalizer_name) @@ -150,7 +149,7 @@ where is_deleting: false, } => { // Finalizer must be added before it's safe to run an `Apply` reconciliation - let patch = json_patch::Patch(if obj.meta().finalizers.is_empty() { + let patch = json_patch::Patch(if obj.finalizers().is_empty() { vec![ PatchOperation::Test(TestOperation { path: "/metadata/finalizers".to_string(), diff --git a/kube-runtime/src/reflector/mod.rs b/kube-runtime/src/reflector/mod.rs index 6051cbaa7..12bf7497c 100644 --- a/kube-runtime/src/reflector/mod.rs +++ b/kube-runtime/src/reflector/mod.rs @@ -70,11 +70,11 @@ mod tests { ..ConfigMap::default() }; let updated_cm = ConfigMap { - data: { + data: Some({ let mut data = BTreeMap::new(); data.insert("data".to_string(), "present!".to_string()); data - }, + }), ..cm.clone() }; reflector( diff --git a/kube/Cargo.toml b/kube/Cargo.toml index 95954b5f1..285725631 100644 --- a/kube/Cargo.toml +++ b/kube/Cargo.toml @@ -73,7 +73,7 @@ rand = { version = "0.8.3", optional = true } tracing = { version = "0.1.25", features = ["log"], optional = true } [dependencies.k8s-openapi] -version = "0.12.0" +version = "0.13.0" default-features = false features = [] @@ -85,6 +85,6 @@ tokio-test = "0.4.0" tower-test = "0.4.0" [dev-dependencies.k8s-openapi] -version = "0.12.0" +version = "0.13.0" default-features = false features = ["v1_20"] diff --git a/kube/src/client/mod.rs b/kube/src/client/mod.rs index 2f3048c31..798897b59 100644 --- a/kube/src/client/mod.rs +++ b/kube/src/client/mod.rs @@ -606,7 +606,7 @@ mod tests { let pods: Api = Api::default_namespaced(Client::new(mock_service, "default")); let pod = pods.get("test").await.unwrap(); - assert_eq!(pod.metadata.annotations.get("kube-rs").unwrap(), "test"); + assert_eq!(pod.metadata.annotations.unwrap().get("kube-rs").unwrap(), "test"); spawned.await.unwrap(); } } diff --git a/tests/Cargo.toml b/tests/Cargo.toml index edd21f057..e9e93bd58 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -18,7 +18,7 @@ anyhow = "1.0.37" env_logger = "0.8.2" futures = "0.3.8" kube = { path = "../kube", version = "^0.58.1", default-features = false, features = ["client", "rustls-tls"] } -k8s-openapi = { version = "0.12.0", features = ["v1_20"], default-features = false } +k8s-openapi = { version = "0.13.0", features = ["v1_20"], default-features = false } log = "0.4.11" serde_json = "1.0.61" tokio = { version = "1.0.1", features = ["full"] }