From 56f2b2fb01f2d418a39e1796abfefcd85e8a9ca1 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Fri, 14 Nov 2025 13:43:52 +0100 Subject: [PATCH 1/7] fix: Prevent Pod 0 restart by utilizing mutating webhook --- Cargo.lock | 470 ++++- Cargo.nix | 1798 ++++++++++++++++- Cargo.toml | 7 +- _TEST.yaml | 62 + crate-hashes.json | 16 +- .../commons-operator/templates/roles.yaml | 7 + rust/operator-binary/src/main.rs | 32 +- .../src/restart_controller/statefulset.rs | 3 +- rust/operator-binary/src/webhooks.rs | 116 ++ 9 files changed, 2398 insertions(+), 113 deletions(-) create mode 100644 _TEST.yaml create mode 100644 rust/operator-binary/src/webhooks.rs diff --git a/Cargo.lock b/Cargo.lock index 36834a2..52a364d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,6 +101,12 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + [[package]] name = "async-broadcast" version = "0.7.2" @@ -221,12 +227,24 @@ dependencies = [ "tokio", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + [[package]] name = "bit-set" version = "0.8.0" @@ -364,6 +382,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "const_format" version = "0.2.35" @@ -442,6 +466,18 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -498,6 +534,30 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "der_derive", + "flagset", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "deranged" version = "0.5.5" @@ -534,7 +594,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -574,6 +636,20 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "educe" version = "0.6.0" @@ -592,6 +668,26 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.35" @@ -674,12 +770,28 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "find-msvc-tools" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" +[[package]] +name = "flagset" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" + [[package]] name = "flate2" version = "1.1.5" @@ -815,6 +927,7 @@ checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -865,6 +978,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "h2" version = "0.4.12" @@ -907,6 +1031,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.12" @@ -1326,7 +1459,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.3" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#184423db7409f853bd69db7eeecd1affbf97ef40" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" dependencies = [ "darling", "regex", @@ -1447,6 +1580,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libc" @@ -1466,6 +1602,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "libz-sys" version = "1.1.22" @@ -1556,12 +1698,48 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1569,6 +1747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1677,7 +1856,7 @@ dependencies = [ "futures-util", "opentelemetry", "percent-encoding", - "rand", + "rand 0.9.2", "thiserror 2.0.17", "tokio", "tokio-stream", @@ -1692,6 +1871,18 @@ dependencies = [ "num-traits", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "parking" version = "2.2.1" @@ -1731,6 +1922,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -1812,6 +2012,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -1842,6 +2063,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro2" version = "1.0.103" @@ -1905,14 +2135,34 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] @@ -1922,7 +2172,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", ] [[package]] @@ -2026,6 +2285,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.14" @@ -2040,6 +2309,27 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rsa" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "sha2", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rustls" version = "0.23.34" @@ -2140,6 +2430,20 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secrecy" version = "0.10.3" @@ -2278,6 +2582,17 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.9" @@ -2313,6 +2628,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -2383,12 +2708,52 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "stackable-certs" +version = "0.4.0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +dependencies = [ + "const-oid", + "ecdsa", + "k8s-openapi", + "kube", + "p256", + "rand 0.9.2", + "rand_core 0.6.4", + "rsa", + "sha2", + "signature", + "snafu 0.8.9", + "stackable-shared", + "tokio", + "tokio-rustls", + "tracing", + "x509-cert", + "zeroize", +] + [[package]] name = "stackable-commons-operator" version = "0.0.0-dev" @@ -2409,8 +2774,8 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.100.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#184423db7409f853bd69db7eeecd1affbf97ef40" +version = "0.100.3" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" dependencies = [ "chrono", "clap", @@ -2437,6 +2802,7 @@ dependencies = [ "stackable-shared", "stackable-telemetry", "stackable-versioned", + "stackable-webhook", "strum", "tokio", "tracing", @@ -2448,7 +2814,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#184423db7409f853bd69db7eeecd1affbf97ef40" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" dependencies = [ "darling", "proc-macro2", @@ -2459,7 +2825,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.0.3" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#184423db7409f853bd69db7eeecd1affbf97ef40" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" dependencies = [ "chrono", "k8s-openapi", @@ -2476,7 +2842,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#184423db7409f853bd69db7eeecd1affbf97ef40" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" dependencies = [ "axum", "clap", @@ -2500,7 +2866,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.8.3" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#184423db7409f853bd69db7eeecd1affbf97ef40" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" dependencies = [ "schemars", "serde", @@ -2513,7 +2879,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.8.3" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#184423db7409f853bd69db7eeecd1affbf97ef40" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" dependencies = [ "convert_case", "darling", @@ -2527,6 +2893,37 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "stackable-webhook" +version = "0.7.1" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +dependencies = [ + "arc-swap", + "async-trait", + "axum", + "futures-util", + "hyper", + "hyper-util", + "k8s-openapi", + "kube", + "opentelemetry", + "opentelemetry-semantic-conventions", + "rand 0.9.2", + "serde", + "serde_json", + "snafu 0.8.9", + "stackable-certs", + "stackable-shared", + "stackable-telemetry", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tracing", + "tracing-opentelemetry", + "x509-cert", +] + [[package]] name = "strsim" version = "0.11.1" @@ -2692,6 +3089,27 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tls_codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "tokio" version = "1.48.0" @@ -3390,6 +3808,20 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid", + "der", + "sha1", + "signature", + "spki", + "tls_codec", +] + [[package]] name = "xml" version = "1.0.1" @@ -3466,6 +3898,20 @@ name = "zeroize" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] [[package]] name = "zerotrie" diff --git a/Cargo.nix b/Cargo.nix index f8bdb0a..4f56375 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -339,6 +339,19 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "arc-swap" = rec { + crateName = "arc-swap"; + version = "1.7.1"; + edition = "2018"; + sha256 = "0mrl9a9r9p9bln74q6aszvf22q1ijiw089jkrmabfqkbj31zixv9"; + libName = "arc_swap"; + authors = [ + "Michal 'vorner' Vaner " + ]; + features = { + "serde" = [ "dep:serde" ]; + }; + }; "async-broadcast" = rec { crateName = "async-broadcast"; version = "0.7.2"; @@ -757,6 +770,19 @@ rec { }; resolvedDefaultFeatures = [ "default" "gloo-timers" "gloo-timers-sleep" "std" "std-blocking-sleep" "tokio" "tokio-sleep" ]; }; + "base16ct" = rec { + crateName = "base16ct"; + version = "0.2.0"; + edition = "2021"; + sha256 = "1kylrjhdzk7qpknrvlphw8ywdnvvg39dizw9622w3wk5xba04zsc"; + authors = [ + "RustCrypto Developers" + ]; + features = { + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; "base64" = rec { crateName = "base64"; version = "0.22.1"; @@ -771,6 +797,19 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; + "base64ct" = rec { + crateName = "base64ct"; + version = "1.8.0"; + edition = "2024"; + sha256 = "1fj4vc6ghy3j1120r7dwn4xw90crfy46b448g5pm9w6an13qn92m"; + authors = [ + "RustCrypto Developers" + ]; + features = { + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; "bit-set" = rec { crateName = "bit-set"; version = "0.8.0"; @@ -1166,6 +1205,20 @@ rec { }; resolvedDefaultFeatures = [ "std" ]; }; + "const-oid" = rec { + crateName = "const-oid"; + version = "0.9.6"; + edition = "2021"; + sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; + authors = [ + "RustCrypto Developers" + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + }; + resolvedDefaultFeatures = [ "db" "std" ]; + }; "const_format" = rec { crateName = "const_format"; version = "0.2.35"; @@ -1380,6 +1433,58 @@ rec { }; resolvedDefaultFeatures = [ "std" ]; }; + "crypto-bigint" = rec { + crateName = "crypto-bigint"; + version = "0.5.5"; + edition = "2021"; + sha256 = "0xmbdff3g6ii5sbxjxc31xfkv9lrmyril4arh3dzckd4gjsjzj8d"; + libName = "crypto_bigint"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "generic-array"; + packageId = "generic-array"; + optional = true; + } + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + optional = true; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + features = [ "std" ]; + } + ]; + features = { + "alloc" = [ "serdect?/alloc" ]; + "default" = [ "rand" ]; + "der" = [ "dep:der" ]; + "generic-array" = [ "dep:generic-array" ]; + "rand" = [ "rand_core/std" ]; + "rand_core" = [ "dep:rand_core" ]; + "rlp" = [ "dep:rlp" ]; + "serde" = [ "dep:serdect" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "generic-array" "rand_core" "zeroize" ]; + }; "crypto-common" = rec { crateName = "crypto-common"; version = "0.1.6"; @@ -1404,6 +1509,7 @@ rec { "getrandom" = [ "rand_core/getrandom" ]; "rand_core" = [ "dep:rand_core" ]; }; + resolvedDefaultFeatures = [ "std" ]; }; "darling" = rec { crateName = "darling"; @@ -1525,6 +1631,83 @@ rec { } ]; + }; + "der" = rec { + crateName = "der"; + version = "0.7.10"; + edition = "2021"; + sha256 = "1jyxacyxdx6mxbkfw99jz59dzvcd9k17rq01a7xvn1dr6wl87hg7"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "const-oid"; + packageId = "const-oid"; + optional = true; + } + { + name = "der_derive"; + packageId = "der_derive"; + optional = true; + } + { + name = "flagset"; + packageId = "flagset"; + optional = true; + } + { + name = "pem-rfc7468"; + packageId = "pem-rfc7468"; + optional = true; + features = [ "alloc" ]; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "zeroize?/alloc" ]; + "arbitrary" = [ "dep:arbitrary" "const-oid?/arbitrary" "std" ]; + "bytes" = [ "dep:bytes" "alloc" ]; + "derive" = [ "dep:der_derive" ]; + "flagset" = [ "dep:flagset" ]; + "oid" = [ "dep:const-oid" ]; + "pem" = [ "dep:pem-rfc7468" "alloc" "zeroize" ]; + "std" = [ "alloc" ]; + "time" = [ "dep:time" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "derive" "flagset" "oid" "pem" "std" "zeroize" ]; + }; + "der_derive" = rec { + crateName = "der_derive"; + version = "0.7.3"; + edition = "2021"; + sha256 = "065d2wy7zd0dank99hh58l5x7lv50hxnr7j6f3sphlb7i4ihjd40"; + procMacro = true; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.108"; + features = [ "extra-traits" ]; + } + ]; + }; "deranged" = rec { crateName = "deranged"; @@ -1656,10 +1839,21 @@ rec { packageId = "block-buffer"; optional = true; } + { + name = "const-oid"; + packageId = "const-oid"; + optional = true; + } { name = "crypto-common"; packageId = "crypto-common"; } + { + name = "subtle"; + packageId = "subtle"; + optional = true; + usesDefaultFeatures = false; + } ]; features = { "blobby" = [ "dep:blobby" ]; @@ -1674,7 +1868,7 @@ rec { "std" = [ "alloc" "crypto-common/std" ]; "subtle" = [ "dep:subtle" ]; }; - resolvedDefaultFeatures = [ "block-buffer" "core-api" "default" ]; + resolvedDefaultFeatures = [ "alloc" "block-buffer" "const-oid" "core-api" "default" "mac" "oid" "std" "subtle" ]; }; "displaydoc" = rec { crateName = "displaydoc"; @@ -1763,6 +1957,79 @@ rec { ]; }; + "ecdsa" = rec { + crateName = "ecdsa"; + version = "0.16.9"; + edition = "2021"; + sha256 = "1jhb0bcbkaz4001sdmfyv8ajrv8a1cg7z7aa5myrd4jjbhmz69zf"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "der"; + packageId = "der"; + optional = true; + } + { + name = "digest"; + packageId = "digest"; + optional = true; + usesDefaultFeatures = false; + features = [ "oid" ]; + } + { + name = "elliptic-curve"; + packageId = "elliptic-curve"; + usesDefaultFeatures = false; + features = [ "digest" "sec1" ]; + } + { + name = "rfc6979"; + packageId = "rfc6979"; + optional = true; + } + { + name = "signature"; + packageId = "signature"; + usesDefaultFeatures = false; + features = [ "rand_core" ]; + } + { + name = "spki"; + packageId = "spki"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "elliptic-curve"; + packageId = "elliptic-curve"; + usesDefaultFeatures = false; + features = [ "dev" ]; + } + ]; + features = { + "alloc" = [ "elliptic-curve/alloc" "signature/alloc" "spki/alloc" ]; + "arithmetic" = [ "elliptic-curve/arithmetic" ]; + "default" = [ "digest" ]; + "der" = [ "dep:der" ]; + "dev" = [ "arithmetic" "digest" "elliptic-curve/dev" "hazmat" ]; + "digest" = [ "dep:digest" "signature/digest" ]; + "pem" = [ "elliptic-curve/pem" "pkcs8" ]; + "pkcs8" = [ "digest" "elliptic-curve/pkcs8" "der" ]; + "rfc6979" = [ "dep:rfc6979" ]; + "serde" = [ "elliptic-curve/serde" "serdect" ]; + "serdect" = [ "dep:serdect" ]; + "sha2" = [ "dep:sha2" ]; + "signing" = [ "arithmetic" "digest" "hazmat" "rfc6979" ]; + "spki" = [ "dep:spki" ]; + "std" = [ "alloc" "elliptic-curve/std" "signature/std" ]; + "verifying" = [ "arithmetic" "digest" "hazmat" ]; + }; + resolvedDefaultFeatures = [ "alloc" "arithmetic" "default" "der" "digest" "hazmat" "pem" "pkcs8" "rfc6979" "signing" "spki" "std" "verifying" ]; + }; "educe" = rec { crateName = "educe"; version = "0.6.0"; @@ -1820,6 +2087,104 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" "use_std" ]; }; + "elliptic-curve" = rec { + crateName = "elliptic-curve"; + version = "0.13.8"; + edition = "2021"; + sha256 = "0ixx4brgnzi61z29r3g1606nh2za88hzyz8c5r3p6ydzhqq09rmm"; + libName = "elliptic_curve"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "base16ct"; + packageId = "base16ct"; + } + { + name = "crypto-bigint"; + packageId = "crypto-bigint"; + usesDefaultFeatures = false; + features = [ "rand_core" "generic-array" "zeroize" ]; + } + { + name = "digest"; + packageId = "digest"; + optional = true; + } + { + name = "ff"; + packageId = "ff"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "generic-array"; + packageId = "generic-array"; + usesDefaultFeatures = false; + features = [ "zeroize" ]; + } + { + name = "group"; + packageId = "group"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "pem-rfc7468"; + packageId = "pem-rfc7468"; + optional = true; + features = [ "alloc" ]; + } + { + name = "pkcs8"; + packageId = "pkcs8"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + usesDefaultFeatures = false; + } + { + name = "sec1"; + packageId = "sec1"; + optional = true; + features = [ "subtle" "zeroize" ]; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "base16ct/alloc" "ff?/alloc" "group?/alloc" "pkcs8?/alloc" "sec1?/alloc" "zeroize/alloc" ]; + "arithmetic" = [ "group" ]; + "bits" = [ "arithmetic" "ff/bits" "dep:tap" ]; + "default" = [ "arithmetic" ]; + "dev" = [ "arithmetic" "dep:hex-literal" "pem" "pkcs8" ]; + "digest" = [ "dep:digest" ]; + "ecdh" = [ "arithmetic" "digest" "dep:hkdf" ]; + "ff" = [ "dep:ff" ]; + "group" = [ "dep:group" "ff" ]; + "hash2curve" = [ "arithmetic" "digest" ]; + "jwk" = [ "dep:base64ct" "dep:serde_json" "alloc" "serde" "zeroize/alloc" ]; + "pem" = [ "dep:pem-rfc7468" "alloc" "arithmetic" "pkcs8" "sec1/pem" ]; + "pkcs8" = [ "dep:pkcs8" "sec1" ]; + "sec1" = [ "dep:sec1" ]; + "serde" = [ "dep:serdect" "alloc" "pkcs8" "sec1/serde" ]; + "std" = [ "alloc" "rand_core/std" "pkcs8?/std" "sec1?/std" ]; + "voprf" = [ "digest" ]; + }; + resolvedDefaultFeatures = [ "alloc" "arithmetic" "digest" "ff" "group" "hazmat" "pem" "pkcs8" "sec1" "std" ]; + }; "encoding_rs" = rec { crateName = "encoding_rs"; version = "0.8.35"; @@ -2031,6 +2396,40 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "std" ]; }; + "ff" = rec { + crateName = "ff"; + version = "0.13.1"; + edition = "2021"; + sha256 = "14v3bc6q24gbcjnxjfbq2dddgf4as2z2gd4mj35gjlrncpxhpdf0"; + authors = [ + "Sean Bowe " + "Jack Grigg " + ]; + dependencies = [ + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + usesDefaultFeatures = false; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + features = [ "i128" ]; + } + ]; + features = { + "bits" = [ "bitvec" ]; + "bitvec" = [ "dep:bitvec" ]; + "byteorder" = [ "dep:byteorder" ]; + "default" = [ "bits" "std" ]; + "derive" = [ "byteorder" "ff_derive" ]; + "derive_bits" = [ "bits" "ff_derive/bits" ]; + "ff_derive" = [ "dep:ff_derive" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; "find-msvc-tools" = rec { crateName = "find-msvc-tools"; version = "0.1.4"; @@ -2039,6 +2438,18 @@ rec { libName = "find_msvc_tools"; }; + "flagset" = rec { + crateName = "flagset"; + version = "0.4.7"; + edition = "2021"; + sha256 = "1zplx30g76kl5la3ayl9ns5p3diqd9zphbcggqcm4nm7411q5b5p"; + authors = [ + "Nathaniel McCallum " + ]; + features = { + "serde" = [ "dep:serde" ]; + }; + }; "flate2" = rec { crateName = "flate2"; version = "1.1.5"; @@ -2447,6 +2858,12 @@ rec { name = "typenum"; packageId = "typenum"; } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } ]; buildDependencies = [ { @@ -2458,7 +2875,7 @@ rec { "serde" = [ "dep:serde" ]; "zeroize" = [ "dep:zeroize" ]; }; - resolvedDefaultFeatures = [ "more_lengths" ]; + resolvedDefaultFeatures = [ "more_lengths" "zeroize" ]; }; "getrandom 0.2.16" = rec { crateName = "getrandom"; @@ -2494,6 +2911,7 @@ rec { "rustc-dep-of-std" = [ "compiler_builtins" "core" "libc/rustc-dep-of-std" "wasi/rustc-dep-of-std" ]; "wasm-bindgen" = [ "dep:wasm-bindgen" ]; }; + resolvedDefaultFeatures = [ "std" ]; }; "getrandom 0.3.4" = rec { crateName = "getrandom"; @@ -2652,6 +3070,42 @@ rec { }; resolvedDefaultFeatures = [ "default" "futures" "futures-channel" "futures-core" ]; }; + "group" = rec { + crateName = "group"; + version = "0.13.0"; + edition = "2021"; + sha256 = "0qqs2p5vqnv3zvq9mfjkmw3qlvgqb0c3cm6p33srkh7pc9sfzygh"; + authors = [ + "Sean Bowe " + "Jack Grigg " + ]; + dependencies = [ + { + name = "ff"; + packageId = "ff"; + usesDefaultFeatures = false; + } + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + usesDefaultFeatures = false; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "alloc" ]; + "memuse" = [ "dep:memuse" ]; + "rand" = [ "dep:rand" ]; + "rand_xorshift" = [ "dep:rand_xorshift" ]; + "tests" = [ "alloc" "rand" "rand_xorshift" ]; + "wnaf-memuse" = [ "alloc" "memuse" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; "h2" = rec { crateName = "h2"; version = "0.4.12"; @@ -2795,6 +3249,33 @@ rec { sha256 = "1sjmpsdl8czyh9ywl3qcsfsq9a307dg4ni2vnlwgnzzqhc4y0113"; }; + "hmac" = rec { + crateName = "hmac"; + version = "0.12.1"; + edition = "2018"; + sha256 = "0pmbr069sfg76z7wsssfk5ddcqd9ncp79fyz6zcm6yn115yc6jbc"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "mac" ]; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "reset" ]; + }; "home" = rec { crateName = "home"; version = "0.5.12"; @@ -3061,7 +3542,7 @@ rec { "server" = [ "dep:httpdate" "dep:pin-project-lite" "dep:smallvec" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "client" "default" "http1" "http2" "server" ]; + resolvedDefaultFeatures = [ "client" "default" "full" "http1" "http2" "server" ]; }; "hyper-rustls" = rec { crateName = "hyper-rustls"; @@ -4162,9 +4643,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "184423db7409f853bd69db7eeecd1affbf97ef40"; - sha256 = "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; }; libName = "k8s_version"; authors = [ @@ -4262,7 +4743,7 @@ rec { "webpki-roots" = [ "kube-client/webpki-roots" "client" ]; "ws" = [ "kube-client/ws" "kube-core/ws" ]; }; - resolvedDefaultFeatures = [ "client" "config" "derive" "jsonpatch" "kube-client" "kube-derive" "kube-runtime" "ring" "runtime" "rustls-tls" ]; + resolvedDefaultFeatures = [ "admission" "client" "config" "derive" "jsonpatch" "kube-client" "kube-derive" "kube-runtime" "ring" "runtime" "rustls-tls" ]; }; "kube-client" = rec { crateName = "kube-client"; @@ -4577,7 +5058,7 @@ rec { "schema" = [ "schemars" ]; "schemars" = [ "dep:schemars" ]; }; - resolvedDefaultFeatures = [ "json-patch" "jsonpatch" "schema" "schemars" ]; + resolvedDefaultFeatures = [ "admission" "json-patch" "jsonpatch" "schema" "schemars" ]; }; "kube-derive" = rec { crateName = "kube-derive"; @@ -4755,10 +5236,20 @@ rec { authors = [ "Marvin Löbel " ]; + dependencies = [ + { + name = "spin"; + packageId = "spin"; + optional = true; + usesDefaultFeatures = false; + features = [ "once" ]; + } + ]; features = { "spin" = [ "dep:spin" ]; "spin_no_std" = [ "spin" ]; }; + resolvedDefaultFeatures = [ "spin" "spin_no_std" ]; }; "libc" = rec { crateName = "libc"; @@ -4820,6 +5311,20 @@ rec { "zlib-ng-compat" = [ "libz-sys/zlib-ng" "libssh2-sys?/zlib-ng-compat" ]; }; }; + "libm" = rec { + crateName = "libm"; + version = "0.2.15"; + edition = "2021"; + sha256 = "1plpzf0p829viazdj57yw5dhmlr8ywf3apayxc2f2bq5a6mvryzr"; + authors = [ + "Jorge Aparicio " + ]; + features = { + "default" = [ "arch" ]; + "unstable" = [ "unstable-intrinsics" "unstable-float" ]; + }; + resolvedDefaultFeatures = [ "arch" "default" ]; + }; "libz-sys" = rec { crateName = "libz-sys"; version = "1.1.22"; @@ -5092,6 +5597,81 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "num-bigint-dig" = rec { + crateName = "num-bigint-dig"; + version = "0.8.6"; + edition = "2021"; + sha256 = "1dxh3d8pzjc5k0kpy8gy2qhhhqs7zw8a7m564zl3ib8gcjkdsqg6"; + libName = "num_bigint_dig"; + authors = [ + "dignifiedquire " + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "lazy_static"; + packageId = "lazy_static"; + usesDefaultFeatures = false; + features = [ "spin_no_std" ]; + } + { + name = "libm"; + packageId = "libm"; + } + { + name = "num-integer"; + packageId = "num-integer"; + usesDefaultFeatures = false; + features = [ "i128" ]; + } + { + name = "num-iter"; + packageId = "num-iter"; + usesDefaultFeatures = false; + } + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + features = [ "i128" ]; + } + { + name = "rand"; + packageId = "rand 0.8.5"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "smallvec"; + packageId = "smallvec"; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "rand"; + packageId = "rand 0.8.5"; + features = [ "small_rng" ]; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "default" = [ "std" "u64_digit" ]; + "fuzz" = [ "arbitrary" "smallvec/arbitrary" ]; + "prime" = [ "rand/std_rng" ]; + "rand" = [ "dep:rand" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "num-integer/std" "num-traits/std" "smallvec/write" "rand/std" "serde/std" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "i128" "prime" "rand" "u64_digit" "zeroize" ]; + }; "num-conv" = rec { crateName = "num-conv"; version = "0.1.0"; @@ -5103,6 +5683,63 @@ rec { ]; }; + "num-integer" = rec { + crateName = "num-integer"; + version = "0.1.46"; + edition = "2018"; + sha256 = "13w5g54a9184cqlbsq80rnxw4jj4s0d8wv75jsq5r2lms8gncsbr"; + libName = "num_integer"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + features = [ "i128" ]; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "num-traits/std" ]; + }; + resolvedDefaultFeatures = [ "i128" ]; + }; + "num-iter" = rec { + crateName = "num-iter"; + version = "0.1.45"; + edition = "2018"; + sha256 = "1gzm7vc5g9qsjjl3bqk9rz1h6raxhygbrcpbfl04swlh0i506a8l"; + libName = "num_iter"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "num-integer"; + packageId = "num-integer"; + usesDefaultFeatures = false; + features = [ "i128" ]; + } + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + features = [ "i128" ]; + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "num-integer/std" "num-traits/std" ]; + }; + }; "num-traits" = rec { crateName = "num-traits"; version = "0.2.19"; @@ -5112,6 +5749,13 @@ rec { authors = [ "The Rust Project Developers" ]; + dependencies = [ + { + name = "libm"; + packageId = "libm"; + optional = true; + } + ]; buildDependencies = [ { name = "autocfg"; @@ -5122,7 +5766,7 @@ rec { "default" = [ "std" ]; "libm" = [ "dep:libm" ]; }; - resolvedDefaultFeatures = [ "std" ]; + resolvedDefaultFeatures = [ "i128" "libm" "std" ]; }; "once_cell" = rec { crateName = "once_cell"; @@ -5553,7 +6197,7 @@ rec { } { name = "rand"; - packageId = "rand"; + packageId = "rand 0.9.2"; optional = true; usesDefaultFeatures = false; features = [ "std" "std_rng" "small_rng" "os_rng" "thread_rng" ]; @@ -5635,6 +6279,79 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "p256" = rec { + crateName = "p256"; + version = "0.13.2"; + edition = "2021"; + sha256 = "0jyd3c3k239ybs59ixpnl7dqkmm072fr1js8kh7ldx58bzc3m1n9"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "ecdsa"; + packageId = "ecdsa"; + rename = "ecdsa-core"; + optional = true; + usesDefaultFeatures = false; + features = [ "der" ]; + } + { + name = "elliptic-curve"; + packageId = "elliptic-curve"; + usesDefaultFeatures = false; + features = [ "hazmat" "sec1" ]; + } + { + name = "primeorder"; + packageId = "primeorder"; + optional = true; + } + { + name = "sha2"; + packageId = "sha2"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "ecdsa"; + packageId = "ecdsa"; + rename = "ecdsa-core"; + usesDefaultFeatures = false; + features = [ "dev" ]; + } + { + name = "primeorder"; + packageId = "primeorder"; + features = [ "dev" ]; + } + ]; + features = { + "alloc" = [ "ecdsa-core?/alloc" "elliptic-curve/alloc" ]; + "arithmetic" = [ "dep:primeorder" "elliptic-curve/arithmetic" ]; + "bits" = [ "arithmetic" "elliptic-curve/bits" ]; + "default" = [ "arithmetic" "ecdsa" "pem" "std" ]; + "digest" = [ "ecdsa-core/digest" "ecdsa-core/hazmat" ]; + "ecdh" = [ "arithmetic" "elliptic-curve/ecdh" ]; + "ecdsa" = [ "arithmetic" "ecdsa-core/signing" "ecdsa-core/verifying" "sha256" ]; + "ecdsa-core" = [ "dep:ecdsa-core" ]; + "expose-field" = [ "arithmetic" ]; + "hash2curve" = [ "arithmetic" "elliptic-curve/hash2curve" ]; + "jwk" = [ "elliptic-curve/jwk" ]; + "pem" = [ "elliptic-curve/pem" "ecdsa-core/pem" "pkcs8" ]; + "pkcs8" = [ "ecdsa-core?/pkcs8" "elliptic-curve/pkcs8" ]; + "serde" = [ "ecdsa-core?/serde" "elliptic-curve/serde" "primeorder?/serde" "serdect" ]; + "serdect" = [ "dep:serdect" ]; + "sha2" = [ "dep:sha2" ]; + "sha256" = [ "digest" "sha2" ]; + "std" = [ "alloc" "ecdsa-core?/std" "elliptic-curve/std" ]; + "test-vectors" = [ "dep:hex-literal" ]; + "voprf" = [ "elliptic-curve/voprf" "sha2" ]; + }; + resolvedDefaultFeatures = [ "alloc" "arithmetic" "default" "digest" "ecdsa" "ecdsa-core" "pem" "pkcs8" "sha2" "sha256" "std" ]; + }; "parking" = rec { crateName = "parking"; version = "2.2.1"; @@ -5743,6 +6460,27 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "pem-rfc7468" = rec { + crateName = "pem-rfc7468"; + version = "0.7.0"; + edition = "2021"; + sha256 = "04l4852scl4zdva31c1z6jafbak0ni5pi0j38ml108zwzjdrrcw8"; + libName = "pem_rfc7468"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "base64ct"; + packageId = "base64ct"; + } + ]; + features = { + "alloc" = [ "base64ct/alloc" ]; + "std" = [ "alloc" "base64ct/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; "percent-encoding" = rec { crateName = "percent-encoding"; version = "2.3.2"; @@ -5939,6 +6677,74 @@ rec { ]; }; + "pkcs1" = rec { + crateName = "pkcs1"; + version = "0.7.5"; + edition = "2021"; + sha256 = "0zz4mil3nchnxljdfs2k5ab1cjqn7kq5lqp62n9qfix01zqvkzy8"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "der"; + packageId = "der"; + features = [ "oid" ]; + } + { + name = "pkcs8"; + packageId = "pkcs8"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "spki"; + packageId = "spki"; + } + ]; + features = { + "alloc" = [ "der/alloc" "zeroize" "pkcs8?/alloc" ]; + "pem" = [ "alloc" "der/pem" "pkcs8?/pem" ]; + "pkcs8" = [ "dep:pkcs8" ]; + "std" = [ "der/std" "alloc" ]; + "zeroize" = [ "der/zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "pem" "pkcs8" "std" "zeroize" ]; + }; + "pkcs8" = rec { + crateName = "pkcs8"; + version = "0.10.2"; + edition = "2021"; + sha256 = "1dx7w21gvn07azszgqd3ryjhyphsrjrmq5mmz1fbxkj5g0vv4l7r"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "der"; + packageId = "der"; + features = [ "oid" ]; + } + { + name = "spki"; + packageId = "spki"; + } + ]; + features = { + "3des" = [ "encryption" "pkcs5/3des" ]; + "alloc" = [ "der/alloc" "der/zeroize" "spki/alloc" ]; + "des-insecure" = [ "encryption" "pkcs5/des-insecure" ]; + "encryption" = [ "alloc" "pkcs5/alloc" "pkcs5/pbes2" "rand_core" ]; + "getrandom" = [ "rand_core/getrandom" ]; + "pem" = [ "alloc" "der/pem" "spki/pem" ]; + "pkcs5" = [ "dep:pkcs5" ]; + "rand_core" = [ "dep:rand_core" ]; + "sha1-insecure" = [ "encryption" "pkcs5/sha1-insecure" ]; + "std" = [ "alloc" "der/std" "spki/std" ]; + "subtle" = [ "dep:subtle" ]; + }; + resolvedDefaultFeatures = [ "alloc" "pem" "std" ]; + }; "pkg-config" = rec { crateName = "pkg-config"; version = "0.3.32"; @@ -6010,6 +6816,29 @@ rec { }; resolvedDefaultFeatures = [ "simd" "std" ]; }; + "primeorder" = rec { + crateName = "primeorder"; + version = "0.13.6"; + edition = "2021"; + sha256 = "1rp16710mxksagcjnxqjjq9r9wf5vf72fs8wxffnvhb6i6hiqgim"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "elliptic-curve"; + packageId = "elliptic-curve"; + usesDefaultFeatures = false; + features = [ "arithmetic" "sec1" ]; + } + ]; + features = { + "alloc" = [ "elliptic-curve/alloc" ]; + "serde" = [ "elliptic-curve/serde" "serdect" ]; + "serdect" = [ "dep:serdect" ]; + "std" = [ "alloc" "elliptic-curve/std" ]; + }; + }; "proc-macro2" = rec { crateName = "proc-macro2"; version = "1.0.103"; @@ -6186,7 +7015,44 @@ rec { "rustc-dep-of-std" = [ "core" ]; }; }; - "rand" = rec { + "rand 0.8.5" = rec { + crateName = "rand"; + version = "0.8.5"; + edition = "2018"; + sha256 = "013l6931nn7gkc23jz5mm3qdhf93jjf0fg64nz2lp4i51qd8vbrl"; + authors = [ + "The Rand Project Developers" + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "rand_chacha"; + packageId = "rand_chacha 0.3.1"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + } + ]; + features = { + "alloc" = [ "rand_core/alloc" ]; + "default" = [ "std" "std_rng" ]; + "getrandom" = [ "rand_core/getrandom" ]; + "libc" = [ "dep:libc" ]; + "log" = [ "dep:log" ]; + "packed_simd" = [ "dep:packed_simd" ]; + "rand_chacha" = [ "dep:rand_chacha" ]; + "serde" = [ "dep:serde" ]; + "serde1" = [ "serde" "rand_core/serde1" ]; + "simd_support" = [ "packed_simd" ]; + "std" = [ "rand_core/std" "rand_chacha/std" "alloc" "getrandom" "libc" ]; + "std_rng" = [ "rand_chacha" ]; + }; + resolvedDefaultFeatures = [ "rand_chacha" "std_rng" ]; + }; + "rand 0.9.2" = rec { crateName = "rand"; version = "0.9.2"; edition = "2021"; @@ -6198,13 +7064,13 @@ rec { dependencies = [ { name = "rand_chacha"; - packageId = "rand_chacha"; + packageId = "rand_chacha 0.9.0"; optional = true; usesDefaultFeatures = false; } { name = "rand_core"; - packageId = "rand_core"; + packageId = "rand_core 0.9.3"; usesDefaultFeatures = false; } ]; @@ -6217,9 +7083,38 @@ rec { "std_rng" = [ "dep:rand_chacha" ]; "thread_rng" = [ "std" "std_rng" "os_rng" ]; }; - resolvedDefaultFeatures = [ "alloc" "os_rng" "small_rng" "std" "std_rng" "thread_rng" ]; + resolvedDefaultFeatures = [ "alloc" "default" "os_rng" "small_rng" "std" "std_rng" "thread_rng" ]; + }; + "rand_chacha 0.3.1" = rec { + crateName = "rand_chacha"; + version = "0.3.1"; + edition = "2018"; + sha256 = "123x2adin558xbhvqb8w4f6syjsdkmqff8cxwhmjacpsl1ihmhg6"; + authors = [ + "The Rand Project Developers" + "The Rust Project Developers" + "The CryptoCorrosion Contributors" + ]; + dependencies = [ + { + name = "ppv-lite86"; + packageId = "ppv-lite86"; + usesDefaultFeatures = false; + features = [ "simd" ]; + } + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + } + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "serde1" = [ "serde" ]; + "std" = [ "ppv-lite86/std" ]; + }; }; - "rand_chacha" = rec { + "rand_chacha 0.9.0" = rec { crateName = "rand_chacha"; version = "0.9.0"; edition = "2021"; @@ -6238,13 +7133,13 @@ rec { } { name = "rand_core"; - packageId = "rand_core"; + packageId = "rand_core 0.9.3"; } ]; devDependencies = [ { name = "rand_core"; - packageId = "rand_core"; + packageId = "rand_core 0.9.3"; features = [ "os_rng" ]; } ]; @@ -6256,7 +7151,31 @@ rec { }; resolvedDefaultFeatures = [ "std" ]; }; - "rand_core" = rec { + "rand_core 0.6.4" = rec { + crateName = "rand_core"; + version = "0.6.4"; + edition = "2018"; + sha256 = "0b4j2v4cb5krak1pv6kakv4sz6xcwbrmy2zckc32hsigbrwy82zc"; + authors = [ + "The Rand Project Developers" + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "getrandom"; + packageId = "getrandom 0.2.16"; + optional = true; + } + ]; + features = { + "getrandom" = [ "dep:getrandom" ]; + "serde" = [ "dep:serde" ]; + "serde1" = [ "serde" ]; + "std" = [ "alloc" "getrandom" "getrandom/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "getrandom" "std" ]; + }; + "rand_core 0.9.3" = rec { crateName = "rand_core"; version = "0.9.3"; edition = "2021"; @@ -6713,6 +7632,29 @@ rec { }; resolvedDefaultFeatures = [ "blocking" ]; }; + "rfc6979" = rec { + crateName = "rfc6979"; + version = "0.4.0"; + edition = "2021"; + sha256 = "1chw95jgcfrysyzsq6a10b1j5qb7bagkx8h0wda4lv25in02mpgq"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "hmac"; + packageId = "hmac"; + usesDefaultFeatures = false; + features = [ "reset" ]; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + ]; + + }; "ring" = rec { crateName = "ring"; version = "0.17.14"; @@ -6774,6 +7716,119 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "dev_urandom_fallback" ]; }; + "rsa" = rec { + crateName = "rsa"; + version = "0.9.9"; + edition = "2021"; + sha256 = "122wywpd4m3v183sj7gzykqi5qkvgfzy8hynv5wq4dfha1n3g820"; + authors = [ + "RustCrypto Developers" + "dignifiedquire " + ]; + dependencies = [ + { + name = "const-oid"; + packageId = "const-oid"; + usesDefaultFeatures = false; + } + { + name = "digest"; + packageId = "digest"; + usesDefaultFeatures = false; + features = [ "alloc" "oid" ]; + } + { + name = "num-bigint-dig"; + packageId = "num-bigint-dig"; + rename = "num-bigint"; + usesDefaultFeatures = false; + features = [ "i128" "prime" "zeroize" ]; + } + { + name = "num-integer"; + packageId = "num-integer"; + usesDefaultFeatures = false; + } + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + features = [ "libm" ]; + } + { + name = "pkcs1"; + packageId = "pkcs1"; + usesDefaultFeatures = false; + features = [ "alloc" "pkcs8" ]; + } + { + name = "pkcs8"; + packageId = "pkcs8"; + usesDefaultFeatures = false; + features = [ "alloc" ]; + } + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + usesDefaultFeatures = false; + } + { + name = "sha2"; + packageId = "sha2"; + optional = true; + usesDefaultFeatures = false; + features = [ "oid" ]; + } + { + name = "signature"; + packageId = "signature"; + usesDefaultFeatures = false; + features = [ "alloc" "digest" "rand_core" ]; + } + { + name = "spki"; + packageId = "spki"; + usesDefaultFeatures = false; + features = [ "alloc" ]; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + features = [ "alloc" ]; + } + ]; + devDependencies = [ + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + usesDefaultFeatures = false; + } + { + name = "sha2"; + packageId = "sha2"; + usesDefaultFeatures = false; + features = [ "oid" ]; + } + ]; + features = { + "default" = [ "std" "pem" "u64_digit" ]; + "getrandom" = [ "rand_core/getrandom" ]; + "nightly" = [ "num-bigint/nightly" ]; + "pem" = [ "pkcs1/pem" "pkcs8/pem" ]; + "pkcs5" = [ "pkcs8/encryption" ]; + "serde" = [ "dep:serde" "num-bigint/serde" ]; + "sha1" = [ "dep:sha1" ]; + "sha2" = [ "dep:sha2" ]; + "std" = [ "digest/std" "pkcs1/std" "pkcs8/std" "rand_core/std" "signature/std" ]; + "u64_digit" = [ "num-bigint/u64_digit" ]; + }; + resolvedDefaultFeatures = [ "default" "pem" "sha2" "std" "u64_digit" ]; + }; "rustls" = rec { crateName = "rustls"; version = "0.23.34"; @@ -7106,6 +8161,66 @@ rec { "default" = [ "use_std" ]; }; }; + "sec1" = rec { + crateName = "sec1"; + version = "0.7.3"; + edition = "2021"; + sha256 = "1p273j8c87pid6a1iyyc7vxbvifrw55wbxgr0dh3l8vnbxb7msfk"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "base16ct"; + packageId = "base16ct"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "der"; + packageId = "der"; + optional = true; + features = [ "oid" ]; + } + { + name = "generic-array"; + packageId = "generic-array"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "pkcs8"; + packageId = "pkcs8"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "subtle"; + packageId = "subtle"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "der?/alloc" "pkcs8?/alloc" "zeroize?/alloc" ]; + "default" = [ "der" "point" ]; + "der" = [ "dep:der" "zeroize" ]; + "pem" = [ "alloc" "der/pem" "pkcs8/pem" ]; + "pkcs8" = [ "dep:pkcs8" ]; + "point" = [ "dep:base16ct" "dep:generic-array" ]; + "serde" = [ "dep:serdect" ]; + "std" = [ "alloc" "der?/std" ]; + "subtle" = [ "dep:subtle" ]; + "zeroize" = [ "dep:zeroize" "der?/zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "der" "pem" "pkcs8" "point" "std" "subtle" "zeroize" ]; + }; "secrecy" = rec { crateName = "secrecy"; version = "0.10.3"; @@ -7505,6 +8620,45 @@ rec { ]; }; + "sha1" = rec { + crateName = "sha1"; + version = "0.10.6"; + edition = "2018"; + sha256 = "1fnnxlfg08xhkmwf2ahv634as30l1i3xhlhkvxflmasi5nd85gz3"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "cpufeatures"; + packageId = "cpufeatures"; + target = { target, features }: (("aarch64" == target."arch" or null) || ("x86" == target."arch" or null) || ("x86_64" == target."arch" or null)); + } + { + name = "digest"; + packageId = "digest"; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "asm" = [ "sha1-asm" ]; + "default" = [ "std" ]; + "oid" = [ "digest/oid" ]; + "sha1-asm" = [ "dep:sha1-asm" ]; + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "sha2" = rec { crateName = "sha2"; version = "0.10.9"; @@ -7543,6 +8697,7 @@ rec { "sha2-asm" = [ "dep:sha2-asm" ]; "std" = [ "digest/std" ]; }; + resolvedDefaultFeatures = [ "default" "oid" "std" ]; }; "sharded-slab" = rec { crateName = "sharded-slab"; @@ -7599,6 +8754,36 @@ rec { ]; }; + "signature" = rec { + crateName = "signature"; + version = "2.2.0"; + edition = "2021"; + sha256 = "1pi9hd5vqfr3q3k49k37z06p7gs5si0in32qia4mmr1dancr6m3p"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "digest"; + packageId = "digest"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "derive" = [ "dep:derive" ]; + "digest" = [ "dep:digest" ]; + "rand_core" = [ "dep:rand_core" ]; + "std" = [ "alloc" "rand_core?/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "digest" "rand_core" "std" ]; + }; "simd-adler32" = rec { crateName = "simd-adler32"; version = "0.3.7"; @@ -7765,54 +8950,214 @@ rec { packageId = "quote"; } { - name = "syn"; - packageId = "syn 2.0.108"; - features = [ "full" ]; + name = "syn"; + packageId = "syn 2.0.108"; + features = [ "full" ]; + } + ]; + features = { + }; + resolvedDefaultFeatures = [ "rust_1_61" ]; + }; + "socket2" = rec { + crateName = "socket2"; + version = "0.6.1"; + edition = "2021"; + sha256 = "109qn0kjhqi5zds84qyqi5wn72g8azjhmf4b04fkgkrkd48rw4hp"; + authors = [ + "Alex Crichton " + "Thomas de Zeeuw " + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "windows-sys"; + packageId = "windows-sys 0.60.2"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; + } + ]; + features = { + }; + resolvedDefaultFeatures = [ "all" ]; + }; + "spin" = rec { + crateName = "spin"; + version = "0.9.8"; + edition = "2015"; + sha256 = "0rvam5r0p3a6qhc18scqpvpgb3ckzyqxpgdfyjnghh8ja7byi039"; + authors = [ + "Mathijs van de Nes " + "John Ericson " + "Joshua Barretto " + ]; + features = { + "barrier" = [ "mutex" ]; + "default" = [ "lock_api" "mutex" "spin_mutex" "rwlock" "once" "lazy" "barrier" ]; + "fair_mutex" = [ "mutex" ]; + "lazy" = [ "once" ]; + "lock_api" = [ "lock_api_crate" ]; + "lock_api_crate" = [ "dep:lock_api_crate" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; + "portable_atomic" = [ "portable-atomic" ]; + "spin_mutex" = [ "mutex" ]; + "ticket_mutex" = [ "mutex" ]; + "use_ticket_mutex" = [ "mutex" "ticket_mutex" ]; + }; + resolvedDefaultFeatures = [ "once" ]; + }; + "spki" = rec { + crateName = "spki"; + version = "0.7.3"; + edition = "2021"; + sha256 = "17fj8k5fmx4w9mp27l970clrh5qa7r5sjdvbsln987xhb34dc7nr"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "base64ct"; + packageId = "base64ct"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "der"; + packageId = "der"; + features = [ "oid" ]; + } + ]; + features = { + "alloc" = [ "base64ct?/alloc" "der/alloc" ]; + "arbitrary" = [ "std" "dep:arbitrary" "der/arbitrary" ]; + "base64" = [ "dep:base64ct" ]; + "fingerprint" = [ "sha2" ]; + "pem" = [ "alloc" "der/pem" ]; + "sha2" = [ "dep:sha2" ]; + "std" = [ "der/std" "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "pem" "std" ]; + }; + "stable_deref_trait" = rec { + crateName = "stable_deref_trait"; + version = "1.2.1"; + edition = "2015"; + sha256 = "15h5h73ppqyhdhx6ywxfj88azmrpml9gl6zp3pwy2malqa6vxqkc"; + authors = [ + "Robert Grosse " + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; + "stackable-certs" = rec { + crateName = "stackable-certs"; + version = "0.4.0"; + edition = "2024"; + workspace_member = null; + src = pkgs.fetchgit { + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + }; + libName = "stackable_certs"; + authors = [ + "Stackable GmbH " + ]; + dependencies = [ + { + name = "const-oid"; + packageId = "const-oid"; + features = [ "db" ]; + } + { + name = "ecdsa"; + packageId = "ecdsa"; + features = [ "digest" "pem" ]; + } + { + name = "k8s-openapi"; + packageId = "k8s-openapi"; + usesDefaultFeatures = false; + features = [ "schemars" "v1_34" ]; + } + { + name = "kube"; + packageId = "kube"; + usesDefaultFeatures = false; + features = [ "client" "jsonpatch" "runtime" "derive" "admission" "rustls-tls" "ring" ]; + } + { + name = "p256"; + packageId = "p256"; + features = [ "ecdsa" ]; + } + { + name = "rand"; + packageId = "rand 0.9.2"; + } + { + name = "rand_core"; + packageId = "rand_core 0.6.4"; + } + { + name = "rsa"; + packageId = "rsa"; + features = [ "sha2" ]; + } + { + name = "sha2"; + packageId = "sha2"; + features = [ "oid" ]; + } + { + name = "signature"; + packageId = "signature"; + } + { + name = "snafu"; + packageId = "snafu 0.8.9"; + } + { + name = "stackable-shared"; + packageId = "stackable-shared"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "macros" "rt-multi-thread" "fs" ]; + } + { + name = "tokio-rustls"; + packageId = "tokio-rustls"; + optional = true; + usesDefaultFeatures = false; + features = [ "ring" "logging" "tls12" ]; + } + { + name = "tracing"; + packageId = "tracing"; } - ]; - features = { - }; - resolvedDefaultFeatures = [ "rust_1_61" ]; - }; - "socket2" = rec { - crateName = "socket2"; - version = "0.6.1"; - edition = "2021"; - sha256 = "109qn0kjhqi5zds84qyqi5wn72g8azjhmf4b04fkgkrkd48rw4hp"; - authors = [ - "Alex Crichton " - "Thomas de Zeeuw " - ]; - dependencies = [ { - name = "libc"; - packageId = "libc"; - target = { target, features }: (target."unix" or false); + name = "x509-cert"; + packageId = "x509-cert"; + features = [ "builder" ]; } { - name = "windows-sys"; - packageId = "windows-sys 0.60.2"; - target = { target, features }: (target."windows" or false); - features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; + name = "zeroize"; + packageId = "zeroize"; } ]; features = { + "rustls" = [ "dep:tokio-rustls" ]; }; - resolvedDefaultFeatures = [ "all" ]; - }; - "stable_deref_trait" = rec { - crateName = "stable_deref_trait"; - version = "1.2.1"; - edition = "2015"; - sha256 = "15h5h73ppqyhdhx6ywxfj88azmrpml9gl6zp3pwy2malqa6vxqkc"; - authors = [ - "Robert Grosse " - ]; - features = { - "default" = [ "std" ]; - "std" = [ "alloc" ]; - }; - resolvedDefaultFeatures = [ "alloc" ]; + resolvedDefaultFeatures = [ "default" "rustls" ]; }; "stackable-commons-operator" = rec { crateName = "stackable-commons-operator"; @@ -7863,7 +9208,7 @@ rec { { name = "stackable-operator"; packageId = "stackable-operator"; - features = [ "telemetry" ]; + features = [ "telemetry" "webhook" ]; } { name = "strum"; @@ -7891,13 +9236,13 @@ rec { }; "stackable-operator" = rec { crateName = "stackable-operator"; - version = "0.100.1"; + version = "0.100.3"; edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "184423db7409f853bd69db7eeecd1affbf97ef40"; - sha256 = "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; }; libName = "stackable_operator"; authors = [ @@ -7962,7 +9307,7 @@ rec { name = "kube"; packageId = "kube"; usesDefaultFeatures = false; - features = [ "client" "jsonpatch" "runtime" "derive" "rustls-tls" "ring" ]; + features = [ "client" "jsonpatch" "runtime" "derive" "admission" "rustls-tls" "ring" ]; } { name = "product-config"; @@ -8018,6 +9363,11 @@ rec { packageId = "stackable-versioned"; optional = true; } + { + name = "stackable-webhook"; + packageId = "stackable-webhook"; + optional = true; + } { name = "strum"; packageId = "strum"; @@ -8056,7 +9406,7 @@ rec { "versioned" = [ "dep:stackable-versioned" ]; "webhook" = [ "dep:stackable-webhook" ]; }; - resolvedDefaultFeatures = [ "clap" "default" "telemetry" "versioned" ]; + resolvedDefaultFeatures = [ "clap" "default" "telemetry" "versioned" "webhook" ]; }; "stackable-operator-derive" = rec { crateName = "stackable-operator-derive"; @@ -8064,9 +9414,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "184423db7409f853bd69db7eeecd1affbf97ef40"; - sha256 = "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -8099,9 +9449,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "184423db7409f853bd69db7eeecd1affbf97ef40"; - sha256 = "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; }; libName = "stackable_shared"; authors = [ @@ -8124,7 +9474,7 @@ rec { name = "kube"; packageId = "kube"; usesDefaultFeatures = false; - features = [ "client" "jsonpatch" "runtime" "derive" "rustls-tls" "ring" ]; + features = [ "client" "jsonpatch" "runtime" "derive" "admission" "rustls-tls" "ring" ]; } { name = "schemars"; @@ -8181,9 +9531,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "184423db7409f853bd69db7eeecd1affbf97ef40"; - sha256 = "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; }; libName = "stackable_telemetry"; authors = [ @@ -8291,9 +9641,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "184423db7409f853bd69db7eeecd1affbf97ef40"; - sha256 = "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; }; libName = "stackable_versioned"; authors = [ @@ -8335,9 +9685,9 @@ rec { edition = "2024"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/stackabletech/operator-rs.git"; - rev = "184423db7409f853bd69db7eeecd1affbf97ef40"; - sha256 = "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l"; + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; }; procMacro = true; libName = "stackable_versioned_macros"; @@ -8376,7 +9726,7 @@ rec { name = "kube"; packageId = "kube"; usesDefaultFeatures = false; - features = [ "client" "jsonpatch" "runtime" "derive" "rustls-tls" "ring" ]; + features = [ "client" "jsonpatch" "runtime" "derive" "admission" "rustls-tls" "ring" ]; } { name = "proc-macro2"; @@ -8392,6 +9742,134 @@ rec { } ]; + }; + "stackable-webhook" = rec { + crateName = "stackable-webhook"; + version = "0.7.1"; + edition = "2024"; + workspace_member = null; + src = pkgs.fetchgit { + url = "https://github.com/stackabletech//operator-rs.git"; + rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; + sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + }; + libName = "stackable_webhook"; + authors = [ + "Stackable GmbH " + ]; + dependencies = [ + { + name = "arc-swap"; + packageId = "arc-swap"; + } + { + name = "async-trait"; + packageId = "async-trait"; + } + { + name = "axum"; + packageId = "axum"; + features = [ "http2" ]; + } + { + name = "futures-util"; + packageId = "futures-util"; + } + { + name = "hyper"; + packageId = "hyper"; + features = [ "full" ]; + } + { + name = "hyper-util"; + packageId = "hyper-util"; + } + { + name = "k8s-openapi"; + packageId = "k8s-openapi"; + usesDefaultFeatures = false; + features = [ "schemars" "v1_34" ]; + } + { + name = "kube"; + packageId = "kube"; + usesDefaultFeatures = false; + features = [ "client" "jsonpatch" "runtime" "derive" "admission" "rustls-tls" "ring" ]; + } + { + name = "opentelemetry"; + packageId = "opentelemetry"; + } + { + name = "opentelemetry-semantic-conventions"; + packageId = "opentelemetry-semantic-conventions"; + } + { + name = "rand"; + packageId = "rand 0.9.2"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "snafu"; + packageId = "snafu 0.8.9"; + } + { + name = "stackable-certs"; + packageId = "stackable-certs"; + features = [ "rustls" ]; + } + { + name = "stackable-shared"; + packageId = "stackable-shared"; + } + { + name = "stackable-telemetry"; + packageId = "stackable-telemetry"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "macros" "rt-multi-thread" "fs" ]; + } + { + name = "tokio-rustls"; + packageId = "tokio-rustls"; + usesDefaultFeatures = false; + features = [ "ring" "logging" "tls12" ]; + } + { + name = "tower"; + packageId = "tower"; + features = [ "util" ]; + } + { + name = "tower-http"; + packageId = "tower-http"; + features = [ "trace" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "tracing-opentelemetry"; + packageId = "tracing-opentelemetry"; + } + { + name = "x509-cert"; + packageId = "x509-cert"; + features = [ "builder" ]; + } + ]; + }; "strsim" = rec { crateName = "strsim"; @@ -8469,6 +9947,7 @@ rec { features = { "default" = [ "std" "i128" ]; }; + resolvedDefaultFeatures = [ "i128" ]; }; "syn 1.0.109" = rec { crateName = "syn"; @@ -8843,6 +10322,68 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "zerovec" ]; }; + "tls_codec" = rec { + crateName = "tls_codec"; + version = "0.4.2"; + edition = "2021"; + sha256 = "0sxzj0pdinn7fsc8aihqgfylsqi7z9jca0aqy3b8kfz28l9f1qhd"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "tls_codec_derive"; + packageId = "tls_codec_derive"; + optional = true; + } + { + name = "zeroize"; + packageId = "zeroize"; + usesDefaultFeatures = false; + features = [ "alloc" "zeroize_derive" ]; + } + ]; + features = { + "arbitrary" = [ "std" "dep:arbitrary" ]; + "conditional_deserialization" = [ "derive" "tls_codec_derive/conditional_deserialization" ]; + "default" = [ "std" ]; + "derive" = [ "tls_codec_derive" ]; + "serde" = [ "std" "dep:serde" ]; + "std" = [ "tls_codec_derive?/std" ]; + "tls_codec_derive" = [ "dep:tls_codec_derive" ]; + }; + resolvedDefaultFeatures = [ "derive" "std" "tls_codec_derive" ]; + }; + "tls_codec_derive" = rec { + crateName = "tls_codec_derive"; + version = "0.4.2"; + edition = "2021"; + sha256 = "1gglj5cxkpv7i3jazffksrfy5h5242kdvsqawjm2yh1915lpcbid"; + procMacro = true; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.108"; + features = [ "parsing" ]; + } + ]; + features = { + "conditional_deserialization" = [ "syn/full" ]; + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "tokio" = rec { crateName = "tokio"; version = "1.48.0"; @@ -9021,7 +10562,7 @@ rec { "tls12" = [ "rustls/tls12" ]; "zlib" = [ "rustls/zlib" ]; }; - resolvedDefaultFeatures = [ "logging" "tls12" ]; + resolvedDefaultFeatures = [ "logging" "ring" "tls12" ]; }; "tokio-stream" = rec { crateName = "tokio-stream"; @@ -12156,6 +13697,62 @@ rec { "either" = [ "dep:either" ]; }; }; + "x509-cert" = rec { + crateName = "x509-cert"; + version = "0.2.5"; + edition = "2021"; + sha256 = "155f42vm6m7phn8w7s2wmk9vli3ws45dqpk5z3jilw0a04syj08k"; + libName = "x509_cert"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "const-oid"; + packageId = "const-oid"; + features = [ "db" ]; + } + { + name = "der"; + packageId = "der"; + features = [ "alloc" "derive" "flagset" "oid" ]; + } + { + name = "sha1"; + packageId = "sha1"; + optional = true; + } + { + name = "signature"; + packageId = "signature"; + optional = true; + features = [ "rand_core" ]; + } + { + name = "spki"; + packageId = "spki"; + features = [ "alloc" ]; + } + { + name = "tls_codec"; + packageId = "tls_codec"; + optional = true; + usesDefaultFeatures = false; + features = [ "derive" ]; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" "std" "der/arbitrary" "spki/arbitrary" ]; + "builder" = [ "std" "sha1/default" "signature" ]; + "default" = [ "pem" "std" ]; + "pem" = [ "der/pem" "spki/pem" ]; + "sct" = [ "dep:tls_codec" ]; + "sha1" = [ "dep:sha1" ]; + "signature" = [ "dep:signature" ]; + "std" = [ "const-oid/std" "der/std" "spki/std" "tls_codec?/std" ]; + }; + resolvedDefaultFeatures = [ "builder" "default" "pem" "sha1" "signature" "std" ]; + }; "xml" = rec { crateName = "xml"; version = "1.0.1"; @@ -12372,6 +13969,13 @@ rec { authors = [ "The RustCrypto Project Developers" ]; + dependencies = [ + { + name = "zeroize_derive"; + packageId = "zeroize_derive"; + optional = true; + } + ]; features = { "default" = [ "alloc" ]; "derive" = [ "zeroize_derive" ]; @@ -12379,7 +13983,33 @@ rec { "std" = [ "alloc" ]; "zeroize_derive" = [ "dep:zeroize_derive" ]; }; - resolvedDefaultFeatures = [ "alloc" "default" ]; + resolvedDefaultFeatures = [ "alloc" "default" "zeroize_derive" ]; + }; + "zeroize_derive" = rec { + crateName = "zeroize_derive"; + version = "1.4.2"; + edition = "2021"; + sha256 = "0sczjlqjdmrp3wn62g7mw6p438c9j4jgp2f9zamd56991mdycdnf"; + procMacro = true; + authors = [ + "The RustCrypto Project Developers" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.108"; + features = [ "full" "extra-traits" "visit" ]; + } + ]; + }; "zerotrie" = rec { crateName = "zerotrie"; diff --git a/Cargo.toml b/Cargo.toml index 6a95b3c..d963c47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" repository = "https://github.com/stackabletech/commons-operator" [workspace.dependencies] -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", features = ["telemetry"], tag = "stackable-operator-0.100.1" } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", features = ["telemetry", "webhook"], tag = "stackable-operator-0.100.1" } anyhow = "1.0" built = { version = "0.8", features = ["chrono", "git2"] } @@ -24,5 +24,6 @@ strum = { version = "0.27", features = ["derive"] } tokio = { version = "1.40", features = ["full"] } tracing = "0.1" -# [patch."https://github.com/stackabletech/operator-rs.git"] -# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" } +[patch."https://github.com/stackabletech/operator-rs.git"] +# stackable-operator = { path = "../operator-rs/crates/stackable-operator" } +stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feat/mutating-webhook" } diff --git a/_TEST.yaml b/_TEST.yaml new file mode 100644 index 0000000..654a06a --- /dev/null +++ b/_TEST.yaml @@ -0,0 +1,62 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: web + labels: + restarter.stackable.tech/enabled: "true" +spec: + selector: + matchLabels: + app: nginx + serviceName: nginx + replicas: 3 + template: + metadata: + labels: + app: nginx + spec: + terminationGracePeriodSeconds: 10 + containers: + - name: nginx + image: registry.k8s.io/nginx-slim:0.24 + ports: + - containerPort: 80 + name: web + volumeMounts: + - name: config + mountPath: "/config" + envFrom: + - configMapRef: + name: web-config-2 + volumes: + - name: config + configMap: + name: web-config +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx + labels: + app: nginx +spec: + ports: + - port: 80 + name: web + clusterIP: None + selector: + app: nginx +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: web-config +data: + foo: bar +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: web-config-2 +data: + foo: bar diff --git a/crate-hashes.json b/crate-hashes.json index 1c58f75..ac585e9 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,10 +1,12 @@ { - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#k8s-version@0.1.3": "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#stackable-operator-derive@0.3.1": "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#stackable-operator@0.100.1": "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#stackable-shared@0.0.3": "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#stackable-telemetry@0.6.1": "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#stackable-versioned-macros@0.8.3": "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l", - "git+https://github.com/stackabletech/operator-rs.git?tag=stackable-operator-0.100.1#stackable-versioned@0.8.3": "1a98klljvifnc168f1wc3d6szcry1lamxgjjdq89plr99p4b953l", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#k8s-version@0.1.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-certs@0.4.0": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-operator-derive@0.3.1": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-operator@0.100.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-shared@0.0.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-telemetry@0.6.1": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-versioned-macros@0.8.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-versioned@0.8.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-webhook@0.7.1": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", "git+https://github.com/stackabletech/product-config.git?tag=0.8.0#product-config@0.8.0": "1dz70kapm2wdqcr7ndyjji0lhsl98bsq95gnb2lw487wf6yr7987" } \ No newline at end of file diff --git a/deploy/helm/commons-operator/templates/roles.yaml b/deploy/helm/commons-operator/templates/roles.yaml index 71b574f..3dd83b2 100644 --- a/deploy/helm/commons-operator/templates/roles.yaml +++ b/deploy/helm/commons-operator/templates/roles.yaml @@ -46,3 +46,10 @@ rules: - pods/eviction verbs: - create + # Required to maintain MutatingWebhookConfigurations. The operator needs to do this, as it needs + # to enter e.g. it's generated certificate in the webhooks. + - apiGroups: [admissionregistration.k8s.io] + resources: [mutatingwebhookconfigurations] + verbs: + - create + - patch diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 5495162..ed05988 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -2,10 +2,9 @@ // This will need changes in our and upstream error types. #![allow(clippy::large_enum_variant)] -mod restart_controller; - +use anyhow::anyhow; use clap::Parser; -use futures::FutureExt; +use futures::{FutureExt, TryFutureExt}; use stackable_operator::{ YamlSchema as _, cli::{Command, RunArguments}, @@ -17,11 +16,18 @@ use stackable_operator::{ shared::yaml::SerializeOptions, telemetry::Tracing, }; +use webhooks::create_webhook; + +mod restart_controller; +mod webhooks; mod built_info { include!(concat!(env!("OUT_DIR"), "/built.rs")); } +pub const OPERATOR_NAME: &str = "commons.stackable.tech"; +pub const FIELD_MANAGER: &str = "commons-operator"; + #[derive(Parser)] #[clap(about, author)] struct Opts { @@ -44,7 +50,7 @@ async fn main() -> anyhow::Result<()> { Command::Run(RunArguments { product_config: _, watch_namespace, - operator_environment: _, + operator_environment, maintenance, common, }) => { @@ -76,12 +82,28 @@ async fn main() -> anyhow::Result<()> { ) .await?; + let webhook = create_webhook( + &operator_environment, + // TODO: Make user configurable + false, + client.as_kube_client(), + ) + .await?; + let webhook = webhook + .run() + .map_err(|err| anyhow!(err).context("failed to run webhook")); + let sts_restart_controller = restart_controller::statefulset::start(&client, &watch_namespace).map(anyhow::Ok); let pod_restart_controller = restart_controller::pod::start(&client, &watch_namespace).map(anyhow::Ok); - futures::try_join!(sts_restart_controller, pod_restart_controller, eos_checker)?; + futures::try_join!( + sts_restart_controller, + pod_restart_controller, + eos_checker, + webhook + )?; } } diff --git a/rust/operator-binary/src/restart_controller/statefulset.rs b/rust/operator-binary/src/restart_controller/statefulset.rs index 9ce1773..76d1ec0 100644 --- a/rust/operator-binary/src/restart_controller/statefulset.rs +++ b/rust/operator-binary/src/restart_controller/statefulset.rs @@ -13,9 +13,8 @@ use stackable_operator::{ apps::v1::StatefulSet, core::v1::{ConfigMap, EnvFromSource, EnvVar, PodSpec, Secret, Volume}, }, - kube, kube::{ - Resource, ResourceExt, + self, Resource, ResourceExt, api::{PartialObjectMeta, Patch, PatchParams}, core::{DeserializeGuard, DynamicObject, error_boundary}, runtime::{ diff --git a/rust/operator-binary/src/webhooks.rs b/rust/operator-binary/src/webhooks.rs new file mode 100644 index 0000000..35d32d7 --- /dev/null +++ b/rust/operator-binary/src/webhooks.rs @@ -0,0 +1,116 @@ +use std::collections::BTreeMap; + +use snafu::{ResultExt, Snafu}; +use stackable_operator::{ + builder::meta::ObjectMetaBuilder, + cli::OperatorEnvironmentOptions, + k8s_openapi::{ + api::{ + admissionregistration::v1::{ + MutatingWebhook, MutatingWebhookConfiguration, RuleWithOperations, + WebhookClientConfig, + }, + apps::v1::StatefulSet, + }, + apimachinery::pkg::apis::meta::v1::LabelSelector, + }, + kube::{ + Client, + core::admission::{AdmissionRequest, AdmissionResponse}, + }, + kvp::Label, + webhook::{WebhookError, WebhookOptions, WebhookServer, servers::MutatingWebhookServer}, +}; + +use crate::{FIELD_MANAGER, OPERATOR_NAME}; + +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display("failed to create webhook server"))] + CreateWebhookServer { source: WebhookError }, +} + +pub async fn create_webhook<'a>( + operator_environment: &'a OperatorEnvironmentOptions, + disable_mutating_webhook_configuration_maintenance: bool, + client: Client, +) -> Result { + let mutating_webhook_server = MutatingWebhookServer::new( + get_mutating_webhook_configuration(), + foo, + disable_mutating_webhook_configuration_maintenance, + client, + FIELD_MANAGER.to_owned(), + ); + + let webhook_options = WebhookOptions { + socket_addr: WebhookServer::DEFAULT_SOCKET_ADDRESS, + operator_namespace: operator_environment.operator_namespace.to_owned(), + operator_service_name: operator_environment.operator_service_name.to_owned(), + }; + WebhookServer::new(webhook_options, vec![Box::new(mutating_webhook_server)]) + .await + .context(CreateWebhookServerSnafu) +} + +fn get_mutating_webhook_configuration() -> MutatingWebhookConfiguration { + let webhook_name = "restarter-sts-enricher.stackable.tech"; + let metadata = ObjectMetaBuilder::new() + .name(webhook_name) + .with_label(Label::stackable_vendor()) + .with_label( + Label::managed_by(OPERATOR_NAME, webhook_name).expect("static label is always valid"), + ) + .build(); + + MutatingWebhookConfiguration { + metadata, + webhooks: Some(vec![MutatingWebhook { + name: webhook_name.to_owned(), + // This is checked by the stackable_webhook code + admission_review_versions: vec!["v1".to_owned()], + rules: Some(vec![RuleWithOperations { + api_groups: Some(vec!["apps".to_owned()]), + api_versions: Some(vec!["v1".to_owned()]), + resources: Some(vec!["statefulsets".to_owned()]), + operations: Some(vec!["CREATE".to_owned()]), + scope: Some("Namespaced".to_owned()), + }]), + // We only need to care about StatefulSets with the `restarter.stackable.tech/enabled`` + // label set to `true`. + object_selector: Some(LabelSelector { + match_labels: Some(BTreeMap::from([( + "restarter.stackable.tech/enabled".to_owned(), + "true".to_owned(), + )])), + match_expressions: None, + }), + // Will be set by the stackable_webhook code + client_config: WebhookClientConfig::default(), + // Worst case the annotations are missing cause a restart of Pod 0, basically the same + // behavior which we had for years. + // See https://github.com/stackabletech/commons-operator/issues/111 for details + // failure_policy: Some("Ignore".to_owned()), + // TEMP for testing + failure_policy: Some("Fail".to_owned()), + // It could be the case that other mutating webhooks add more ConfigMpa/Secret mounts, + // in which case it would be nice if we detect that. + reinvocation_policy: Some("IfNeeded".to_owned()), + // We don't have side effects + side_effects: "None".to_owned(), + ..Default::default() + }]), + } +} + +fn foo(request: AdmissionRequest) -> AdmissionResponse { + let Some(sts) = &request.object else { + return AdmissionResponse::invalid( + "object (of type StatefulSet) missing - for operation CREATE it must be always present", + ); + }; + + dbg!(&request); + + AdmissionResponse::from(&request) +} From 54480ad07b2c1a8d6c5e9b39947dfecf7cac68ba Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 17 Nov 2025 16:30:36 +0100 Subject: [PATCH 2/7] Actually enrich StatefulSets in mutating webhooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many parts copied from https://github.com/stackabletech/commons-operator/tree/spike/sts-restarter-webhook Co-authored-by: Natalie Klestrup Röijezon --- Cargo.lock | 19 +- Cargo.nix | 40 ++-- Cargo.toml | 1 + _TEST.yaml | 57 ++--- crate-hashes.json | 18 +- rust/operator-binary/Cargo.toml | 1 + rust/operator-binary/src/main.rs | 21 +- .../src/restart_controller/pod.rs | 8 +- .../src/restart_controller/statefulset.rs | 185 ++++++++------- .../operator-binary/src/utils/delayed_init.rs | 212 ++++++++++++++++++ rust/operator-binary/src/utils/mod.rs | 1 + rust/operator-binary/src/webhooks.rs | 76 ++++++- 12 files changed, 478 insertions(+), 161 deletions(-) create mode 100644 rust/operator-binary/src/utils/delayed_init.rs create mode 100644 rust/operator-binary/src/utils/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 52a364d..c07e76d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1459,7 +1459,7 @@ dependencies = [ [[package]] name = "k8s-version" version = "0.1.3" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "darling", "regex", @@ -2733,7 +2733,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stackable-certs" version = "0.4.0" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "const-oid", "ecdsa", @@ -2763,6 +2763,7 @@ dependencies = [ "clap", "futures 0.3.31", "http", + "json-patch", "serde", "serde_json", "snafu 0.8.9", @@ -2775,7 +2776,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.100.3" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "chrono", "clap", @@ -2814,7 +2815,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.3.1" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "darling", "proc-macro2", @@ -2825,7 +2826,7 @@ dependencies = [ [[package]] name = "stackable-shared" version = "0.0.3" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "chrono", "k8s-openapi", @@ -2842,7 +2843,7 @@ dependencies = [ [[package]] name = "stackable-telemetry" version = "0.6.1" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "axum", "clap", @@ -2866,7 +2867,7 @@ dependencies = [ [[package]] name = "stackable-versioned" version = "0.8.3" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "schemars", "serde", @@ -2879,7 +2880,7 @@ dependencies = [ [[package]] name = "stackable-versioned-macros" version = "0.8.3" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "convert_case", "darling", @@ -2896,7 +2897,7 @@ dependencies = [ [[package]] name = "stackable-webhook" version = "0.7.1" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#91fd3cb2a2093b54660f0cb88d43a2523851fcd0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#886efccb8e3d2a8af602c8bb09171e96c6367145" dependencies = [ "arc-swap", "async-trait", diff --git a/Cargo.nix b/Cargo.nix index 4f56375..2d3dc45 100644 --- a/Cargo.nix +++ b/Cargo.nix @@ -4644,8 +4644,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; libName = "k8s_version"; authors = [ @@ -9063,8 +9063,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; libName = "stackable_certs"; authors = [ @@ -9192,6 +9192,10 @@ rec { name = "http"; packageId = "http"; } + { + name = "json-patch"; + packageId = "json-patch"; + } { name = "serde"; packageId = "serde"; @@ -9241,8 +9245,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; libName = "stackable_operator"; authors = [ @@ -9415,8 +9419,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; procMacro = true; libName = "stackable_operator_derive"; @@ -9450,8 +9454,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; libName = "stackable_shared"; authors = [ @@ -9532,8 +9536,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; libName = "stackable_telemetry"; authors = [ @@ -9642,8 +9646,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; libName = "stackable_versioned"; authors = [ @@ -9686,8 +9690,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; procMacro = true; libName = "stackable_versioned_macros"; @@ -9750,8 +9754,8 @@ rec { workspace_member = null; src = pkgs.fetchgit { url = "https://github.com/stackabletech//operator-rs.git"; - rev = "91fd3cb2a2093b54660f0cb88d43a2523851fcd0"; - sha256 = "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd"; + rev = "886efccb8e3d2a8af602c8bb09171e96c6367145"; + sha256 = "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf"; }; libName = "stackable_webhook"; authors = [ diff --git a/Cargo.toml b/Cargo.toml index d963c47..fb36734 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ built = { version = "0.8", features = ["chrono", "git2"] } clap = "4.5" futures = { version = "0.3", features = ["compat"] } http = "1.3" +json-patch = "4.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" snafu = "0.8" diff --git a/_TEST.yaml b/_TEST.yaml index 654a06a..b894716 100644 --- a/_TEST.yaml +++ b/_TEST.yaml @@ -1,3 +1,32 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx + labels: + app: nginx +spec: + ports: + - port: 80 + name: web + clusterIP: None + selector: + app: nginx +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: web-config +data: + foo: bar +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: web-config-2 +data: + foo: bar +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -32,31 +61,3 @@ spec: - name: config configMap: name: web-config ---- -apiVersion: v1 -kind: Service -metadata: - name: nginx - labels: - app: nginx -spec: - ports: - - port: 80 - name: web - clusterIP: None - selector: - app: nginx ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: web-config -data: - foo: bar ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: web-config-2 -data: - foo: bar diff --git a/crate-hashes.json b/crate-hashes.json index ac585e9..99c8408 100644 --- a/crate-hashes.json +++ b/crate-hashes.json @@ -1,12 +1,12 @@ { - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#k8s-version@0.1.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-certs@0.4.0": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-operator-derive@0.3.1": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-operator@0.100.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-shared@0.0.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-telemetry@0.6.1": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-versioned-macros@0.8.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-versioned@0.8.3": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", - "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-webhook@0.7.1": "1n56r0zzwr6lyzga1d7wmqgw63kysn7vim3ghr9c591lql2v0gsd", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#k8s-version@0.1.3": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-certs@0.4.0": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-operator-derive@0.3.1": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-operator@0.100.3": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-shared@0.0.3": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-telemetry@0.6.1": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-versioned-macros@0.8.3": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-versioned@0.8.3": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", + "git+https://github.com/stackabletech//operator-rs.git?branch=feat%2Fmutating-webhook#stackable-webhook@0.7.1": "1950vy1q95nld8f33w62r5375177mkyrwl23im78xky0zad5f8bf", "git+https://github.com/stackabletech/product-config.git?tag=0.8.0#product-config@0.8.0": "1dz70kapm2wdqcr7ndyjji0lhsl98bsq95gnb2lw487wf6yr7987" } \ No newline at end of file diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index f4f0508..15833c7 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -15,6 +15,7 @@ anyhow.workspace = true clap.workspace = true http.workspace = true futures.workspace = true +json-patch.workspace = true serde.workspace = true serde_json.workspace = true snafu.workspace = true diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index ed05988..2d3df64 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -5,6 +5,7 @@ use anyhow::anyhow; use clap::Parser; use futures::{FutureExt, TryFutureExt}; +use restart_controller::statefulset::create_context; use stackable_operator::{ YamlSchema as _, cli::{Command, RunArguments}, @@ -19,6 +20,7 @@ use stackable_operator::{ use webhooks::create_webhook; mod restart_controller; +mod utils; mod webhooks; mod built_info { @@ -82,7 +84,19 @@ async fn main() -> anyhow::Result<()> { ) .await?; + let (ctx, cm_store_tx, secret_store_tx) = create_context(client.clone()); + let sts_restart_controller = restart_controller::statefulset::start( + ctx.clone(), + cm_store_tx, + secret_store_tx, + &watch_namespace, + ) + .map(anyhow::Ok); + let pod_restart_controller = + restart_controller::pod::start(&client, &watch_namespace).map(anyhow::Ok); + let webhook = create_webhook( + ctx, &operator_environment, // TODO: Make user configurable false, @@ -93,16 +107,11 @@ async fn main() -> anyhow::Result<()> { .run() .map_err(|err| anyhow!(err).context("failed to run webhook")); - let sts_restart_controller = - restart_controller::statefulset::start(&client, &watch_namespace).map(anyhow::Ok); - let pod_restart_controller = - restart_controller::pod::start(&client, &watch_namespace).map(anyhow::Ok); - futures::try_join!( sts_restart_controller, pod_restart_controller, + webhook, eos_checker, - webhook )?; } } diff --git a/rust/operator-binary/src/restart_controller/pod.rs b/rust/operator-binary/src/restart_controller/pod.rs index 9ceed1f..a20b277 100644 --- a/rust/operator-binary/src/restart_controller/pod.rs +++ b/rust/operator-binary/src/restart_controller/pod.rs @@ -42,7 +42,7 @@ enum Error { #[snafu(display( "failed to parse expiry timestamp annotation ({annotation:?}: {value:?}) as RFC 3999" ))] - UnparseableExpiryTimestamp { + UnparsableExpiryTimestamp { source: chrono::ParseError, annotation: String, value: String, @@ -60,7 +60,7 @@ impl ReconcilerError for Error { match self { Error::PodHasNoName => None, Error::PodHasNoNamespace => None, - Error::UnparseableExpiryTimestamp { + Error::UnparsableExpiryTimestamp { source: _, annotation: _, value: _, @@ -73,6 +73,8 @@ impl ReconcilerError for Error { pub async fn start(client: &Client, watch_namespace: &WatchNamespace) { let controller = Controller::new( watch_namespace.get_api::>(client), + // TODO: Can we only watch a subset of Pods with a specify label, e.g. + // vendor=Stackable to reduce the memory footprint? watcher::Config::default(), ); let event_recorder = Arc::new(Recorder::new( @@ -124,7 +126,7 @@ async fn reconcile(pod: Arc>, ctx: Arc) -> Result>, - cms_inited: Arc, - secrets: Store>, - secrets_inited: Arc, +pub struct Ctx { + client: Client, + cms: DelayedInit>>, + secrets: DelayedInit>>, } #[derive(Snafu, Debug, EnumDiscriminants)] #[strum_discriminants(derive(IntoStaticStr))] -enum Error { +pub enum Error { #[snafu(display("StatefulSet object is invalid"))] InvalidStatefulSet { source: error_boundary::InvalidObject, @@ -55,11 +51,11 @@ enum Error { obj_ref: Box>, }, - #[snafu(display("configmaps were not yet loaded"))] - ConfigMapsUninitialized, + #[snafu(display("configmap initializer was cancelled"))] + ConfigMapsUninitialized { source: InitDropped }, - #[snafu(display("secrets were not yet loaded"))] - SecretsUninitialized, + #[snafu(display("secrets initializer was cancelled"))] + SecretsUninitialized { source: InitDropped }, } impl ReconcilerError for Error { @@ -69,25 +65,49 @@ impl ReconcilerError for Error { fn secondary_object(&self) -> Option> { match self { - Error::InvalidStatefulSet { source: _ } => None, + Error::InvalidStatefulSet { .. } => None, Error::PatchFailed { obj_ref, .. } => Some(*obj_ref.clone()), - Error::ConfigMapsUninitialized => None, - Error::SecretsUninitialized => None, + Error::ConfigMapsUninitialized { .. } => None, + Error::SecretsUninitialized { .. } => None, } } } -pub async fn start(client: &Client, watch_namespace: &WatchNamespace) { - let stses = watch_namespace.get_api::>(client); - let cms = watch_namespace.get_api::(client); - let secrets = watch_namespace.get_api::(client); +pub fn create_context( + client: Client, +) -> ( + Arc, + Initializer>>, + Initializer>>, +) { + let (cm_store_tx, cm_store_delayed) = DelayedInit::new(); + let (secret_store_tx, secret_store_delayed) = DelayedInit::new(); + let ctx = Arc::new(Ctx { + client, + cms: cm_store_delayed, + secrets: secret_store_delayed, + }); + + (ctx, cm_store_tx, secret_store_tx) +} + +pub async fn start( + ctx: Arc, + cm_store_tx: Initializer>>, + secret_store_tx: Initializer>>, + watch_namespace: &WatchNamespace, +) { + let stses = watch_namespace.get_api::>(&ctx.client); + let cms = watch_namespace.get_api::(&ctx.client); + let secrets = watch_namespace.get_api::(&ctx.client); let sts_store = reflector::store::Writer::>::new(()); let cm_store = reflector::store::Writer::>::new(()); let secret_store = reflector::store::Writer::>::new(()); - let cms_inited = Arc::new(AtomicBool::from(false)); - let secrets_inited = Arc::new(AtomicBool::from(false)); + let mut cm_store_tx = Some(cm_store_tx); + let mut secret_store_tx = Some(secret_store_tx); + let ctx2 = ctx.clone(); let event_recorder = Arc::new(Recorder::new( - client.as_kube_client(), + ctx.client.as_kube_client(), Reporter { controller: FULL_CONTROLLER_NAME.to_string(), instance: None, @@ -97,29 +117,37 @@ pub async fn start(client: &Client, watch_namespace: &WatchNamespace) { applier( |sts, ctx| Box::pin(reconcile(sts, ctx)), error_policy, - Arc::new(Ctx { - kube: client.as_kube_client(), - cms: cm_store.as_reader(), - secrets: secret_store.as_reader(), - cms_inited: cms_inited.clone(), - secrets_inited: secrets_inited.clone(), - }), + ctx2, sts_store.as_reader(), stream::select( stream::select( trigger_all( - reflector(cm_store, metadata_watcher(cms, watcher::Config::default())) - .inspect(|_| cms_inited.store(true, std::sync::atomic::Ordering::SeqCst)) - .touched_objects(), + { + let cm_reader = cm_store.as_reader(); + reflector(cm_store, metadata_watcher(cms, watcher::Config::default())) + .inspect(move |_| { + if let Some(tx) = cm_store_tx.take() { + tx.init(cm_reader.clone()); + } + }) + .touched_objects() + }, sts_store.as_reader(), ), trigger_all( - reflector( - secret_store, - metadata_watcher(secrets, watcher::Config::default()), - ) - .inspect(|_| secrets_inited.store(true, std::sync::atomic::Ordering::SeqCst)) - .touched_objects(), + { + let secret_reader = secret_store.as_reader(); + reflector( + secret_store, + metadata_watcher(secrets, watcher::Config::default()), + ) + .inspect(move |_| { + if let Some(tx) = secret_store_tx.take() { + tx.init(secret_reader.clone()); + } + }) + .touched_objects() + }, sts_store.as_reader(), ), ), @@ -193,24 +221,10 @@ fn find_pod_refs<'a, K: Resource + 'a>( .chain(container_env_from_refs) } -async fn reconcile( - sts: Arc>, +pub async fn get_updated_restarter_annotations( + sts: &StatefulSet, ctx: Arc, -) -> Result { - tracing::info!("Starting reconcile"); - let sts = sts - .0 - .as_ref() - .map_err(error_boundary::InvalidObject::clone) - .context(InvalidStatefulSetSnafu)?; - - if !ctx.cms_inited.load(std::sync::atomic::Ordering::SeqCst) { - return ConfigMapsUninitializedSnafu.fail(); - } - if !ctx.secrets_inited.load(std::sync::atomic::Ordering::SeqCst) { - return SecretsUninitializedSnafu.fail(); - } - +) -> Result, Error> { let ns = sts.metadata.namespace.as_deref().unwrap(); let mut annotations = BTreeMap::::new(); let pod_specs = sts @@ -245,23 +259,20 @@ async fn reconcile( ) }) .map(|cm_ref| cm_ref.within(ns)); - annotations.extend( - cm_refs - .flat_map(|cm_ref| ctx.cms.get(&cm_ref)) - .flat_map(|cm| { - Some(( - format!( - "configmap.restarter.stackable.tech/{}", - cm.metadata.name.as_ref()? - ), - format!( - "{}/{}", - cm.metadata.uid.as_ref()?, - cm.metadata.resource_version.as_ref()? - ), - )) - }), - ); + let cms = ctx.cms.get().await.context(ConfigMapsUninitializedSnafu)?; + annotations.extend(cm_refs.flat_map(|cm_ref| cms.get(&cm_ref)).flat_map(|cm| { + Some(( + format!( + "configmap.restarter.stackable.tech/{}", + cm.metadata.name.as_ref()? + ), + format!( + "{}/{}", + cm.metadata.uid.as_ref()?, + cm.metadata.resource_version.as_ref()? + ), + )) + })); let secret_refs = pod_specs .flat_map(|pod_spec| { find_pod_refs( @@ -284,9 +295,10 @@ async fn reconcile( ) }) .map(|secret_ref| secret_ref.within(ns)); + let secrets = ctx.secrets.get().await.context(SecretsUninitializedSnafu)?; annotations.extend( secret_refs - .flat_map(|secret_ref| ctx.secrets.get(&secret_ref)) + .flat_map(|secret_ref| secrets.get(&secret_ref)) .flat_map(|cm| { Some(( format!( @@ -301,7 +313,22 @@ async fn reconcile( )) }), ); - let stses = kube::Api::::namespaced(ctx.kube.clone(), ns); + Ok(annotations) +} + +async fn reconcile( + sts: Arc>, + ctx: Arc, +) -> Result { + tracing::info!("Starting reconcile"); + let sts = sts + .0 + .as_ref() + .map_err(error_boundary::InvalidObject::clone) + .context(InvalidStatefulSetSnafu)?; + let ns = sts.metadata.namespace.as_deref().unwrap(); + + let stses = kube::Api::::namespaced(ctx.client.as_kube_client(), ns); stses .patch( &sts.name_unchecked(), @@ -323,7 +350,7 @@ async fn reconcile( "spec": { "template": { "metadata": { - "annotations": annotations, + "annotations": get_updated_restarter_annotations(&sts, ctx).await?, }, }, }, diff --git a/rust/operator-binary/src/utils/delayed_init.rs b/rust/operator-binary/src/utils/delayed_init.rs new file mode 100644 index 0000000..6cf56b1 --- /dev/null +++ b/rust/operator-binary/src/utils/delayed_init.rs @@ -0,0 +1,212 @@ +// use tokio::sync::RwLock; +#[cfg(test)] +use std::sync::RwLockWriteGuard; +use std::{fmt::Debug, sync::RwLock, task::Poll}; + +use futures::{Future, FutureExt, channel}; +use snafu::Snafu; +use tracing::trace; + +/// The sending counterpart to a [`DelayedInit`] +pub struct Initializer(channel::oneshot::Sender); +impl Initializer { + /// Sends `value` to the linked [`DelayedInit`]. + pub fn init(self, value: T) { + // oneshot::Sender::send fails if no recipients remain, this is not really a relevant + // case to signal for our use case + let _ = self.0.send(value); + } +} + +/// A value that must be initialized by an external writer +/// +/// Can be considered equivalent to a [`channel::oneshot`] channel, except for that +/// the value produced is retained for subsequent calls to [`Self::get`]. +pub struct DelayedInit { + state: RwLock>, + // A test-only hook to let us create artificial race conditions + #[cfg(test)] + #[allow(clippy::type_complexity)] + test_hook_start_of_slow_path: + Box>) + Send + Sync>, +} +enum ReceiverState { + Waiting(channel::oneshot::Receiver), + Ready(Result), +} +impl DelayedInit { + /// Returns an empty `DelayedInit` that has no value, along with a linked [`Initializer`] + pub fn new() -> (Initializer, Self) { + let (tx, rx) = channel::oneshot::channel(); + ( + Initializer(tx), + DelayedInit { + state: RwLock::new(ReceiverState::Waiting(rx)), + #[cfg(test)] + test_hook_start_of_slow_path: Box::new(|_| ()), + }, + ) + } +} +impl DelayedInit { + /// Wait for the value to be available and then return it + /// + /// Calling `get` again if a value has already been returned is guaranteed to return (a clone of) + /// the same value. + pub async fn get(&self) -> Result { + DelayedInitGet(self).await + } +} + +// Using a manually implemented future because we don't want to hold the lock across poll calls +// since that would mean that an unpolled writer would stall all other tasks from being able to poll it +struct DelayedInitGet<'a, T>(&'a DelayedInit); +impl<'a, T> Future for DelayedInitGet<'a, T> +where + T: Clone, +{ + type Output = Result; + + #[tracing::instrument(name = "DelayedInit::get", level = "trace", skip(self, cx))] + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let read_lock = self.0.state.read().unwrap(); + if let ReceiverState::Ready(v) = &*read_lock { + trace!("using fast path, value is already ready"); + Poll::Ready(v.clone()) + } else { + trace!("using slow path, need to wait for the channel"); + // IMPORTANT: Make sure that the optimistic read lock has been released already + drop(read_lock); + let mut state = self.0.state.write().unwrap(); + trace!("got write lock"); + #[cfg(test)] + (self.0.test_hook_start_of_slow_path)(&mut state); + match &mut *state { + ReceiverState::Waiting(rx) => { + trace!("channel still active, polling"); + if let Poll::Ready(value) = rx.poll_unpin(cx).map_err(|_| InitDropped) { + trace!("got value on slow path, memoizing"); + *state = ReceiverState::Ready(value.clone()); + Poll::Ready(value) + } else { + trace!("channel is still pending"); + Poll::Pending + } + } + ReceiverState::Ready(v) => { + trace!( + "slow path but value was already initialized, another writer already initialized" + ); + Poll::Ready(v.clone()) + } + } + } + } +} + +#[derive(Debug, Snafu, Clone, Copy, PartialEq, Eq)] +#[snafu(display("initializer was dropped before value was initialized"))] +pub struct InitDropped; + +#[cfg(test)] +mod tests { + use std::{ + sync::{Arc, Mutex}, + task::Poll, + }; + + use futures::{pin_mut, poll}; + + // use tracing::Level; + + // use tracing_subscriber::util::SubscriberInitExt; + use super::DelayedInit; + use crate::utils::delayed_init::ReceiverState; + + // fn setup_tracing() -> tracing::dispatcher::DefaultGuard { + // tracing_subscriber::fmt() + // .with_max_level(Level::TRACE) + // .with_test_writer() + // .finish() + // .set_default() + // } + + #[tokio::test] + async fn must_allow_single_reader() { + // let _tracing = setup_tracing(); + let (tx, rx) = DelayedInit::::new(); + let get1 = rx.get(); + pin_mut!(get1); + assert_eq!(poll!(get1.as_mut()), Poll::Pending); + tx.init(1); + assert_eq!(poll!(get1), Poll::Ready(Ok(1))); + } + + #[tokio::test] + async fn must_allow_concurrent_readers_while_waiting() { + // let _tracing = setup_tracing(); + let (tx, rx) = DelayedInit::::new(); + let get1 = rx.get(); + let get2 = rx.get(); + let get3 = rx.get(); + pin_mut!(get1, get2, get3); + assert_eq!(poll!(get1.as_mut()), Poll::Pending); + assert_eq!(poll!(get2.as_mut()), Poll::Pending); + assert_eq!(poll!(get3.as_mut()), Poll::Pending); + tx.init(1); + assert_eq!(poll!(get1), Poll::Ready(Ok(1))); + assert_eq!(poll!(get2), Poll::Ready(Ok(1))); + assert_eq!(poll!(get3), Poll::Ready(Ok(1))); + } + + #[tokio::test] + async fn must_allow_reading_after_init() { + // let _tracing = setup_tracing(); + let (tx, rx) = DelayedInit::::new(); + let get1 = rx.get(); + pin_mut!(get1); + assert_eq!(poll!(get1.as_mut()), Poll::Pending); + tx.init(1); + assert_eq!(poll!(get1), Poll::Ready(Ok(1))); + assert_eq!(rx.get().await, Ok(1)); + assert_eq!(rx.get().await, Ok(1)); + } + + #[tokio::test] + async fn must_allow_concurrent_readers_in_any_order() { + // let _tracing = setup_tracing(); + let (tx, rx) = DelayedInit::::new(); + let get1 = rx.get(); + let get2 = rx.get(); + let get3 = rx.get(); + pin_mut!(get1, get2, get3); + assert_eq!(poll!(get1.as_mut()), Poll::Pending); + assert_eq!(poll!(get2.as_mut()), Poll::Pending); + assert_eq!(poll!(get3.as_mut()), Poll::Pending); + tx.init(1); + assert_eq!(poll!(get3), Poll::Ready(Ok(1))); + assert_eq!(poll!(get2), Poll::Ready(Ok(1))); + assert_eq!(poll!(get1), Poll::Ready(Ok(1))); + } + + #[tokio::test] + async fn must_work_despite_writer_race() { + // let _tracing = setup_tracing(); + let (_tx, mut rx) = DelayedInit::::new(); + let slow_path_calls = Arc::new(Mutex::new(0)); + let slow_path_calls2 = slow_path_calls.clone(); + // This emulates two racing get() calls, where a fake get() memoizes a value while the true get() + // is waiting to upgrade its read lock to a write lock. + rx.test_hook_start_of_slow_path = Box::new(move |state| { + *slow_path_calls2.lock().unwrap() += 1; + **state = ReceiverState::Ready(Ok(1)); + }); + assert_eq!(rx.get().await, Ok(1)); + assert_eq!(rx.get().await, Ok(1)); + assert_eq!(rx.get().await, Ok(1)); + assert_eq!(*slow_path_calls.lock().unwrap(), 1); + } +} diff --git a/rust/operator-binary/src/utils/mod.rs b/rust/operator-binary/src/utils/mod.rs new file mode 100644 index 0000000..2e542e1 --- /dev/null +++ b/rust/operator-binary/src/utils/mod.rs @@ -0,0 +1 @@ +pub mod delayed_init; diff --git a/rust/operator-binary/src/webhooks.rs b/rust/operator-binary/src/webhooks.rs index 35d32d7..9d3ed60 100644 --- a/rust/operator-binary/src/webhooks.rs +++ b/rust/operator-binary/src/webhooks.rs @@ -1,5 +1,6 @@ -use std::collections::BTreeMap; +use std::{collections::BTreeMap, sync::Arc}; +use json_patch::{AddOperation, Patch, PatchOperation, jsonptr::PointerBuf}; use snafu::{ResultExt, Snafu}; use stackable_operator::{ builder::meta::ObjectMetaBuilder, @@ -22,7 +23,10 @@ use stackable_operator::{ webhook::{WebhookError, WebhookOptions, WebhookServer, servers::MutatingWebhookServer}, }; -use crate::{FIELD_MANAGER, OPERATOR_NAME}; +use crate::{ + FIELD_MANAGER, OPERATOR_NAME, + restart_controller::statefulset::{Ctx, get_updated_restarter_annotations}, +}; #[derive(Debug, Snafu)] pub enum Error { @@ -31,13 +35,15 @@ pub enum Error { } pub async fn create_webhook<'a>( + ctx: Arc, operator_environment: &'a OperatorEnvironmentOptions, disable_mutating_webhook_configuration_maintenance: bool, client: Client, ) -> Result { let mutating_webhook_server = MutatingWebhookServer::new( get_mutating_webhook_configuration(), - foo, + add_sts_restarter_annotation, + ctx, disable_mutating_webhook_configuration_maintenance, client, FIELD_MANAGER.to_owned(), @@ -90,9 +96,7 @@ fn get_mutating_webhook_configuration() -> MutatingWebhookConfiguration { // Worst case the annotations are missing cause a restart of Pod 0, basically the same // behavior which we had for years. // See https://github.com/stackabletech/commons-operator/issues/111 for details - // failure_policy: Some("Ignore".to_owned()), - // TEMP for testing - failure_policy: Some("Fail".to_owned()), + failure_policy: Some("Ignore".to_owned()), // It could be the case that other mutating webhooks add more ConfigMpa/Secret mounts, // in which case it would be nice if we detect that. reinvocation_policy: Some("IfNeeded".to_owned()), @@ -103,14 +107,68 @@ fn get_mutating_webhook_configuration() -> MutatingWebhookConfiguration { } } -fn foo(request: AdmissionRequest) -> AdmissionResponse { +async fn add_sts_restarter_annotation( + ctx: Arc, + request: AdmissionRequest, +) -> AdmissionResponse { let Some(sts) = &request.object else { return AdmissionResponse::invalid( "object (of type StatefulSet) missing - for operation CREATE it must be always present", ); }; - dbg!(&request); + let mut paths_to_be_created = vec![]; + let spec = sts.spec.as_ref(); + if spec.is_none() { + paths_to_be_created.push("/spec"); + } + let metadata = spec.and_then(|spec| spec.template.metadata.as_ref()); + if metadata.is_none() { + paths_to_be_created.push("/spec/template/metadata"); + } + let annotations = metadata.and_then(|metadata| metadata.annotations.as_ref()); + if annotations.is_none() { + paths_to_be_created.push("/spec/template/metadata/annotations"); + } + let create_paths = paths_to_be_created.into_iter().map(|path| { + PatchOperation::Add(AddOperation { + path: PointerBuf::parse(path).expect("hard-coded annotation paths are valid"), + value: serde_json::Value::Object(serde_json::Map::new()), + }) + }); + + let annotations = match get_updated_restarter_annotations(&sts, ctx).await { + Ok(annotations) => annotations, + Err(err) => { + return AdmissionResponse::invalid(format!( + "failed to get updated restarted annotations: {err:#}" + )); + } + }; + + let add_annotations = annotations.iter().map(|(k, v)| { + PatchOperation::Add(AddOperation { + path: PointerBuf::from_tokens([ + "spec", + "template", + "metadata", + "annotations", + // It's totally fine (and even expected) that the annotations contains slashes ("/"), + // as `PointerBuf::from_tokens` escapes them + k, + ]), + value: serde_json::Value::String(v.to_owned()), + }) + }); - AdmissionResponse::from(&request) + match AdmissionResponse::from(&request) + .with_patch(Patch(create_paths.chain(add_annotations).collect())) + { + Ok(response) => response, + Err(err) => { + return AdmissionResponse::invalid(format!( + "failed to add patch to AdmissionResponse: {err:#}" + )); + } + } } From 3f29772280f69d328baa98fd395f67310d40faae Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 18 Nov 2025 14:21:39 +0100 Subject: [PATCH 3/7] Add CLI flag to disable mutating webhook --- rust/operator-binary/src/main.rs | 38 ++++++++++---- rust/operator-binary/src/webhook/mod.rs | 50 +++++++++++++++++++ .../restarter_mutate_sts.rs} | 45 ++--------------- 3 files changed, 81 insertions(+), 52 deletions(-) create mode 100644 rust/operator-binary/src/webhook/mod.rs rename rust/operator-binary/src/{webhooks.rs => webhook/restarter_mutate_sts.rs} (77%) diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 2d3df64..bcddfc2 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -17,11 +17,11 @@ use stackable_operator::{ shared::yaml::SerializeOptions, telemetry::Tracing, }; -use webhooks::create_webhook; +use webhook::create_webhook; mod restart_controller; mod utils; -mod webhooks; +mod webhook; mod built_info { include!(concat!(env!("OUT_DIR"), "/built.rs")); @@ -34,7 +34,20 @@ pub const FIELD_MANAGER: &str = "commons-operator"; #[clap(about, author)] struct Opts { #[clap(subcommand)] - cmd: Command, + cmd: Command, +} + +#[derive(Debug, PartialEq, Eq, Parser)] +pub struct CommonsOperatorRunArguments { + #[command(flatten)] + pub common: RunArguments, + + /// Don't start the controller mutating webhook and maintain the MutatingWebhookConfiguration. + /// + /// The mutating webhook is used to prevent an unneeded restart of the first Pod of freshly + /// created StatefulSets. It can be turned off in case you can accept an unneeded Pod restart. + #[arg(long, env)] + pub disable_restarter_mutating_webhook: bool, } #[tokio::main] @@ -49,12 +62,16 @@ async fn main() -> anyhow::Result<()> { S3Bucket::merged_crd(S3BucketVersion::V1Alpha1)? .print_yaml_schema(built_info::PKG_VERSION, SerializeOptions::default())?; } - Command::Run(RunArguments { - product_config: _, - watch_namespace, - operator_environment, - maintenance, - common, + Command::Run(CommonsOperatorRunArguments { + common: + RunArguments { + product_config: _, + watch_namespace, + operator_environment, + maintenance, + common, + }, + disable_restarter_mutating_webhook, }) => { // NOTE (@NickLarsenNZ): Before stackable-telemetry was used: // - The console log level was set by `COMMONS_OPERATOR_LOG`, and is now `CONSOLE_LOG` (when using Tracing::pre_configured). @@ -98,8 +115,7 @@ async fn main() -> anyhow::Result<()> { let webhook = create_webhook( ctx, &operator_environment, - // TODO: Make user configurable - false, + disable_restarter_mutating_webhook, client.as_kube_client(), ) .await?; diff --git a/rust/operator-binary/src/webhook/mod.rs b/rust/operator-binary/src/webhook/mod.rs new file mode 100644 index 0000000..863145f --- /dev/null +++ b/rust/operator-binary/src/webhook/mod.rs @@ -0,0 +1,50 @@ +use std::sync::Arc; + +use restarter_mutate_sts::{add_sts_restarter_annotation, get_mutating_webhook_configuration}; +use snafu::{ResultExt, Snafu}; +use stackable_operator::{ + cli::OperatorEnvironmentOptions, + kube::Client, + webhook::{ + WebhookError, WebhookOptions, WebhookServer, + servers::{MutatingWebhookServer, WebhookServerImplementation}, + }, +}; + +use crate::{FIELD_MANAGER, restart_controller::statefulset::Ctx}; + +mod restarter_mutate_sts; + +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display("failed to create webhook server"))] + CreateWebhookServer { source: WebhookError }, +} + +pub async fn create_webhook<'a>( + ctx: Arc, + operator_environment: &'a OperatorEnvironmentOptions, + disable_restarter_mutating_webhook: bool, + client: Client, +) -> Result { + let mut webhooks: Vec> = vec![]; + if !disable_restarter_mutating_webhook { + webhooks.push(Box::new(MutatingWebhookServer::new( + get_mutating_webhook_configuration(), + add_sts_restarter_annotation, + ctx, + disable_restarter_mutating_webhook, + client, + FIELD_MANAGER.to_owned(), + ))); + } + + let webhook_options = WebhookOptions { + socket_addr: WebhookServer::DEFAULT_SOCKET_ADDRESS, + operator_namespace: operator_environment.operator_namespace.to_owned(), + operator_service_name: operator_environment.operator_service_name.to_owned(), + }; + WebhookServer::new(webhook_options, webhooks) + .await + .context(CreateWebhookServerSnafu) +} diff --git a/rust/operator-binary/src/webhooks.rs b/rust/operator-binary/src/webhook/restarter_mutate_sts.rs similarity index 77% rename from rust/operator-binary/src/webhooks.rs rename to rust/operator-binary/src/webhook/restarter_mutate_sts.rs index 9d3ed60..6fd1f4f 100644 --- a/rust/operator-binary/src/webhooks.rs +++ b/rust/operator-binary/src/webhook/restarter_mutate_sts.rs @@ -1,10 +1,8 @@ use std::{collections::BTreeMap, sync::Arc}; use json_patch::{AddOperation, Patch, PatchOperation, jsonptr::PointerBuf}; -use snafu::{ResultExt, Snafu}; use stackable_operator::{ builder::meta::ObjectMetaBuilder, - cli::OperatorEnvironmentOptions, k8s_openapi::{ api::{ admissionregistration::v1::{ @@ -15,51 +13,16 @@ use stackable_operator::{ }, apimachinery::pkg::apis::meta::v1::LabelSelector, }, - kube::{ - Client, - core::admission::{AdmissionRequest, AdmissionResponse}, - }, + kube::core::admission::{AdmissionRequest, AdmissionResponse}, kvp::Label, - webhook::{WebhookError, WebhookOptions, WebhookServer, servers::MutatingWebhookServer}, }; use crate::{ - FIELD_MANAGER, OPERATOR_NAME, + OPERATOR_NAME, restart_controller::statefulset::{Ctx, get_updated_restarter_annotations}, }; -#[derive(Debug, Snafu)] -pub enum Error { - #[snafu(display("failed to create webhook server"))] - CreateWebhookServer { source: WebhookError }, -} - -pub async fn create_webhook<'a>( - ctx: Arc, - operator_environment: &'a OperatorEnvironmentOptions, - disable_mutating_webhook_configuration_maintenance: bool, - client: Client, -) -> Result { - let mutating_webhook_server = MutatingWebhookServer::new( - get_mutating_webhook_configuration(), - add_sts_restarter_annotation, - ctx, - disable_mutating_webhook_configuration_maintenance, - client, - FIELD_MANAGER.to_owned(), - ); - - let webhook_options = WebhookOptions { - socket_addr: WebhookServer::DEFAULT_SOCKET_ADDRESS, - operator_namespace: operator_environment.operator_namespace.to_owned(), - operator_service_name: operator_environment.operator_service_name.to_owned(), - }; - WebhookServer::new(webhook_options, vec![Box::new(mutating_webhook_server)]) - .await - .context(CreateWebhookServerSnafu) -} - -fn get_mutating_webhook_configuration() -> MutatingWebhookConfiguration { +pub fn get_mutating_webhook_configuration() -> MutatingWebhookConfiguration { let webhook_name = "restarter-sts-enricher.stackable.tech"; let metadata = ObjectMetaBuilder::new() .name(webhook_name) @@ -107,7 +70,7 @@ fn get_mutating_webhook_configuration() -> MutatingWebhookConfiguration { } } -async fn add_sts_restarter_annotation( +pub async fn add_sts_restarter_annotation( ctx: Arc, request: AdmissionRequest, ) -> AdmissionResponse { From d4dc4fd3fcf8a1d1466a19ad8dfbcb8ba2409668 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 18 Nov 2025 15:50:11 +0100 Subject: [PATCH 4/7] Rename function --- rust/operator-binary/src/main.rs | 8 ++++---- rust/operator-binary/src/webhook/mod.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index bcddfc2..4e7fa4b 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -17,7 +17,7 @@ use stackable_operator::{ shared::yaml::SerializeOptions, telemetry::Tracing, }; -use webhook::create_webhook; +use webhook::create_webhook_server; mod restart_controller; mod utils; @@ -112,21 +112,21 @@ async fn main() -> anyhow::Result<()> { let pod_restart_controller = restart_controller::pod::start(&client, &watch_namespace).map(anyhow::Ok); - let webhook = create_webhook( + let webhook_server = create_webhook_server( ctx, &operator_environment, disable_restarter_mutating_webhook, client.as_kube_client(), ) .await?; - let webhook = webhook + let webhook_server = webhook_server .run() .map_err(|err| anyhow!(err).context("failed to run webhook")); futures::try_join!( sts_restart_controller, pod_restart_controller, - webhook, + webhook_server, eos_checker, )?; } diff --git a/rust/operator-binary/src/webhook/mod.rs b/rust/operator-binary/src/webhook/mod.rs index 863145f..abc7b5d 100644 --- a/rust/operator-binary/src/webhook/mod.rs +++ b/rust/operator-binary/src/webhook/mod.rs @@ -21,7 +21,7 @@ pub enum Error { CreateWebhookServer { source: WebhookError }, } -pub async fn create_webhook<'a>( +pub async fn create_webhook_server<'a>( ctx: Arc, operator_environment: &'a OperatorEnvironmentOptions, disable_restarter_mutating_webhook: bool, From 64d643765477a3bfc965a9b90e81820423e1f284 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 18 Nov 2025 15:51:28 +0100 Subject: [PATCH 5/7] clippy lints --- rust/operator-binary/src/restart_controller/statefulset.rs | 3 ++- rust/operator-binary/src/webhook/mod.rs | 4 ++-- rust/operator-binary/src/webhook/restarter_mutate_sts.rs | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/rust/operator-binary/src/restart_controller/statefulset.rs b/rust/operator-binary/src/restart_controller/statefulset.rs index 2dea0c8..03b50bf 100644 --- a/rust/operator-binary/src/restart_controller/statefulset.rs +++ b/rust/operator-binary/src/restart_controller/statefulset.rs @@ -73,6 +73,7 @@ impl ReconcilerError for Error { } } +#[allow(clippy::type_complexity)] pub fn create_context( client: Client, ) -> ( @@ -350,7 +351,7 @@ async fn reconcile( "spec": { "template": { "metadata": { - "annotations": get_updated_restarter_annotations(&sts, ctx).await?, + "annotations": get_updated_restarter_annotations(sts, ctx).await?, }, }, }, diff --git a/rust/operator-binary/src/webhook/mod.rs b/rust/operator-binary/src/webhook/mod.rs index abc7b5d..9ba5798 100644 --- a/rust/operator-binary/src/webhook/mod.rs +++ b/rust/operator-binary/src/webhook/mod.rs @@ -21,9 +21,9 @@ pub enum Error { CreateWebhookServer { source: WebhookError }, } -pub async fn create_webhook_server<'a>( +pub async fn create_webhook_server( ctx: Arc, - operator_environment: &'a OperatorEnvironmentOptions, + operator_environment: &OperatorEnvironmentOptions, disable_restarter_mutating_webhook: bool, client: Client, ) -> Result { diff --git a/rust/operator-binary/src/webhook/restarter_mutate_sts.rs b/rust/operator-binary/src/webhook/restarter_mutate_sts.rs index 6fd1f4f..3cde9d7 100644 --- a/rust/operator-binary/src/webhook/restarter_mutate_sts.rs +++ b/rust/operator-binary/src/webhook/restarter_mutate_sts.rs @@ -100,7 +100,7 @@ pub async fn add_sts_restarter_annotation( }) }); - let annotations = match get_updated_restarter_annotations(&sts, ctx).await { + let annotations = match get_updated_restarter_annotations(sts, ctx).await { Ok(annotations) => annotations, Err(err) => { return AdmissionResponse::invalid(format!( @@ -129,9 +129,9 @@ pub async fn add_sts_restarter_annotation( { Ok(response) => response, Err(err) => { - return AdmissionResponse::invalid(format!( + AdmissionResponse::invalid(format!( "failed to add patch to AdmissionResponse: {err:#}" - )); + )) } } } From c5a0200b0119e315ebd063203e88e1fb084eaccb Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 18 Nov 2025 15:52:05 +0100 Subject: [PATCH 6/7] cargo fmt --- rust/operator-binary/src/webhook/restarter_mutate_sts.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rust/operator-binary/src/webhook/restarter_mutate_sts.rs b/rust/operator-binary/src/webhook/restarter_mutate_sts.rs index 3cde9d7..e8b79d4 100644 --- a/rust/operator-binary/src/webhook/restarter_mutate_sts.rs +++ b/rust/operator-binary/src/webhook/restarter_mutate_sts.rs @@ -129,9 +129,7 @@ pub async fn add_sts_restarter_annotation( { Ok(response) => response, Err(err) => { - AdmissionResponse::invalid(format!( - "failed to add patch to AdmissionResponse: {err:#}" - )) + AdmissionResponse::invalid(format!("failed to add patch to AdmissionResponse: {err:#}")) } } } From ab362fedac93a38767e63dae38369b8c23e9ca48 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 18 Nov 2025 16:13:03 +0100 Subject: [PATCH 7/7] Make YAML nicer --- _TEST.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/_TEST.yaml b/_TEST.yaml index b894716..7a4b2ee 100644 --- a/_TEST.yaml +++ b/_TEST.yaml @@ -49,14 +49,14 @@ spec: - name: nginx image: registry.k8s.io/nginx-slim:0.24 ports: - - containerPort: 80 - name: web + - containerPort: 80 + name: web volumeMounts: - - name: config - mountPath: "/config" + - name: config + mountPath: "/config" envFrom: - - configMapRef: - name: web-config-2 + - configMapRef: + name: web-config-2 volumes: - name: config configMap: