diff --git a/Cargo.lock b/Cargo.lock index df5a324..f0dd1f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "actix-codec" @@ -498,9 +498,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -541,7 +541,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "thiserror 2.0.4", + "thiserror 2.0.7", "tokio", "tower-test", "tracing", @@ -1031,6 +1031,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "hostname" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +dependencies = [ + "cfg-if", + "libc", + "windows", +] + [[package]] name = "http" version = "0.2.12" @@ -1090,9 +1101,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -1454,9 +1465,9 @@ dependencies = [ [[package]] name = "k8s-openapi" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8847402328d8301354c94d605481f25a6bdc1ed65471fd96af8eca71141b13" +checksum = "2c75b990324f09bef15e791606b7b7a296d02fc88a344f6eba9390970a870ad5" dependencies = [ "base64 0.22.1", "chrono", @@ -1467,9 +1478,9 @@ dependencies = [ [[package]] name = "kube" -version = "0.97.0" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5fd2596428f922f784ca43907c449f104d69055c811135684474143736c67ae" +checksum = "32053dc495efad4d188c7b33cc7c02ef4a6e43038115348348876efd39a53cba" dependencies = [ "k8s-openapi", "kube-client", @@ -1480,9 +1491,9 @@ dependencies = [ [[package]] name = "kube-client" -version = "0.97.0" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d539b6493d162ae5ab691762be972b6a1c20f6d8ddafaae305c0e2111b589d99" +checksum = "9d34ad38cdfbd1fa87195d42569f57bb1dda6ba5f260ee32fef9570b7937a0c9" dependencies = [ "base64 0.22.1", "bytes", @@ -1508,7 +1519,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "thiserror 2.0.4", + "thiserror 2.0.7", "tokio", "tokio-util", "tower 0.5.1", @@ -1518,9 +1529,9 @@ dependencies = [ [[package]] name = "kube-core" -version = "0.97.0" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98a87cc0046cf6b62cbb63ae1fbc366ee8ba29269f575289679473754ff5d7a7" +checksum = "97aa830b288a178a90e784d1b0f1539f2d200d2188c7b4a3146d9dc983d596f3" dependencies = [ "chrono", "form_urlencoded", @@ -1531,14 +1542,14 @@ dependencies = [ "serde", "serde-value", "serde_json", - "thiserror 2.0.4", + "thiserror 2.0.7", ] [[package]] name = "kube-derive" -version = "0.97.0" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65576922713e6154a89b5a8d2747adca15725b90fa64fc2b828774bf96d6acd8" +checksum = "37745d8a4076b77e0b1952e94e358726866c8e14ec94baaca677d47dcdb98658" dependencies = [ "darling", "proc-macro2", @@ -1549,9 +1560,9 @@ dependencies = [ [[package]] name = "kube-runtime" -version = "0.97.0" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f348cc3e6c9be0ae17f300594bde541b667d10ab8934a119edd61ab5123c43e" +checksum = "7a41af186a0fe80c71a13a13994abdc3ebff80859ca6a4b8a6079948328c135b" dependencies = [ "ahash", "async-broadcast", @@ -1561,6 +1572,7 @@ dependencies = [ "educe", "futures", "hashbrown 0.15.2", + "hostname", "json-patch", "jsonptr", "k8s-openapi", @@ -1569,7 +1581,7 @@ dependencies = [ "pin-project", "serde", "serde_json", - "thiserror 2.0.4", + "thiserror 2.0.7", "tokio", "tokio-util", "tracing", @@ -2309,9 +2321,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] @@ -2328,9 +2340,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -2525,11 +2537,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.4" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" dependencies = [ - "thiserror-impl 2.0.4", + "thiserror-impl 2.0.7", ] [[package]] @@ -2545,9 +2557,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.4" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" dependencies = [ "proc-macro2", "quote", @@ -3059,6 +3071,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + [[package]] name = "windows-core" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 9ec6e5e..42c48ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ telemetry = ["opentelemetry-otlp"] actix-web = "4.4.0" futures = "0.3.31" tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread"] } -k8s-openapi = { version = "0.23.0", features = ["latest"] } +k8s-openapi = { version = "0.24.0", features = ["latest"] } schemars = { version = "0.8.12", features = ["chrono"] } serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" @@ -53,7 +53,7 @@ tower-test = "0.4.0" [dependencies.kube] features = ["runtime", "client", "derive" ] -version = "0.97.0" +version = "0.98.0" # testing new releases - ignore #git = "https://github.com/kube-rs/kube.git" diff --git a/src/controller.rs b/src/controller.rs index 165b9f7..a22b577 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -24,6 +24,8 @@ pub static DOCUMENT_FINALIZER: &str = "documents.kube.rs"; /// Generate the Kubernetes wrapper struct `Document` from our Spec and Status struct /// /// This provides a hook for generating the CRD yaml (in crdgen.rs) +/// NB: CustomResource generates a pub struct Document here +/// To query for documents.kube.rs with kube, use Api. #[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)] #[cfg_attr(test, derive(Default))] #[kube(kind = "Document", group = "kube.rs", version = "v1", namespaced)] @@ -50,6 +52,8 @@ impl Document { pub struct Context { /// Kubernetes client pub client: Client, + /// Event recorder + pub recorder: Recorder, /// Diagnostics read by the web server pub diagnostics: Arc>, /// Prometheus metrics @@ -88,7 +92,7 @@ impl Document { // Reconcile (for non-finalizer related changes) async fn reconcile(&self, ctx: Arc) -> Result { let client = ctx.client.clone(); - let recorder = ctx.diagnostics.read().await.recorder(client.clone(), self); + let oref = self.object_ref(&()); let ns = self.namespace().unwrap(); let name = self.name_any(); let docs: Api = Api::namespaced(client, &ns); @@ -96,14 +100,17 @@ impl Document { let should_hide = self.spec.hide; if !self.was_hidden() && should_hide { // send an event once per hide - recorder - .publish(Event { - type_: EventType::Normal, - reason: "HideRequested".into(), - note: Some(format!("Hiding `{name}`")), - action: "Hiding".into(), - secondary: None, - }) + ctx.recorder + .publish( + &Event { + type_: EventType::Normal, + reason: "HideRequested".into(), + note: Some(format!("Hiding `{name}`")), + action: "Hiding".into(), + secondary: None, + }, + &oref, + ) .await .map_err(Error::KubeError)?; } @@ -130,16 +137,19 @@ impl Document { // Finalizer cleanup (the object was deleted, ensure nothing is orphaned) async fn cleanup(&self, ctx: Arc) -> Result { - let recorder = ctx.diagnostics.read().await.recorder(ctx.client.clone(), self); + let oref = self.object_ref(&()); // Document doesn't have any real cleanup, so we just publish an event - recorder - .publish(Event { - type_: EventType::Normal, - reason: "DeleteRequested".into(), - note: Some(format!("Delete `{}`", self.name_any())), - action: "Deleting".into(), - secondary: None, - }) + ctx.recorder + .publish( + &Event { + type_: EventType::Normal, + reason: "DeleteRequested".into(), + note: Some(format!("Delete `{}`", self.name_any())), + action: "Deleting".into(), + secondary: None, + }, + &oref, + ) .await .map_err(Error::KubeError)?; Ok(Action::await_change()) @@ -163,8 +173,8 @@ impl Default for Diagnostics { } } impl Diagnostics { - fn recorder(&self, client: Client, doc: &Document) -> Recorder { - Recorder::new(client, self.reporter.clone(), doc.object_ref(&())) + fn recorder(&self, client: Client) -> Recorder { + Recorder::new(client, self.reporter.clone()) } } @@ -193,9 +203,10 @@ impl State { } // Create a Controller Context that can update State - pub fn to_context(&self, client: Client) -> Arc { + pub async fn to_context(&self, client: Client) -> Arc { Arc::new(Context { - client, + client: client.clone(), + recorder: self.diagnostics.read().await.recorder(client), metrics: self.metrics.clone(), diagnostics: self.diagnostics.clone(), }) @@ -213,7 +224,7 @@ pub async fn run(state: State) { } Controller::new(docs, Config::default().any_semantic()) .shutdown_on_signal() - .run(reconcile, error_policy, state.to_context(client)) + .run(reconcile, error_policy, state.to_context(client).await) .filter_map(|x| async move { std::result::Result::ok(x) }) .for_each(|_| futures::future::ready(())) .await; @@ -293,7 +304,7 @@ mod test { #[ignore = "uses k8s current-context"] async fn integration_reconcile_should_set_status_and_send_event() { let client = kube::Client::try_default().await.unwrap(); - let ctx = super::State::default().to_context(client.clone()); + let ctx = super::State::default().to_context(client.clone()).await; // create a test doc let doc = Document::test().finalized().needs_hide(); diff --git a/src/fixtures.rs b/src/fixtures.rs index 9e99085..5147152 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -2,7 +2,7 @@ use crate::{Context, Document, DocumentSpec, DocumentStatus, Result, DOCUMENT_FINALIZER}; use assert_json_diff::assert_json_include; use http::{Request, Response}; -use kube::{client::Body, Client, Resource, ResourceExt}; +use kube::{client::Body, runtime::events::Recorder, Client, Resource, ResourceExt}; use std::sync::Arc; impl Document { @@ -210,10 +210,12 @@ impl Context { pub fn test() -> (Arc, ApiServerVerifier) { let (mock_service, handle) = tower_test::mock::pair::, Response>(); let mock_client = Client::new(mock_service, "default"); + let mock_recorder = Recorder::new(mock_client.clone(), "doc-ctrl-test".into()); let ctx = Self { client: mock_client, metrics: Arc::default(), diagnostics: Arc::default(), + recorder: mock_recorder, }; (Arc::new(ctx), ApiServerVerifier(handle)) } diff --git a/yaml/crd.yaml b/yaml/crd.yaml index 3ad309c..4437c28 100644 --- a/yaml/crd.yaml +++ b/yaml/crd.yaml @@ -23,7 +23,7 @@ spec: description: |- Generate the Kubernetes wrapper struct `Document` from our Spec and Status struct - This provides a hook for generating the CRD yaml (in crdgen.rs) + This provides a hook for generating the CRD yaml (in crdgen.rs) NB: CustomResource generates a pub struct Document here To query for documents.kube.rs with kube, use Api. properties: content: type: string