From 1bb5d6a78dbf2ef1a8c830a77219dfabfd53795f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 28 Jun 2022 09:18:36 +0200 Subject: [PATCH 01/99] Initial NodePort-only PoC --- .gitignore | 4 + .gitmodules | 3 + Cargo.lock | 2508 +++++++++++++++++ Cargo.toml | 6 + Tiltfile | 33 + default.nix | 53 + deploy/helm/lb-operator/.helmignore | 28 + deploy/helm/lb-operator/Chart.yaml | 10 + deploy/helm/lb-operator/README.md | 27 + deploy/helm/lb-operator/crds/crds.yaml | 84 + .../helm/lb-operator/templates/_helpers.tpl | 76 + .../helm/lb-operator/templates/configmap.yaml | 9 + .../helm/lb-operator/templates/csidriver.yaml | 12 + .../helm/lb-operator/templates/daemonset.yaml | 90 + .../lb-operator/templates/deployment.yaml | 1 + deploy/helm/lb-operator/templates/roles.yaml | 59 + .../lb-operator/templates/serviceaccount.yaml | 29 + .../lb-operator/templates/storageclass.yaml | 7 + deploy/helm/lb-operator/values.yaml | 52 + examples/nginx.yaml | 34 + rust/lb-operator/Cargo.toml | 27 + rust/lb-operator/build.rs | 11 + rust/lb-operator/src/csi_server/controller.rs | 129 + rust/lb-operator/src/csi_server/identity.rs | 55 + rust/lb-operator/src/csi_server/mod.rs | 3 + rust/lb-operator/src/csi_server/node.rs | 165 ++ rust/lb-operator/src/grpc.rs | 10 + rust/lb-operator/src/main.rs | 84 + rust/lb-operator/src/utils.rs | 138 + rust/lb-operator/vendor/csi | 1 + 30 files changed, 3748 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Tiltfile create mode 100644 default.nix create mode 100644 deploy/helm/lb-operator/.helmignore create mode 100644 deploy/helm/lb-operator/Chart.yaml create mode 100644 deploy/helm/lb-operator/README.md create mode 100644 deploy/helm/lb-operator/crds/crds.yaml create mode 100644 deploy/helm/lb-operator/templates/_helpers.tpl create mode 100644 deploy/helm/lb-operator/templates/configmap.yaml create mode 100644 deploy/helm/lb-operator/templates/csidriver.yaml create mode 100644 deploy/helm/lb-operator/templates/daemonset.yaml create mode 100644 deploy/helm/lb-operator/templates/deployment.yaml create mode 100644 deploy/helm/lb-operator/templates/roles.yaml create mode 100644 deploy/helm/lb-operator/templates/serviceaccount.yaml create mode 100644 deploy/helm/lb-operator/templates/storageclass.yaml create mode 100644 deploy/helm/lb-operator/values.yaml create mode 100644 examples/nginx.yaml create mode 100644 rust/lb-operator/Cargo.toml create mode 100644 rust/lb-operator/build.rs create mode 100644 rust/lb-operator/src/csi_server/controller.rs create mode 100644 rust/lb-operator/src/csi_server/identity.rs create mode 100644 rust/lb-operator/src/csi_server/mod.rs create mode 100644 rust/lb-operator/src/csi_server/node.rs create mode 100644 rust/lb-operator/src/grpc.rs create mode 100644 rust/lb-operator/src/main.rs create mode 100644 rust/lb-operator/src/utils.rs create mode 160000 rust/lb-operator/vendor/csi diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..52d87385 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +/result +Cargo.nix +crate-hashes.json diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..2a810051 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "rust/lb-operator/vendor/csi"] + path = rust/lb-operator/vendor/csi + url = https://github.com/container-storage-interface/spec diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..1872f422 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2508 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-trait" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "axum" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc47084705629d09d15060d70a8dbfce479c842303d05929ce29c74c995916ae" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa 1.0.2", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde", + "sync_wrapper", + "tokio", + "tower", + "tower-http 0.3.4", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2efed1c501becea07ce48118786ebcf229531d0d3b28edf224a720020d9e106" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", +] + +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "getrandom", + "instant", + "rand", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bit-set" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "serde", + "winapi", +] + +[[package]] +name = "clap" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "cmake" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +dependencies = [ + "cc", +] + +[[package]] +name = "const_format" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6a1316fa6a23fea1ee41cb80321590385e5f3e575e99f77c4d918ce5d44379d" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef196d5d972878a48da7decb7686eded338b4858fbabeed513d63a7c98b2b82d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + +[[package]] +name = "darling" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" +dependencies = [ + "darling_core 0.14.1", + "darling_macro 0.14.1", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core 0.13.4", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" +dependencies = [ + "darling_core 0.14.1", + "quote", + "syn", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dyn-clone" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +dependencies = [ + "encoding-index-japanese", + "encoding-index-korean", + "encoding-index-simpchinese", + "encoding-index-singlebyte", + "encoding-index-tradchinese", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" + +[[package]] +name = "fancy-regex" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95b4efe5be9104a4a18a9916e86654319895138be727b229820c39257c30dda" +dependencies = [ + "bit-set", + "regex", +] + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "fixedbitset" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "h2" +version = "0.3.7" +source = "git+https://github.com/stackabletech/h2.git?branch=feature/grpc-uds#b7554e1b8730af5fbb7fc1841d92f9247c4e477c" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util 0.6.10", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.2", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + +[[package]] +name = "httparse" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 0.4.8", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-openssl" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ee5d7a8f718585d1c3c61dfde28ef5b0bb14734b4db13f5ada856cdc6c612b" +dependencies = [ + "http", + "hyper", + "linked_hash_set", + "once_cell", + "openssl", + "openssl-sys", + "parking_lot", + "tokio", + "tokio-openssl", + "tower-layer", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-encoding" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e85a1509a128c855368e135cffcde7eac17d8e1083f41e2b98c58bc1a5074be" + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" + +[[package]] +name = "java-properties" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1904d8654a1ef51034d02d5a9411b50bf91bea15b0ab644ae179d1325976263" +dependencies = [ + "encoding", + "lazy_static", + "regex", +] + +[[package]] +name = "js-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json-patch" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f995a3c8f2bc3dd52a18a583e90f9ec109c047fa1603a853e46bcda14d2e279d" +dependencies = [ + "serde", + "serde_json", + "treediff", +] + +[[package]] +name = "jsonpath_lib" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" +dependencies = [ + "log", + "serde", + "serde_json", +] + +[[package]] +name = "k8s-openapi" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0489fc937cc7616a9abfa61bf39c250d7e32e1325ef028c8d9278dd24ea395b3" +dependencies = [ + "base64", + "bytes", + "chrono", + "schemars", + "serde", + "serde-value", + "serde_json", +] + +[[package]] +name = "kube" +version = "0.71.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342744dfeb81fe186b84f485b33f12c6a15d3396987d933b06a566a3db52ca38" +dependencies = [ + "k8s-openapi", + "kube-client", + "kube-core", + "kube-derive", + "kube-runtime", +] + +[[package]] +name = "kube-client" +version = "0.71.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f69a504997799340408635d6e351afb8aab2c34ca3165e162f41b3b34a69a79" +dependencies = [ + "base64", + "bytes", + "chrono", + "dirs-next", + "either", + "futures", + "http", + "http-body", + "hyper", + "hyper-openssl", + "hyper-timeout", + "hyper-tls", + "jsonpath_lib", + "k8s-openapi", + "kube-core", + "openssl", + "pem", + "pin-project", + "secrecy", + "serde", + "serde_json", + "serde_yaml", + "thiserror", + "tokio", + "tokio-native-tls", + "tokio-util 0.7.3", + "tower", + "tower-http 0.2.5", + "tracing", +] + +[[package]] +name = "kube-core" +version = "0.71.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a247487699941baaf93438d65b12d4e32450bea849d619d19ed394e8a4a645" +dependencies = [ + "chrono", + "form_urlencoded", + "http", + "json-patch", + "k8s-openapi", + "once_cell", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "kube-derive" +version = "0.71.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "203f7c5acf9d0dfb0b08d44ec1d66ace3d1dfe0cdd82e65e274f3f96615d666c" +dependencies = [ + "darling 0.13.4", + "proc-macro2", + "quote", + "serde_json", + "syn", +] + +[[package]] +name = "kube-runtime" +version = "0.71.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02ea50e6ed56578e1d1d02548901b12fe6d3edbf110269a396955e285d487973" +dependencies = [ + "ahash", + "backoff", + "derivative", + "futures", + "json-patch", + "k8s-openapi", + "kube-client", + "parking_lot", + "pin-project", + "serde", + "serde_json", + "smallvec", + "thiserror", + "tokio", + "tokio-util 0.7.3", + "tracing", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "linked_hash_set" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "matchit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mio" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + +[[package]] +name = "openssl" +version = "0.10.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "opentelemetry" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8" +dependencies = [ + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "js-sys", + "lazy_static", + "percent-encoding", + "pin-project", + "rand", + "thiserror", + "tokio", + "tokio-stream", +] + +[[package]] +name = "opentelemetry-jaeger" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c0b12cd9e3f9b35b52f6e0dac66866c519b26f424f4bbf96e3fe8bfbdc5229" +dependencies = [ + "async-trait", + "lazy_static", + "opentelemetry", + "opentelemetry-semantic-conventions", + "thiserror", + "thrift", + "tokio", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985cc35d832d412224b2cffe2f9194b1b89b6aa5d0bef76d080dce09d90e62bd" +dependencies = [ + "opentelemetry", +] + +[[package]] +name = "ordered-float" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits", +] + +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pem" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" +dependencies = [ + "base64", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "petgraph" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "prettyplease" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28f53e8b192565862cf99343194579a022eb9c7dd3a8d03134734803c7b3125" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "product-config" +version = "0.4.0" +source = "git+https://github.com/stackabletech/product-config.git?tag=0.4.0#e1e5938b4f6120f85a088194e86d22433fdba731" +dependencies = [ + "fancy-regex", + "java-properties", + "schemars", + "semver", + "serde", + "serde_json", + "serde_yaml", + "thiserror", + "xml-rs", +] + +[[package]] +name = "prost" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab" +dependencies = [ + "bytes", + "cfg-if", + "cmake", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prost", + "prost-types", + "regex", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" +dependencies = [ + "bytes", + "prost", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[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", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + +[[package]] +name = "ryu" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static", + "windows-sys", +] + +[[package]] +name = "schemars" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b5a3c80cea1ab61f4260238409510e814e38b4b563c06044edf91e7dc070e3" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ae4dce13e8614c46ac3c38ef1c0d668b101df6ac39817aebdaa26642ddae9b" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" + +[[package]] +name = "serde" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float 2.10.0", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +dependencies = [ + "indexmap", + "itoa 1.0.2", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc" +dependencies = [ + "indexmap", + "ryu", + "serde", + "yaml-rust", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "stackable-lb-operator" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "futures", + "h2", + "libc", + "pin-project", + "prost", + "prost-types", + "socket2", + "stackable-operator", + "tokio", + "tokio-stream", + "tonic", + "tonic-build", + "tonic-reflection", +] + +[[package]] +name = "stackable-operator" +version = "0.21.1" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.21.1#01b0aa2069580b9f2088a4409a63436f9917004b" +dependencies = [ + "backoff", + "chrono", + "clap", + "const_format", + "derivative", + "either", + "futures", + "json-patch", + "k8s-openapi", + "kube", + "lazy_static", + "opentelemetry", + "opentelemetry-jaeger", + "product-config", + "rand", + "regex", + "schemars", + "serde", + "serde_json", + "serde_yaml", + "stackable-operator-derive", + "strum", + "thiserror", + "tokio", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", +] + +[[package]] +name = "stackable-operator-derive" +version = "0.21.1" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.21.1#01b0aa2069580b9f2088a4409a63436f9917004b" +dependencies = [ + "darling 0.14.1", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "thiserror" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "thrift" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b82ca8f46f95b3ce96081fe3dd89160fdea970c254bb72925255d1b62aae692e" +dependencies = [ + "byteorder", + "integer-encoding", + "log", + "ordered-float 1.1.1", + "threadpool", +] + +[[package]] +name = "tokio" +version = "1.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-openssl" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08f9ffb7809f1b20c1b398d92acf4cc719874b3b2b2d9ea2f09b4a80350878a" +dependencies = [ + "futures-util", + "openssl", + "openssl-sys", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "slab", + "tokio", + "tracing", +] + +[[package]] +name = "tonic" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9d60db39854b30b835107500cf0aca0b0d14d6e1c3de124217c23a29c2ddb" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "prost-derive", + "tokio", + "tokio-stream", + "tokio-util 0.7.3", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tonic-build" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9263bf4c9bfaae7317c1c2faf7f18491d2fe476f70c414b73bf5d445b00ffa1" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "quote", + "syn", +] + +[[package]] +name = "tonic-reflection" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1d786fcf313b48f1aac280142eae249f3c03495355c7906aa49872a41955015" +dependencies = [ + "bytes", + "prost", + "prost-types", + "tokio", + "tokio-stream", + "tonic", + "tonic-build", +] + +[[package]] +name = "tower" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util 0.7.3", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" +dependencies = [ + "base64", + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-opentelemetry" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93600c803bb15e2a32bd376001b8625587f268fe887669b5ac86af524637c242" +dependencies = [ + "once_cell", + "opentelemetry", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "treediff" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "761e8d5ad7ce14bb82b7e61ccc0ca961005a275a060b9644a2431aa11553c2ff" +dependencies = [ + "serde_json", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + +[[package]] +name = "unicode-xid" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" + +[[package]] +name = "which" +version = "4.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +dependencies = [ + "either", + "lazy_static", + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "zeroize" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..bcc6da07 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = ["rust/lb-operator"] + +[patch.crates-io] +# Workaround for https://github.com/hyperium/tonic/issues/243 +h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } \ No newline at end of file diff --git a/Tiltfile b/Tiltfile new file mode 100644 index 00000000..d1a571c4 --- /dev/null +++ b/Tiltfile @@ -0,0 +1,33 @@ +default_registry('docker.stackable.tech') + +custom_build( + 'docker.stackable.tech/teozkr/lb-operator', + 'nix run -f . crate2nix generate && nix-build . -A docker --arg dockerTag null --argstr dockerRegistry k3d-registry.localhost:11337 && ./result/load-image | docker load', + deps=['rust', 'Cargo.toml', 'Cargo.lock', 'default.nix', 'build.rs', 'vendor'], + # ignore=['result*', 'Cargo.nix', 'target', *.yaml], + outputs_image_ref_to='result/ref', +) + +# Load the latest CRDs from Nix +watch_file('result') +if os.path.exists('result'): + k8s_yaml('result/crds.yaml') + +# Exclude stale CRDs from Helm chart, and apply the rest +helm_crds, helm_non_crds = filter_yaml( + helm( + 'deploy/helm/lb-operator', + name='lb-operator', + set=[ + 'image.repository=docker.stackable.tech/teozkr/lb-operator', + ], + ), + api_version = "^apiextensions\\.k8s\\.io/.*$", + kind = "^CustomResourceDefinition$", +) +k8s_yaml(helm_non_crds) + +# Load examples +k8s_yaml('examples/nginx.yaml') +# k8s_yaml('examples/simple-consumer-nginx.yaml') +# k8s_yaml('examples/simple-consumer-shell.yaml') diff --git a/default.nix b/default.nix new file mode 100644 index 00000000..c6b97f0a --- /dev/null +++ b/default.nix @@ -0,0 +1,53 @@ +{ nixpkgs ? +, pkgs ? import nixpkgs {} +, cargo ? import ./Cargo.nix { + inherit nixpkgs pkgs; release = false; + defaultCrateOverrides = pkgs.defaultCrateOverrides // { + prost-build = attrs: { + buildInputs = [ pkgs.protobuf ]; + }; + tonic-reflection = attrs: { + buildInputs = [ pkgs.rustfmt ]; + }; + stackable-lb-operator = attrs: { + buildInputs = [ pkgs.rustfmt ]; + }; + }; + } +, dockerRegistry ? "docker.stackable.tech" +, dockerRepo ? "${dockerRegistry}/teozkr/lb-operator" +, dockerTag ? "latest" +}: +rec { + build = cargo.rootCrate.build; + crds = pkgs.runCommand "lb-provisioner-crds.yaml" {} + '' + ${build}/bin/stackable-lb-operator crd > $out + ''; + + dockerImage = pkgs.dockerTools.streamLayeredImage { + name = dockerRepo; + tag = dockerTag; + contents = [ pkgs.bashInteractive pkgs.coreutils pkgs.util-linuxMinimal ]; + config = { + Cmd = [ (build+"/bin/stackable-lb-operator") "run" ]; + }; + }; + docker = pkgs.linkFarm "lb-provisioner-docker" [ + { + name = "load-image"; + path = dockerImage; + } + { + name = "ref"; + path = pkgs.writeText "${dockerImage.name}-image-tag" "${dockerImage.imageName}:${dockerImage.imageTag}"; + } + { + name = "crds.yaml"; + path = crds; + } + ]; + + crate2nix = pkgs.crate2nix; + tilt = pkgs.tilt; +} diff --git a/deploy/helm/lb-operator/.helmignore b/deploy/helm/lb-operator/.helmignore new file mode 100644 index 00000000..fef44b7e --- /dev/null +++ b/deploy/helm/lb-operator/.helmignore @@ -0,0 +1,28 @@ +# ============= +# This file is automatically generated from the templates in stackabletech/operator-templating +# DON'T MANUALLY EDIT THIS FILE +# ============= + +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deploy/helm/lb-operator/Chart.yaml b/deploy/helm/lb-operator/Chart.yaml new file mode 100644 index 00000000..26875c20 --- /dev/null +++ b/deploy/helm/lb-operator/Chart.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v2 +name: lb-operator +version: 0.5.0-nightly +appVersion: "0.5.0-nightly" +description: The Stackable Operator for Stackable Load Balancing Operator +home: https://github.com/stackabletech/lb-operator +maintainers: + - name: Stackable + url: https://www.stackable.tech diff --git a/deploy/helm/lb-operator/README.md b/deploy/helm/lb-operator/README.md new file mode 100644 index 00000000..adfad90f --- /dev/null +++ b/deploy/helm/lb-operator/README.md @@ -0,0 +1,27 @@ +# Helm Chart for Stackable Operator for Stackable Load Balancer Operator + +This Helm Chart can be used to install Custom Resource Definitions and the Operator for Stackable Load Balancer Operator. + +## Requirements + +- Create a [Kubernetes Cluster](../Readme.md) +- Install [Helm](https://helm.sh/docs/intro/install/) + +## Install the Stackable Operator for Stackable Secret Operator + +```bash +# From the root of the operator repository +make compile-chart + +helm install lb-operator deploy/helm/lb-operator +``` + +## Usage of the CRDs + +The usage of this operator and its CRDs is described in the [documentation](https://docs.stackable.tech/lb-operator/index.html) + +The operator has example requests included in the [`/examples`](https://github.com/stackabletech/lb-operator/tree/main/examples) directory. + +## Links + +https://github.com/stackabletech/lb-operator diff --git a/deploy/helm/lb-operator/crds/crds.yaml b/deploy/helm/lb-operator/crds/crds.yaml new file mode 100644 index 00000000..46c56932 --- /dev/null +++ b/deploy/helm/lb-operator/crds/crds.yaml @@ -0,0 +1,84 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: secretclasses.secrets.stackable.tech + annotations: + helm.sh/resource-policy: keep +spec: + group: secrets.stackable.tech + names: + categories: [] + kind: SecretClass + plural: secretclasses + shortNames: [] + singular: secretclass + scope: Cluster + versions: + - additionalPrinterColumns: [] + name: v1alpha1 + schema: + openAPIV3Schema: + description: "Auto-generated derived type for SecretClassSpec via `CustomResource`" + properties: + spec: + properties: + backend: + oneOf: + - required: + - k8sSearch + - required: + - autoTls + properties: + autoTls: + properties: + ca: + properties: + autoGenerate: + default: false + description: Whether a new certificate authority should be generated if it does not already exist + type: boolean + secret: + description: SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace + properties: + name: + description: Name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret name must be unique. + type: string + type: object + required: + - secret + type: object + required: + - ca + type: object + k8sSearch: + properties: + searchNamespace: + oneOf: + - required: + - pod + - required: + - name + properties: + name: + type: string + pod: + type: object + type: object + required: + - searchNamespace + type: object + type: object + required: + - backend + type: object + required: + - spec + title: SecretClass + type: object + served: true + storage: true + subresources: {} diff --git a/deploy/helm/lb-operator/templates/_helpers.tpl b/deploy/helm/lb-operator/templates/_helpers.tpl new file mode 100644 index 00000000..a2258b27 --- /dev/null +++ b/deploy/helm/lb-operator/templates/_helpers.tpl @@ -0,0 +1,76 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-operator" }} +{{- end }} + +{{/* +Expand the name of the chart. +*/}} +{{- define "operator.appname" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "operator.labels" -}} +helm.sh/chart: {{ include "operator.chart" . }} +{{ include "operator.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "operator.selectorLabels" -}} +app.kubernetes.io/name: {{ include "operator.appname" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "operator.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Labels for Kubernetes objects created by helm test +*/}} +{{- define "operator.testLabels" -}} +helm.sh/test: {{ include "operator.chart" . }} +{{- end }} diff --git a/deploy/helm/lb-operator/templates/configmap.yaml b/deploy/helm/lb-operator/templates/configmap.yaml new file mode 100644 index 00000000..7fa8613d --- /dev/null +++ b/deploy/helm/lb-operator/templates/configmap.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +data: +{{ (.Files.Glob "configs/*").AsConfig | indent 2 }} +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-configmap + labels: + {{- include "operator.labels" . | nindent 4 }} diff --git a/deploy/helm/lb-operator/templates/csidriver.yaml b/deploy/helm/lb-operator/templates/csidriver.yaml new file mode 100644 index 00000000..d327cad3 --- /dev/null +++ b/deploy/helm/lb-operator/templates/csidriver.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: lb.stackable.tech +spec: + attachRequired: false + podInfoOnMount: true + fsGroupPolicy: File + volumeLifecycleModes: + - Ephemeral + - Persistent diff --git a/deploy/helm/lb-operator/templates/daemonset.yaml b/deploy/helm/lb-operator/templates/daemonset.yaml new file mode 100644 index 00000000..387036d2 --- /dev/null +++ b/deploy/helm/lb-operator/templates/daemonset.yaml @@ -0,0 +1,90 @@ +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ .Release.Name }}-daemonset + labels: + {{- include "operator.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "operator.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "operator.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Release.Name }}-serviceaccount + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ include "operator.appname" . }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + env: + - name: CSI_ENDPOINT + value: /csi/csi.sock + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + volumeMounts: + - name: csi + mountPath: /csi + - name: mountpoint + mountPath: /var/lib/kubelet/pods + mountPropagation: Bidirectional + - name: external-provisioner + image: k8s.gcr.io/sig-storage/csi-provisioner:v3.1.0 + args: + - --csi-address=/csi/csi.sock + - --feature-gates=Topology=true + - --extra-create-metadata + volumeMounts: + - name: csi + mountPath: /csi + - name: node-driver-registrar + image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0 + args: + - --csi-address=/csi/csi.sock + - --kubelet-registration-path=/var/lib/kubelet/plugins/secrets.stackable.tech/csi.sock + volumeMounts: + - name: registration-sock + mountPath: /registration + - name: csi + mountPath: /csi + volumes: + - name: registration-sock + hostPath: + path: /var/lib/kubelet/plugins_registry/secrets.stackable.tech-reg.sock + - name: csi + hostPath: + path: /var/lib/kubelet/plugins/secrets.stackable.tech/ + - name: mountpoint + hostPath: + path: /var/lib/kubelet/pods/ + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deploy/helm/lb-operator/templates/deployment.yaml b/deploy/helm/lb-operator/templates/deployment.yaml new file mode 100644 index 00000000..a5c58dd7 --- /dev/null +++ b/deploy/helm/lb-operator/templates/deployment.yaml @@ -0,0 +1 @@ +# Templated Deployment disabled for this operator diff --git a/deploy/helm/lb-operator/templates/roles.yaml b/deploy/helm/lb-operator/templates/roles.yaml new file mode 100644 index 00000000..47e95263 --- /dev/null +++ b/deploy/helm/lb-operator/templates/roles.yaml @@ -0,0 +1,59 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Name }}-clusterrole +rules: + - apiGroups: + - "" + resources: + - secrets + - events + - services + verbs: + - get + - list + - watch + - create + - patch + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - create + - delete + - apiGroups: + - "" + resources: + - nodes + - persistentvolumeclaims + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - csinodes + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - patch + - apiGroups: + - secrets.stackable.tech + resources: + - secretclasses + verbs: + - get diff --git a/deploy/helm/lb-operator/templates/serviceaccount.yaml b/deploy/helm/lb-operator/templates/serviceaccount.yaml new file mode 100644 index 00000000..ff2b7f8e --- /dev/null +++ b/deploy/helm/lb-operator/templates/serviceaccount.yaml @@ -0,0 +1,29 @@ +--- +{{ if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Release.Name }}-serviceaccount + labels: + {{- include "operator.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace. +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Name }}-clusterrolebinding + labels: + {{- include "operator.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ .Release.Name }}-serviceaccount + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ .Release.Name }}-clusterrole + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/deploy/helm/lb-operator/templates/storageclass.yaml b/deploy/helm/lb-operator/templates/storageclass.yaml new file mode 100644 index 00000000..58074654 --- /dev/null +++ b/deploy/helm/lb-operator/templates/storageclass.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: lb.stackable.tech +provisioner: lb.stackable.tech +volumeBindingMode: WaitForFirstConsumer diff --git a/deploy/helm/lb-operator/values.yaml b/deploy/helm/lb-operator/values.yaml new file mode 100644 index 00000000..85c422ba --- /dev/null +++ b/deploy/helm/lb-operator/values.yaml @@ -0,0 +1,52 @@ +# Default values for lb-operator. +--- +image: + repository: docker.stackable.tech/stackable/lb-operator + pullPolicy: IfNotPresent + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + # lb-operator requires root permissions + runAsUser: 0 + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/examples/nginx.yaml b/examples/nginx.yaml new file mode 100644 index 00000000..ea404850 --- /dev/null +++ b/examples/nginx.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: exposed-nginx +spec: + replicas: 1 + selector: + matchLabels: + app: exposed-nginx + template: + metadata: + labels: + app: exposed-nginx + spec: + containers: + - name: nginx + image: nginx:latest + ports: + - name: http + containerPort: 80 + volumeMounts: + - name: lb + mountPath: /usr/share/nginx/html/lb + volumeClaimTemplates: + - metadata: + name: lb + spec: + accessModes: + - ReadWriteMany + storageClassName: lb.stackable.tech + resources: + requests: + storage: 1 diff --git a/rust/lb-operator/Cargo.toml b/rust/lb-operator/Cargo.toml new file mode 100644 index 00000000..aeb38c96 --- /dev/null +++ b/rust/lb-operator/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "stackable-lb-operator" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# Need to keep this in sync with our patched h2 build +h2 = "=0.3.7" + +clap = { version = "3.1.18", features = ["derive"] } +futures = "0.3.21" +libc = "0.2.125" +pin-project = "1.0.10" +prost = "0.10.3" +prost-types = "0.10.1" +socket2 = { version = "0.4.4", features = ["all"] } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.21.1" } +tokio = { version = "1.18.2", features = ["full"] } +tokio-stream = { version = "0.1.8", features = ["net"] } +tonic = "0.7.2" +tonic-reflection = "0.4.0" +anyhow = "1.0.57" + +[build-dependencies] +tonic-build = "0.7.2" diff --git a/rust/lb-operator/build.rs b/rust/lb-operator/build.rs new file mode 100644 index 00000000..155e936c --- /dev/null +++ b/rust/lb-operator/build.rs @@ -0,0 +1,11 @@ +//! Compile Rust code from gRPC definition files stored in the vendor/csi directory. + +use std::path::PathBuf; + +fn main() { + let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR is required")); + tonic_build::configure() + .file_descriptor_set_path(out_dir.join("file_descriptor_set.bin")) + .compile(&["csi.proto"], &["vendor/csi"]) + .unwrap(); +} diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs new file mode 100644 index 00000000..a4302263 --- /dev/null +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -0,0 +1,129 @@ +use tonic::{Request, Response, Status}; + +use crate::grpc::csi::{ + self, + v1::{controller_server::Controller, ControllerGetCapabilitiesResponse}, +}; + +pub struct LbOperatorController { + pub client: stackable_operator::client::Client, +} + +#[tonic::async_trait] +impl csi::v1::controller_server::Controller for LbOperatorController { + async fn controller_get_capabilities( + &self, + _request: Request, + ) -> Result, Status> { + Ok(Response::new(csi::v1::ControllerGetCapabilitiesResponse { + capabilities: vec![csi::v1::ControllerServiceCapability { + r#type: Some(csi::v1::controller_service_capability::Type::Rpc( + csi::v1::controller_service_capability::Rpc { + r#type: + csi::v1::controller_service_capability::rpc::Type::CreateDeleteVolume + .into(), + }, + )), + }], + })) + } + + async fn create_volume( + &self, + request: Request, + ) -> Result, Status> { + let request = request.into_inner(); + Ok(Response::new(csi::v1::CreateVolumeResponse { + volume: Some(csi::v1::Volume { + capacity_bytes: 0, + volume_id: "asdf".to_string(), + volume_context: [].into(), + content_source: None, + accessible_topology: vec![request + .accessibility_requirements + .unwrap_or_default() + .preferred + .first() + .unwrap() + .clone()], + }), + })) + } + + async fn delete_volume( + &self, + request: Request, + ) -> Result, Status> { + Ok(Response::new(csi::v1::DeleteVolumeResponse {})) + } + + async fn controller_publish_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn controller_unpublish_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn validate_volume_capabilities( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn list_volumes( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn get_capacity( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn create_snapshot( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn delete_snapshot( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn list_snapshots( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn controller_expand_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn controller_get_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } +} diff --git a/rust/lb-operator/src/csi_server/identity.rs b/rust/lb-operator/src/csi_server/identity.rs new file mode 100644 index 00000000..c6281701 --- /dev/null +++ b/rust/lb-operator/src/csi_server/identity.rs @@ -0,0 +1,55 @@ +use std::collections::HashMap; + +use clap::crate_version; +use tonic::{Request, Response, Status}; + +use crate::grpc::csi; + +pub struct LbOperatorIdentity; + +#[tonic::async_trait] +impl csi::v1::identity_server::Identity for LbOperatorIdentity { + async fn get_plugin_info( + &self, + _request: Request, + ) -> Result, Status> { + Ok(Response::new(csi::v1::GetPluginInfoResponse { + name: "lb.stackable.tech".to_string(), + vendor_version: crate_version!().to_string(), + manifest: HashMap::new(), + })) + } + + async fn get_plugin_capabilities( + &self, + _request: Request, + ) -> Result, Status> { + Ok(Response::new(csi::v1::GetPluginCapabilitiesResponse { + capabilities: vec![ + csi::v1::PluginCapability { + r#type: Some(csi::v1::plugin_capability::Type::Service( + csi::v1::plugin_capability::Service { + r#type: + csi::v1::plugin_capability::service::Type::VolumeAccessibilityConstraints + .into(), + }, + )), + }, + csi::v1::PluginCapability { + r#type: Some(csi::v1::plugin_capability::Type::Service( + csi::v1::plugin_capability::Service { + r#type: csi::v1::plugin_capability::service::Type::ControllerService.into(), + }, + )), + }, + ], + })) + } + + async fn probe( + &self, + _request: Request, + ) -> Result, Status> { + Ok(Response::new(csi::v1::ProbeResponse { ready: Some(true) })) + } +} diff --git a/rust/lb-operator/src/csi_server/mod.rs b/rust/lb-operator/src/csi_server/mod.rs new file mode 100644 index 00000000..c3af2f16 --- /dev/null +++ b/rust/lb-operator/src/csi_server/mod.rs @@ -0,0 +1,3 @@ +pub mod controller; +pub mod identity; +pub mod node; diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs new file mode 100644 index 00000000..11bf929f --- /dev/null +++ b/rust/lb-operator/src/csi_server/node.rs @@ -0,0 +1,165 @@ +use std::path::PathBuf; + +use stackable_operator::{ + k8s_openapi::api::core::v1::{Node, Pod, Service, ServicePort, ServiceSpec}, + kube::core::ObjectMeta, +}; +use tokio::io::AsyncWriteExt; +use tonic::{Request, Response, Status}; + +use crate::grpc::csi::{self, v1::Topology}; + +const FIELD_MANAGER_SCOPE: &str = "volume"; + +pub struct LbOperatorNode { + pub client: stackable_operator::client::Client, + pub node_name: String, +} + +#[tonic::async_trait] +impl csi::v1::node_server::Node for LbOperatorNode { + async fn node_get_info( + &self, + _request: Request, + ) -> Result, Status> { + Ok(Response::new(csi::v1::NodeGetInfoResponse { + node_id: self.node_name.clone(), + max_volumes_per_node: i64::MAX, + accessible_topology: Some(Topology { + segments: [( + "lb.stackable.tech/hostname".to_string(), + self.node_name.clone(), + )] + .into(), + }), + })) + } + + async fn node_get_capabilities( + &self, + request: Request, + ) -> Result, Status> { + Ok(Response::new(csi::v1::NodeGetCapabilitiesResponse { + capabilities: Vec::new(), + })) + } + + async fn node_stage_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn node_unstage_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn node_publish_volume( + &self, + request: Request, + ) -> Result, Status> { + let request = request.into_inner(); + let ns = request + .volume_context + .get("csi.storage.k8s.io/pod.namespace") + .unwrap(); + let pod_name = request + .volume_context + .get("csi.storage.k8s.io/pod.name") + .unwrap(); + let pod = self.client.get::(pod_name, Some(ns)).await.unwrap(); + let node = self + .client + .get::( + pod.spec + .as_ref() + .and_then(|ps| ps.node_name.as_deref()) + .unwrap(), + None, + ) + .await + .unwrap(); + let svc = Service { + metadata: ObjectMeta { + namespace: Some(ns.clone()), + name: Some(request.volume_id.clone()), + ..Default::default() + }, + spec: Some(ServiceSpec { + type_: Some("NodePort".to_string()), + ports: Some( + pod.spec + .iter() + .flat_map(|ps| &ps.containers) + .flat_map(|ctr| &ctr.ports) + .flatten() + .map(|port| ServicePort { + name: port.name.clone(), + protocol: port.protocol.clone(), + port: port.container_port, + ..Default::default() + }) + .collect(), + ), + external_traffic_policy: Some("Local".to_string()), + selector: pod.metadata.labels, + ..Default::default() + }), + ..Default::default() + }; + let svc = self + .client + .apply_patch(FIELD_MANAGER_SCOPE, &svc, &svc) + .await + .unwrap(); + + let target_path = PathBuf::from(&request.target_path); + let ports_path = target_path.join("ports"); + tokio::fs::create_dir_all(&ports_path).await.unwrap(); + tokio::fs::File::create(target_path.join("address")) + .await + .unwrap() + .write_all(node.metadata.name.unwrap().as_bytes()) + .await + .unwrap(); + for port in svc.spec.as_ref().unwrap().ports.as_ref().unwrap() { + tokio::fs::File::create(ports_path.join(port.name.as_deref().unwrap())) + .await + .unwrap() + .write_all(port.node_port.unwrap().to_string().as_bytes()) + .await + .unwrap(); + } + + Ok(Response::new(csi::v1::NodePublishVolumeResponse {})) + } + + async fn node_unpublish_volume( + &self, + request: Request, + ) -> Result, Status> { + let request = request.into_inner(); + tokio::fs::remove_dir_all(request.target_path) + .await + .unwrap(); + Ok(Response::new(csi::v1::NodeUnpublishVolumeResponse {})) + } + + async fn node_get_volume_stats( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn node_expand_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } +} diff --git a/rust/lb-operator/src/grpc.rs b/rust/lb-operator/src/grpc.rs new file mode 100644 index 00000000..c5adf86a --- /dev/null +++ b/rust/lb-operator/src/grpc.rs @@ -0,0 +1,10 @@ +//! Include gRPC definition files that have been generated by `build.rs` + +pub static FILE_DESCRIPTOR_SET_BYTES: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/file_descriptor_set.bin")); + +pub mod csi { + pub mod v1 { + tonic::include_proto!("csi.v1"); + } +} diff --git a/rust/lb-operator/src/main.rs b/rust/lb-operator/src/main.rs new file mode 100644 index 00000000..ae3c017b --- /dev/null +++ b/rust/lb-operator/src/main.rs @@ -0,0 +1,84 @@ +use std::{os::unix::prelude::FileTypeExt, path::PathBuf}; + +use clap::Parser; +use csi_server::{ + controller::LbOperatorController, identity::LbOperatorIdentity, node::LbOperatorNode, +}; +use futures::{FutureExt, TryStreamExt}; +use grpc::csi::v1::{ + controller_server::ControllerServer, identity_server::IdentityServer, node_server::NodeServer, +}; +use stackable_operator::{cli::ProductOperatorRun, logging::TracingTarget}; +use tokio::signal::unix::{signal, SignalKind}; +use tokio_stream::wrappers::UnixListenerStream; +use tonic::transport::Server; +use utils::{uds_bind_private, TonicUnixStream}; + +mod csi_server; +mod grpc; +mod utils; + +#[derive(clap::Parser)] +#[clap(author, version)] +struct Opts { + #[clap(subcommand)] + cmd: stackable_operator::cli::Command, +} + +#[derive(clap::Parser)] +struct LbOperatorRun { + #[clap(long, env)] + csi_endpoint: PathBuf, + #[clap(long, env)] + node_name: String, + #[clap(long, env, default_value_t, arg_enum)] + tracing_target: TracingTarget, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let opts = Opts::parse(); + match opts.cmd { + stackable_operator::cli::Command::Crd => {} + stackable_operator::cli::Command::Run(LbOperatorRun { + csi_endpoint, + node_name, + tracing_target, + }) => { + stackable_operator::logging::initialize_logging( + "LB_OPERATOR_LOG", + "lb-operator", + tracing_target, + ); + let client = + stackable_operator::client::create_client(Some("lb.stackable.tech".to_string())) + .await?; + if csi_endpoint + .symlink_metadata() + .map_or(false, |meta| meta.file_type().is_socket()) + { + let _ = std::fs::remove_file(&csi_endpoint); + } + let mut sigterm = signal(SignalKind::terminate())?; + Server::builder() + .add_service( + tonic_reflection::server::Builder::configure() + .include_reflection_service(true) + .register_encoded_file_descriptor_set(grpc::FILE_DESCRIPTOR_SET_BYTES) + .build()?, + ) + .add_service(IdentityServer::new(LbOperatorIdentity)) + .add_service(ControllerServer::new(LbOperatorController { + client: client.clone(), + })) + .add_service(NodeServer::new(LbOperatorNode { client, node_name })) + .serve_with_incoming_shutdown( + UnixListenerStream::new(uds_bind_private(csi_endpoint)?) + .map_ok(TonicUnixStream), + sigterm.recv().map(|_| ()), + ) + .await?; + } + } + Ok(()) +} diff --git a/rust/lb-operator/src/utils.rs b/rust/lb-operator/src/utils.rs new file mode 100644 index 00000000..d309bcc2 --- /dev/null +++ b/rust/lb-operator/src/utils.rs @@ -0,0 +1,138 @@ +use std::{fmt::LowerHex, os::unix::prelude::AsRawFd, path::Path}; + +use pin_project::pin_project; +use socket2::Socket; +use tokio::{ + io::{AsyncRead, AsyncWrite}, + net::{UnixListener, UnixStream}, +}; +use tonic::transport::server::Connected; + +/// Adapter for using [`UnixStream`] as a [`tonic`] connection +/// Tonic usually communicates via TCP sockets, but the Kubernetes CSI interface expects +/// plugins to use Unix sockets instead. +/// This provides a wrapper implementation which delegates to tokio's [`UnixStream`] in order +/// to enable tonic to communicate via Unix sockets. +#[pin_project] +pub struct TonicUnixStream(#[pin] pub UnixStream); + +impl AsyncRead for TonicUnixStream { + fn poll_read( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &mut tokio::io::ReadBuf<'_>, + ) -> std::task::Poll> { + self.project().0.poll_read(cx, buf) + } +} + +impl AsyncWrite for TonicUnixStream { + fn poll_write( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &[u8], + ) -> std::task::Poll> { + self.project().0.poll_write(cx, buf) + } + + fn poll_flush( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.project().0.poll_flush(cx) + } + + fn poll_shutdown( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.project().0.poll_shutdown(cx) + } + + fn poll_write_vectored( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> std::task::Poll> { + self.project().0.poll_write_vectored(cx, bufs) + } + + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } +} + +impl Connected for TonicUnixStream { + type ConnectInfo = (); + + fn connect_info(&self) -> Self::ConnectInfo {} +} + +/// Bind a Unix Domain Socket listener that is only accessible to the current user +pub fn uds_bind_private(path: impl AsRef) -> Result { + // Workaround for https://github.com/tokio-rs/tokio/issues/4422 + let socket = Socket::new(socket2::Domain::UNIX, socket2::Type::STREAM, None)?; + unsafe { + // Socket-level chmod is propagated to the file created by Socket::bind. + // We need to chmod /before/ creating the file, because otherwise there is a brief window where + // the file is world-accessible (unless restricted by the global umask). + if libc::fchmod(socket.as_raw_fd(), 0o600) == -1 { + return Err(std::io::Error::last_os_error()); + } + } + socket.bind(&socket2::SockAddr::unix(path)?)?; + socket.listen(1024)?; + socket.set_nonblocking(true)?; + UnixListener::from_std(socket.into()) +} + +/// Helper for formatting byte arrays +pub struct FmtByteSlice<'a>(pub &'a [u8]); +impl LowerHex for FmtByteSlice<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for byte in self.0 { + f.write_fmt(format_args!("{:02x}", byte))?; + } + Ok(()) + } +} + +/// Combines the messages of an error and its sources into a [`String`] of the form `"error: source 1: source 2: root error"` +pub fn error_full_message(err: &dyn std::error::Error) -> String { + // Build the full hierarchy of error messages by walking up the stack until an error + // without `source` set is encountered and concatenating all encountered error strings. + let mut full_msg = format!("{}", err); + let mut curr_err = err.source(); + while let Some(curr_source) = curr_err { + full_msg.push_str(&format!(": {}", curr_source)); + curr_err = curr_source.source(); + } + full_msg +} + +#[cfg(test)] +mod tests { + use crate::utils::{error_full_message, FmtByteSlice}; + + #[test] + fn fmt_hex_byte_slice() { + assert_eq!(format!("{:x}", FmtByteSlice(&[1, 2, 255, 128])), "0102ff80"); + } + + #[test] + fn error_messages() { + assert_eq!( + error_full_message(anyhow::anyhow!("standalone error").as_ref()), + "standalone error" + ); + assert_eq!( + error_full_message( + anyhow::anyhow!("root error") + .context("middleware") + .context("leaf") + .as_ref() + ), + "leaf: middleware: root error" + ); + } +} diff --git a/rust/lb-operator/vendor/csi b/rust/lb-operator/vendor/csi new file mode 160000 index 00000000..ad238e5c --- /dev/null +++ b/rust/lb-operator/vendor/csi @@ -0,0 +1 @@ +Subproject commit ad238e5cad5a27188fcdae1ff3ace3f612638ca5 From d622e9ecc3a18f39ef045545c723ce115ab7834b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 28 Jun 2022 09:34:24 +0200 Subject: [PATCH 02/99] Generate unique Service names per PV --- rust/lb-operator/src/csi_server/controller.rs | 2 +- rust/lb-operator/src/csi_server/node.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs index a4302263..5a9bbd56 100644 --- a/rust/lb-operator/src/csi_server/controller.rs +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -36,7 +36,7 @@ impl csi::v1::controller_server::Controller for LbOperatorController { Ok(Response::new(csi::v1::CreateVolumeResponse { volume: Some(csi::v1::Volume { capacity_bytes: 0, - volume_id: "asdf".to_string(), + volume_id: request.name, volume_context: [].into(), content_source: None, accessible_topology: vec![request diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index 11bf929f..2e358d89 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -1,7 +1,8 @@ use std::path::PathBuf; use stackable_operator::{ - k8s_openapi::api::core::v1::{Node, Pod, Service, ServicePort, ServiceSpec}, + builder::OwnerReferenceBuilder, + k8s_openapi::api::core::v1::{Node, PersistentVolume, Pod, Service, ServicePort, ServiceSpec}, kube::core::ObjectMeta, }; use tokio::io::AsyncWriteExt; @@ -71,6 +72,11 @@ impl csi::v1::node_server::Node for LbOperatorNode { .volume_context .get("csi.storage.k8s.io/pod.name") .unwrap(); + let pv = self + .client + .get::(&request.volume_id, None) + .await + .unwrap(); let pod = self.client.get::(pod_name, Some(ns)).await.unwrap(); let node = self .client @@ -87,6 +93,10 @@ impl csi::v1::node_server::Node for LbOperatorNode { metadata: ObjectMeta { namespace: Some(ns.clone()), name: Some(request.volume_id.clone()), + owner_references: Some(vec![OwnerReferenceBuilder::new() + .initialize_from_resource(&pv) + .build() + .unwrap()]), ..Default::default() }, spec: Some(ServiceSpec { From c1321139c4823bf75df6c92880e595b8a77deb88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 28 Jun 2022 11:11:48 +0200 Subject: [PATCH 03/99] Also support native K8s LoadBalancer services --- Cargo.lock | 3 + Tiltfile | 5 +- .../lb-operator/templates/lb-classes.yaml | 14 +++ deploy/helm/lb-operator/templates/roles.yaml | 4 +- examples/nginx-lb.yaml | 63 +++++++++++ examples/{nginx.yaml => nginx-nodeport.yaml} | 8 +- rust/lb-operator/Cargo.toml | 3 + rust/lb-operator/src/crd.rs | 29 +++++ rust/lb-operator/src/csi_server/controller.rs | 51 +++++++-- rust/lb-operator/src/csi_server/node.rs | 107 ++++++++++++++---- rust/lb-operator/src/main.rs | 12 +- 11 files changed, 254 insertions(+), 45 deletions(-) create mode 100644 deploy/helm/lb-operator/templates/lb-classes.yaml create mode 100644 examples/nginx-lb.yaml rename examples/{nginx.yaml => nginx-nodeport.yaml} (77%) create mode 100644 rust/lb-operator/src/crd.rs diff --git a/Cargo.lock b/Cargo.lock index 1872f422..cd885574 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1780,6 +1780,9 @@ dependencies = [ "pin-project", "prost", "prost-types", + "serde", + "serde_json", + "serde_yaml", "socket2", "stackable-operator", "tokio", diff --git a/Tiltfile b/Tiltfile index d1a571c4..179ed8fd 100644 --- a/Tiltfile +++ b/Tiltfile @@ -28,6 +28,5 @@ helm_crds, helm_non_crds = filter_yaml( k8s_yaml(helm_non_crds) # Load examples -k8s_yaml('examples/nginx.yaml') -# k8s_yaml('examples/simple-consumer-nginx.yaml') -# k8s_yaml('examples/simple-consumer-shell.yaml') +k8s_yaml('examples/nginx-nodeport.yaml') +k8s_yaml('examples/nginx-lb.yaml') diff --git a/deploy/helm/lb-operator/templates/lb-classes.yaml b/deploy/helm/lb-operator/templates/lb-classes.yaml new file mode 100644 index 00000000..85c4e0fb --- /dev/null +++ b/deploy/helm/lb-operator/templates/lb-classes.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancerClass +metadata: + name: nodeport +spec: + serviceType: NodePort +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancerClass +metadata: + name: lb-external +spec: + serviceType: LoadBalancer diff --git a/deploy/helm/lb-operator/templates/roles.yaml b/deploy/helm/lb-operator/templates/roles.yaml index 47e95263..7159173d 100644 --- a/deploy/helm/lb-operator/templates/roles.yaml +++ b/deploy/helm/lb-operator/templates/roles.yaml @@ -52,8 +52,8 @@ rules: - get - patch - apiGroups: - - secrets.stackable.tech + - lb.stackable.tech resources: - - secretclasses + - loadbalancerclasses verbs: - get diff --git a/examples/nginx-lb.yaml b/examples/nginx-lb.yaml new file mode 100644 index 00000000..c5e7fa34 --- /dev/null +++ b/examples/nginx-lb.yaml @@ -0,0 +1,63 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: exposed-nginx-lb +spec: + replicas: 1 + selector: + matchLabels: + app: exposed-nginx-lb + template: + metadata: + labels: + app: exposed-nginx-lb + spec: + containers: + - name: nginx + image: nginx:latest + ports: + - name: http + containerPort: 9999 + volumeMounts: + - name: lb + mountPath: /usr/share/nginx/html/lb + - name: config + mountPath: /etc/nginx/templates + volumes: + - name: config + configMap: + name: exposed-nginx-lb-config + volumeClaimTemplates: + - metadata: + name: lb + annotations: + lb.stackable.tech/lb-class: lb-external + spec: + accessModes: + - ReadWriteMany + storageClassName: lb.stackable.tech + resources: + requests: + storage: 1 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: exposed-nginx-lb-config +data: + default.conf.template: | + server { + listen 9999; + listen [::]:9999; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } diff --git a/examples/nginx.yaml b/examples/nginx-nodeport.yaml similarity index 77% rename from examples/nginx.yaml rename to examples/nginx-nodeport.yaml index ea404850..070d78d7 100644 --- a/examples/nginx.yaml +++ b/examples/nginx-nodeport.yaml @@ -2,16 +2,16 @@ apiVersion: apps/v1 kind: StatefulSet metadata: - name: exposed-nginx + name: exposed-nginx-nodeport spec: replicas: 1 selector: matchLabels: - app: exposed-nginx + app: exposed-nginx-nodeport template: metadata: labels: - app: exposed-nginx + app: exposed-nginx-nodeport spec: containers: - name: nginx @@ -25,6 +25,8 @@ spec: volumeClaimTemplates: - metadata: name: lb + annotations: + lb.stackable.tech/lb-class: nodeport spec: accessModes: - ReadWriteMany diff --git a/rust/lb-operator/Cargo.toml b/rust/lb-operator/Cargo.toml index aeb38c96..88ac59ee 100644 --- a/rust/lb-operator/Cargo.toml +++ b/rust/lb-operator/Cargo.toml @@ -22,6 +22,9 @@ tokio-stream = { version = "0.1.8", features = ["net"] } tonic = "0.7.2" tonic-reflection = "0.4.0" anyhow = "1.0.57" +serde = "1.0.137" +serde_json = "1.0.81" +serde_yaml = "0.8.24" [build-dependencies] tonic-build = "0.7.2" diff --git a/rust/lb-operator/src/crd.rs b/rust/lb-operator/src/crd.rs new file mode 100644 index 00000000..1156d6ab --- /dev/null +++ b/rust/lb-operator/src/crd.rs @@ -0,0 +1,29 @@ +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; +use stackable_operator::kube::CustomResource; +use stackable_operator::schemars::{self, JsonSchema}; + +#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)] +#[kube( + group = "lb.stackable.tech", + version = "v1alpha1", + kind = "LoadBalancerClass", + crates( + kube_core = "stackable_operator::kube::core", + k8s_openapi = "stackable_operator::k8s_openapi", + schemars = "stackable_operator::schemars" + ) +)] +#[serde(rename_all = "camelCase")] +pub struct LoadBalancerClassSpec { + pub service_type: ServiceType, + #[serde(default)] + pub service_annotations: BTreeMap, +} + +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] +pub enum ServiceType { + NodePort, + LoadBalancer, +} diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs index 5a9bbd56..1ca5c0af 100644 --- a/rust/lb-operator/src/csi_server/controller.rs +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -1,8 +1,9 @@ +use stackable_operator::k8s_openapi::api::core::v1::PersistentVolumeClaim; use tonic::{Request, Response, Status}; -use crate::grpc::csi::{ - self, - v1::{controller_server::Controller, ControllerGetCapabilitiesResponse}, +use crate::{ + crd::{LoadBalancerClass, ServiceType}, + grpc::csi, }; pub struct LbOperatorController { @@ -33,19 +34,47 @@ impl csi::v1::controller_server::Controller for LbOperatorController { request: Request, ) -> Result, Status> { let request = request.into_inner(); + let pvc = self + .client + .get::( + request + .parameters + .get("csi.storage.k8s.io/pvc/name") + .unwrap(), + Some( + request + .parameters + .get("csi.storage.k8s.io/pvc/namespace") + .unwrap(), + ), + ) + .await + .unwrap(); + let volume_context = pvc.metadata.annotations.unwrap_or_default(); + let lb_class = self + .client + .get::( + volume_context.get("lb.stackable.tech/lb-class").unwrap(), + None, + ) + .await + .unwrap(); Ok(Response::new(csi::v1::CreateVolumeResponse { volume: Some(csi::v1::Volume { capacity_bytes: 0, volume_id: request.name, - volume_context: [].into(), + volume_context: volume_context.into_iter().collect(), content_source: None, - accessible_topology: vec![request - .accessibility_requirements - .unwrap_or_default() - .preferred - .first() - .unwrap() - .clone()], + accessible_topology: match lb_class.spec.service_type { + ServiceType::NodePort => vec![request + .accessibility_requirements + .unwrap_or_default() + .preferred + .first() + .unwrap() + .clone()], + ServiceType::LoadBalancer => Vec::new(), + }, }), })) } diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index 2e358d89..ec8417f2 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -8,7 +8,10 @@ use stackable_operator::{ use tokio::io::AsyncWriteExt; use tonic::{Request, Response, Status}; -use crate::grpc::csi::{self, v1::Topology}; +use crate::{ + crd::{LoadBalancerClass, ServiceType}, + grpc::csi::{self, v1::Topology}, +}; const FIELD_MANAGER_SCOPE: &str = "volume"; @@ -38,27 +41,13 @@ impl csi::v1::node_server::Node for LbOperatorNode { async fn node_get_capabilities( &self, - request: Request, + _request: Request, ) -> Result, Status> { Ok(Response::new(csi::v1::NodeGetCapabilitiesResponse { capabilities: Vec::new(), })) } - async fn node_stage_volume( - &self, - request: Request, - ) -> Result, Status> { - todo!() - } - - async fn node_unstage_volume( - &self, - request: Request, - ) -> Result, Status> { - todo!() - } - async fn node_publish_volume( &self, request: Request, @@ -72,6 +61,17 @@ impl csi::v1::node_server::Node for LbOperatorNode { .volume_context .get("csi.storage.k8s.io/pod.name") .unwrap(); + let lb_class = self + .client + .get::( + request + .volume_context + .get("lb.stackable.tech/lb-class") + .unwrap(), + None, + ) + .await + .unwrap(); let pv = self .client .get::(&request.volume_id, None) @@ -100,7 +100,10 @@ impl csi::v1::node_server::Node for LbOperatorNode { ..Default::default() }, spec: Some(ServiceSpec { - type_: Some("NodePort".to_string()), + type_: Some(match lb_class.spec.service_type { + ServiceType::NodePort => "NodePort".to_string(), + ServiceType::LoadBalancer => "LoadBalancer".to_string(), + }), ports: Some( pod.spec .iter() @@ -127,20 +130,58 @@ impl csi::v1::node_server::Node for LbOperatorNode { .await .unwrap(); + let address; + let ports: Vec<_>; + match lb_class.spec.service_type { + ServiceType::NodePort => { + address = node.metadata.name.as_deref().unwrap(); + ports = svc + .spec + .as_ref() + .unwrap() + .ports + .as_ref() + .unwrap() + .iter() + .map(|port| (port.name.as_deref().unwrap(), port.node_port.unwrap())) + .collect(); + } + ServiceType::LoadBalancer => { + address = svc + .status + .as_ref() + .and_then(|ss| { + let ingress = ss.load_balancer.as_ref()?.ingress.as_ref()?.first()?; + ingress.hostname.as_deref().or(ingress.ip.as_deref()) + }) + .unwrap(); + ports = svc + .spec + .as_ref() + .unwrap() + .ports + .as_ref() + .unwrap() + .iter() + .map(|port| (port.name.as_deref().unwrap(), port.port)) + .collect(); + } + }; + let target_path = PathBuf::from(&request.target_path); let ports_path = target_path.join("ports"); tokio::fs::create_dir_all(&ports_path).await.unwrap(); tokio::fs::File::create(target_path.join("address")) .await .unwrap() - .write_all(node.metadata.name.unwrap().as_bytes()) + .write_all(address.as_bytes()) .await .unwrap(); - for port in svc.spec.as_ref().unwrap().ports.as_ref().unwrap() { - tokio::fs::File::create(ports_path.join(port.name.as_deref().unwrap())) + for (port_name, port) in ports { + tokio::fs::File::create(ports_path.join(port_name)) .await .unwrap() - .write_all(port.node_port.unwrap().to_string().as_bytes()) + .write_all(port.to_string().as_bytes()) .await .unwrap(); } @@ -153,12 +194,30 @@ impl csi::v1::node_server::Node for LbOperatorNode { request: Request, ) -> Result, Status> { let request = request.into_inner(); - tokio::fs::remove_dir_all(request.target_path) - .await - .unwrap(); + match tokio::fs::remove_dir_all(request.target_path).await { + Ok(()) => {} + Err(err) if err.kind() == std::io::ErrorKind::NotFound => { + // already deleted => nothing to do + } + Err(err) => Err(err).unwrap(), + } Ok(Response::new(csi::v1::NodeUnpublishVolumeResponse {})) } + async fn node_stage_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + + async fn node_unstage_volume( + &self, + request: Request, + ) -> Result, Status> { + todo!() + } + async fn node_get_volume_stats( &self, request: Request, diff --git a/rust/lb-operator/src/main.rs b/rust/lb-operator/src/main.rs index ae3c017b..5b84f108 100644 --- a/rust/lb-operator/src/main.rs +++ b/rust/lb-operator/src/main.rs @@ -8,12 +8,15 @@ use futures::{FutureExt, TryStreamExt}; use grpc::csi::v1::{ controller_server::ControllerServer, identity_server::IdentityServer, node_server::NodeServer, }; -use stackable_operator::{cli::ProductOperatorRun, logging::TracingTarget}; +use stackable_operator::{kube::CustomResourceExt, logging::TracingTarget}; use tokio::signal::unix::{signal, SignalKind}; use tokio_stream::wrappers::UnixListenerStream; use tonic::transport::Server; use utils::{uds_bind_private, TonicUnixStream}; +use crate::crd::LoadBalancerClass; + +mod crd; mod csi_server; mod grpc; mod utils; @@ -39,7 +42,12 @@ struct LbOperatorRun { async fn main() -> anyhow::Result<()> { let opts = Opts::parse(); match opts.cmd { - stackable_operator::cli::Command::Crd => {} + stackable_operator::cli::Command::Crd => { + println!( + "{}", + serde_yaml::to_string(&LoadBalancerClass::crd()).unwrap() + ); + } stackable_operator::cli::Command::Run(LbOperatorRun { csi_endpoint, node_name, From 57eea89fcb532afd5d79ff99fdfbbfaea93c9820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 28 Jun 2022 11:35:29 +0200 Subject: [PATCH 04/99] README --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..c95559fe --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Stackable Load Balancer Operator + +A CSI provider intended to provide an abstract way to expose a single Pod to the outside network, +while hiding details about the cluster from the application developer. + +This is intended to be used by services that perform their own clustering and replica discovery, +and require external clients to connect to the correct replica. For example, this would be suitable +for HDFS DataNodes and Kafka listener connections, but not so much for HDFS NameNodes, or Kafka bootstrap +addresses. + +## Usage + +### Running + +`nix run -f. tilt up` + +### LoadBalancerClass + +`LoadBalancerClass` objects are used by cluster administrators to define a policy for how incoming connections +should be handled. For example, a small on-prem cluster might prefer to use `NodePort` services (because they don't +require BGP peering or ARP spoofing, at the cost of making each instance "sticky" to its initial K8s Node), while a +managed cloud cluster might prefer `LoadBalancer`. + +### Pods + +Pods are exposed by mounting a `PersistentVolume` with the `storageClassName` of `lb.stackable.tech` into them. +This can either be created as a `volumeClaimTemplate` of a `StatefulSet` (ensuring that each network identity will be +persistent for each replica identity, even across pod replacements) or an `ephemeral` pod `Volume` (in which case the +network identity will be recreated from scratch for every Pod). + +The `LoadBalancerClass` is specified using the `lb.stackable.tech/lb-class` annotation on the `PersistentVolumeClaim`. + +The mounted volume will contain the file `address` (containing the external address of the `Pod`), as well as +`ports/{port-name}` (containing the port number that the port is accessible on `address` from, which may or may not +be the same as the `containerPort`). From e29c62ad8c7b0d1f64869da1bdba77b57a43702a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 30 Jun 2022 17:29:15 +0200 Subject: [PATCH 05/99] Move Service provisioning logic into a separate LoadBalancer controller K8s API consumers also need to be able to introspect LB metadata, such as when building product operators build client config files. --- Cargo.lock | 29 +++ Tiltfile | 2 + deploy/helm/lb-operator/templates/roles.yaml | 12 + examples/nginx-preprovisioned-lb.yaml | 46 ++++ rust/lb-operator/Cargo.toml | 1 + rust/lb-operator/src/crd.rs | 44 ++++ rust/lb-operator/src/csi_server/node.rs | 170 +++++--------- rust/lb-operator/src/lb_controller.rs | 219 +++++++++++++++++++ rust/lb-operator/src/main.rs | 23 +- 9 files changed, 426 insertions(+), 120 deletions(-) create mode 100644 examples/nginx-preprovisioned-lb.yaml create mode 100644 rust/lb-operator/src/lb_controller.rs diff --git a/Cargo.lock b/Cargo.lock index cd885574..febf157d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -416,6 +416,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "dyn-clone" version = "1.0.5" @@ -1758,6 +1764,28 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "snafu" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5177903bf45656592d9eb5c0e22f408fc023aae51dbe2088889b71633ba451f2" +dependencies = [ + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "410b26ed97440d90ced3e2488c868d56a86e2064f5d7d6f417909b286afe25e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "socket2" version = "0.4.4" @@ -1783,6 +1811,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", + "snafu", "socket2", "stackable-operator", "tokio", diff --git a/Tiltfile b/Tiltfile index 179ed8fd..5065e33a 100644 --- a/Tiltfile +++ b/Tiltfile @@ -30,3 +30,5 @@ k8s_yaml(helm_non_crds) # Load examples k8s_yaml('examples/nginx-nodeport.yaml') k8s_yaml('examples/nginx-lb.yaml') +# use case currently broken... +#k8s_yaml('examples/nginx-preprovisioned-lb.yaml') diff --git a/deploy/helm/lb-operator/templates/roles.yaml b/deploy/helm/lb-operator/templates/roles.yaml index 7159173d..21110457 100644 --- a/deploy/helm/lb-operator/templates/roles.yaml +++ b/deploy/helm/lb-operator/templates/roles.yaml @@ -31,6 +31,7 @@ rules: resources: - nodes - persistentvolumeclaims + - endpoints verbs: - get - list @@ -55,5 +56,16 @@ rules: - lb.stackable.tech resources: - loadbalancerclasses + - loadbalancers verbs: - get + - list + - watch + - apiGroups: + - lb.stackable.tech + resources: + - loadbalancers + - loadbalancers/status + verbs: + - patch + - create diff --git a/examples/nginx-preprovisioned-lb.yaml b/examples/nginx-preprovisioned-lb.yaml new file mode 100644 index 00000000..e4f675a4 --- /dev/null +++ b/examples/nginx-preprovisioned-lb.yaml @@ -0,0 +1,46 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: exposed-nginx-preprovisioned-lb +spec: + replicas: 1 + selector: + matchLabels: + app: exposed-nginx-preprovisioned-lb + template: + metadata: + labels: + app: exposed-nginx-preprovisioned-lb + spec: + containers: + - name: nginx + image: nginx:latest + ports: + - name: http + containerPort: 80 + volumeMounts: + - name: lb + mountPath: /usr/share/nginx/html/lb + volumeClaimTemplates: + - metadata: + name: lb + annotations: + lb.stackable.tech/lb-name: exposed-nginx-preprovisioned-lb + spec: + accessModes: + - ReadWriteMany + storageClassName: lb.stackable.tech + resources: + requests: + storage: 1 +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancer +metadata: + name: exposed-nginx-preprovisioned-lb +spec: + className: lb-external + ports: + - name: http + port: 9998 diff --git a/rust/lb-operator/Cargo.toml b/rust/lb-operator/Cargo.toml index 88ac59ee..2c85717c 100644 --- a/rust/lb-operator/Cargo.toml +++ b/rust/lb-operator/Cargo.toml @@ -25,6 +25,7 @@ anyhow = "1.0.57" serde = "1.0.137" serde_json = "1.0.81" serde_yaml = "0.8.24" +snafu = "0.7.1" [build-dependencies] tonic-build = "0.7.2" diff --git a/rust/lb-operator/src/crd.rs b/rust/lb-operator/src/crd.rs index 1156d6ab..f3eecde7 100644 --- a/rust/lb-operator/src/crd.rs +++ b/rust/lb-operator/src/crd.rs @@ -9,6 +9,7 @@ use stackable_operator::schemars::{self, JsonSchema}; group = "lb.stackable.tech", version = "v1alpha1", kind = "LoadBalancerClass", + shortname = "lbclass", crates( kube_core = "stackable_operator::kube::core", k8s_openapi = "stackable_operator::k8s_openapi", @@ -27,3 +28,46 @@ pub enum ServiceType { NodePort, LoadBalancer, } + +#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default)] +#[kube( + group = "lb.stackable.tech", + version = "v1alpha1", + kind = "LoadBalancer", + shortname = "lb", + namespaced, + status = "LoadBalancerStatus", + crates( + kube_core = "stackable_operator::kube::core", + k8s_openapi = "stackable_operator::k8s_openapi", + schemars = "stackable_operator::schemars" + ) +)] +#[serde(rename_all = "camelCase")] +pub struct LoadBalancerSpec { + pub class_name: Option, + pub pod_selector: Option>, + pub ports: Option>, +} + +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct LoadBalancerPort { + pub name: String, + pub port: i32, + pub protocol: Option, +} + +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct LoadBalancerStatus { + pub service_name: Option, + pub ingress_addresses: Option>, +} + +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct LoadBalancerIngress { + pub address: String, + pub ports: BTreeMap, +} diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index ec8417f2..77eb1564 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -9,7 +9,7 @@ use tokio::io::AsyncWriteExt; use tonic::{Request, Response, Status}; use crate::{ - crd::{LoadBalancerClass, ServiceType}, + crd::{LoadBalancer, LoadBalancerClass, LoadBalancerPort, LoadBalancerSpec, ServiceType}, grpc::csi::{self, v1::Topology}, }; @@ -61,129 +61,75 @@ impl csi::v1::node_server::Node for LbOperatorNode { .volume_context .get("csi.storage.k8s.io/pod.name") .unwrap(); - let lb_class = self - .client - .get::( - request - .volume_context - .get("lb.stackable.tech/lb-class") - .unwrap(), - None, - ) - .await - .unwrap(); let pv = self .client .get::(&request.volume_id, None) .await .unwrap(); let pod = self.client.get::(pod_name, Some(ns)).await.unwrap(); - let node = self - .client - .get::( - pod.spec - .as_ref() - .and_then(|ps| ps.node_name.as_deref()) - .unwrap(), - None, - ) - .await - .unwrap(); - let svc = Service { - metadata: ObjectMeta { - namespace: Some(ns.clone()), - name: Some(request.volume_id.clone()), - owner_references: Some(vec![OwnerReferenceBuilder::new() - .initialize_from_resource(&pv) - .build() - .unwrap()]), - ..Default::default() - }, - spec: Some(ServiceSpec { - type_: Some(match lb_class.spec.service_type { - ServiceType::NodePort => "NodePort".to_string(), - ServiceType::LoadBalancer => "LoadBalancer".to_string(), - }), - ports: Some( - pod.spec - .iter() - .flat_map(|ps| &ps.containers) - .flat_map(|ctr| &ctr.ports) - .flatten() - .map(|port| ServicePort { - name: port.name.clone(), - protocol: port.protocol.clone(), - port: port.container_port, - ..Default::default() - }) - .collect(), - ), - external_traffic_policy: Some("Local".to_string()), - selector: pod.metadata.labels, - ..Default::default() - }), - ..Default::default() - }; - let svc = self - .client - .apply_patch(FIELD_MANAGER_SCOPE, &svc, &svc) - .await - .unwrap(); - let address; - let ports: Vec<_>; - match lb_class.spec.service_type { - ServiceType::NodePort => { - address = node.metadata.name.as_deref().unwrap(); - ports = svc - .spec - .as_ref() - .unwrap() - .ports - .as_ref() - .unwrap() - .iter() - .map(|port| (port.name.as_deref().unwrap(), port.node_port.unwrap())) - .collect(); - } - ServiceType::LoadBalancer => { - address = svc - .status - .as_ref() - .and_then(|ss| { - let ingress = ss.load_balancer.as_ref()?.ingress.as_ref()?.first()?; - ingress.hostname.as_deref().or(ingress.ip.as_deref()) - }) - .unwrap(); - ports = svc - .spec - .as_ref() - .unwrap() - .ports - .as_ref() - .unwrap() - .iter() - .map(|port| (port.name.as_deref().unwrap(), port.port)) - .collect(); - } + let lb = if let Some(lb_name) = request.volume_context.get("lb.stackable.tech/lb-name") { + self.client.get(lb_name, Some(ns)).await.unwrap() + } else { + let lb = LoadBalancer { + metadata: ObjectMeta { + namespace: Some(ns.clone()), + name: Some(request.volume_id.clone()), + owner_references: Some(vec![OwnerReferenceBuilder::new() + .initialize_from_resource(&pv) + .build() + .unwrap()]), + ..Default::default() + }, + spec: LoadBalancerSpec { + class_name: request + .volume_context + .get("lb.stackable.tech/lb-class") + .cloned(), + ports: Some( + pod.spec + .iter() + .flat_map(|ps| &ps.containers) + .flat_map(|ctr| &ctr.ports) + .flatten() + .map(|port| LoadBalancerPort { + name: port.name.clone().unwrap(), + protocol: port.protocol.clone(), + port: port.container_port, + }) + .collect(), + ), + pod_selector: pod.metadata.labels, + }, + status: None, + }; + self.client + .apply_patch(FIELD_MANAGER_SCOPE, &lb, &lb) + .await + .unwrap() }; let target_path = PathBuf::from(&request.target_path); - let ports_path = target_path.join("ports"); - tokio::fs::create_dir_all(&ports_path).await.unwrap(); - tokio::fs::File::create(target_path.join("address")) - .await - .unwrap() - .write_all(address.as_bytes()) - .await - .unwrap(); - for (port_name, port) in ports { - tokio::fs::File::create(ports_path.join(port_name)) - .await - .unwrap() - .write_all(port.to_string().as_bytes()) + let addrs_path = target_path.join("addresses"); + tokio::fs::create_dir_all(&addrs_path).await.unwrap(); + for addr in lb + .status + .as_ref() + .and_then(|lbs| lbs.ingress_addresses.as_ref()) + .into_iter() + .flatten() + { + let addr_dir = addrs_path.join(&addr.address); + let ports_dir = addr_dir.join("ports"); + tokio::fs::create_dir_all(&ports_dir).await.unwrap(); + tokio::fs::write(addr_dir.join("address"), addr.address.as_bytes()) .await .unwrap(); + for (port_name, port) in &addr.ports { + tokio::fs::write(ports_dir.join(port_name), port.to_string().as_bytes()) + .await + .unwrap(); + } } Ok(Response::new(csi::v1::NodePublishVolumeResponse {})) diff --git a/rust/lb-operator/src/lb_controller.rs b/rust/lb-operator/src/lb_controller.rs new file mode 100644 index 00000000..22169c59 --- /dev/null +++ b/rust/lb-operator/src/lb_controller.rs @@ -0,0 +1,219 @@ +use crate::crd::{ + LoadBalancer, LoadBalancerClass, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec, + LoadBalancerStatus, ServiceType, +}; +use futures::StreamExt; +use snafu::Snafu; +use stackable_operator::{ + builder::OwnerReferenceBuilder, + k8s_openapi::api::core::v1::{ + Endpoints, PersistentVolume, Pod, Service, ServicePort, ServiceSpec, + }, + kube::{ + api::{ListParams, ObjectMeta}, + runtime::{controller, reflector::ObjectRef}, + }, + logging::controller::{report_controller_reconciled, ReconcilerError}, +}; +use std::{collections::BTreeMap, sync::Arc, time::Duration}; + +const FIELD_MANAGER_SCOPE: &str = "loadbalancer"; + +pub async fn run(client: stackable_operator::client::Client) { + let controller = + controller::Controller::new(client.get_all_api::(), ListParams::default()); + let lb_store = controller.store(); + controller + .owns(client.get_all_api::(), ListParams::default()) + .watches( + client.get_all_api::(), + ListParams::default(), + move |endpoints| { + lb_store + .state() + .into_iter() + .filter(move |lb| { + lb.status + .as_ref() + .and_then(|lbs| lbs.service_name.as_deref()) + == endpoints.metadata.name.as_deref() + }) + .map(|lb| ObjectRef::from_obj(&*lb)) + }, + ) + .shutdown_on_signal() + .run( + reconcile, + error_policy, + controller::Context::new(Ctx { + client: client.clone(), + }), + ) + .map(|res| { + report_controller_reconciled(&client, "loadbalancers.lb.stackable.tech", &res); + }) + .collect::<()>() + .await; +} + +pub struct Ctx { + pub client: stackable_operator::client::Client, +} + +#[derive(Debug, Snafu)] +pub enum Error {} +impl ReconcilerError for Error { + fn category(&self) -> &'static str { + match *self {} + } + + fn secondary_object( + &self, + ) -> Option< + stackable_operator::kube::runtime::reflector::ObjectRef< + stackable_operator::kube::api::DynamicObject, + >, + > { + match *self {} + } +} + +pub async fn reconcile( + lb: Arc, + ctx: controller::Context, +) -> Result { + let ctx = ctx.get_ref(); + let ns = lb.metadata.namespace.clone().unwrap(); + let lb_class = ctx + .client + .get::(lb.spec.class_name.as_deref().unwrap(), None) + .await + .unwrap(); + let svc = Service { + metadata: ObjectMeta { + namespace: Some(ns.clone()), + name: lb.metadata.name.clone(), + owner_references: Some(vec![OwnerReferenceBuilder::new() + .initialize_from_resource(&*lb) + .build() + .unwrap()]), + ..Default::default() + }, + spec: Some(ServiceSpec { + type_: Some(match lb_class.spec.service_type { + ServiceType::NodePort => "NodePort".to_string(), + ServiceType::LoadBalancer => "LoadBalancer".to_string(), + }), + ports: Some( + lb.spec + .ports + .iter() + .flatten() + .map( + |LoadBalancerPort { + name, + port, + protocol, + }| ServicePort { + name: Some(name.clone()), + protocol: protocol.clone(), + port: *port, + ..Default::default() + }, + ) + .collect(), + ), + external_traffic_policy: Some("Local".to_string()), + selector: lb.spec.pod_selector.clone(), + ..Default::default() + }), + ..Default::default() + }; + let svc = ctx + .client + .apply_patch(FIELD_MANAGER_SCOPE, &svc, &svc) + .await + .unwrap(); + + let addresses: Vec<_>; + let ports: BTreeMap; + match lb_class.spec.service_type { + ServiceType::NodePort => { + let endpoints = ctx + .client + .get::(svc.metadata.name.as_deref().unwrap(), Some(&ns)) + .await + .unwrap(); + addresses = endpoints + .subsets + .into_iter() + .flatten() + .flat_map(|subset| subset.addresses) + .flatten() + .flat_map(|addr| addr.node_name) + .collect(); + ports = svc + .spec + .as_ref() + .unwrap() + .ports + .as_ref() + .unwrap() + .iter() + .map(|port| (port.name.clone().unwrap(), port.node_port.unwrap())) + .collect(); + } + ServiceType::LoadBalancer => { + addresses = svc + .status + .iter() + .flat_map(|ss| ss.load_balancer.as_ref()?.ingress.as_ref()) + .flatten() + .flat_map(|ingress| ingress.hostname.clone().or_else(|| ingress.ip.clone())) + .collect(); + ports = svc + .spec + .as_ref() + .unwrap() + .ports + .as_ref() + .unwrap() + .iter() + .map(|port| (port.name.clone().unwrap(), port.port)) + .collect(); + } + }; + + let lb_status_meta = LoadBalancer { + metadata: ObjectMeta { + name: lb.metadata.name.clone(), + namespace: lb.metadata.namespace.clone(), + uid: lb.metadata.uid.clone(), + ..Default::default() + }, + spec: LoadBalancerSpec::default(), + status: None, + }; + let lb_status = LoadBalancerStatus { + service_name: svc.metadata.name, + ingress_addresses: Some( + addresses + .into_iter() + .map(|addr| LoadBalancerIngress { + address: addr, + ports: ports.clone(), + }) + .collect(), + ), + }; + ctx.client + .apply_patch_status(FIELD_MANAGER_SCOPE, &lb_status_meta, &lb_status) + .await + .unwrap(); + + Ok(controller::Action::await_change()) +} + +pub fn error_policy(err: &Error, ctx: controller::Context) -> controller::Action { + controller::Action::requeue(Duration::from_secs(5)) +} diff --git a/rust/lb-operator/src/main.rs b/rust/lb-operator/src/main.rs index 5b84f108..1c73e6ff 100644 --- a/rust/lb-operator/src/main.rs +++ b/rust/lb-operator/src/main.rs @@ -4,7 +4,7 @@ use clap::Parser; use csi_server::{ controller::LbOperatorController, identity::LbOperatorIdentity, node::LbOperatorNode, }; -use futures::{FutureExt, TryStreamExt}; +use futures::{pin_mut, FutureExt, TryStreamExt}; use grpc::csi::v1::{ controller_server::ControllerServer, identity_server::IdentityServer, node_server::NodeServer, }; @@ -14,11 +14,12 @@ use tokio_stream::wrappers::UnixListenerStream; use tonic::transport::Server; use utils::{uds_bind_private, TonicUnixStream}; -use crate::crd::LoadBalancerClass; +use crate::crd::{LoadBalancer, LoadBalancerClass}; mod crd; mod csi_server; mod grpc; +mod lb_controller; mod utils; #[derive(clap::Parser)] @@ -44,8 +45,9 @@ async fn main() -> anyhow::Result<()> { match opts.cmd { stackable_operator::cli::Command::Crd => { println!( - "{}", - serde_yaml::to_string(&LoadBalancerClass::crd()).unwrap() + "{}{}", + serde_yaml::to_string(&LoadBalancerClass::crd()).unwrap(), + serde_yaml::to_string(&LoadBalancer::crd()).unwrap() ); } stackable_operator::cli::Command::Run(LbOperatorRun { @@ -68,7 +70,7 @@ async fn main() -> anyhow::Result<()> { let _ = std::fs::remove_file(&csi_endpoint); } let mut sigterm = signal(SignalKind::terminate())?; - Server::builder() + let csi_server = Server::builder() .add_service( tonic_reflection::server::Builder::configure() .include_reflection_service(true) @@ -79,13 +81,18 @@ async fn main() -> anyhow::Result<()> { .add_service(ControllerServer::new(LbOperatorController { client: client.clone(), })) - .add_service(NodeServer::new(LbOperatorNode { client, node_name })) + .add_service(NodeServer::new(LbOperatorNode { + client: client.clone(), + node_name, + })) .serve_with_incoming_shutdown( UnixListenerStream::new(uds_bind_private(csi_endpoint)?) .map_ok(TonicUnixStream), sigterm.recv().map(|_| ()), - ) - .await?; + ); + let controller = lb_controller::run(client); + pin_mut!(csi_server, controller); + futures::future::select(csi_server, controller).await; } } Ok(()) From 2e9e4c86352be3c549fe945a87e5269208164476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 2 Aug 2022 15:29:53 +0200 Subject: [PATCH 06/99] Update Nix and Tilt config from secret-operator --- Tiltfile | 10 +-- default.nix | 14 ++-- nix/sources.json | 14 ++++ nix/sources.nix | 194 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 220 insertions(+), 12 deletions(-) create mode 100644 nix/sources.json create mode 100644 nix/sources.nix diff --git a/Tiltfile b/Tiltfile index 5065e33a..b269ad07 100644 --- a/Tiltfile +++ b/Tiltfile @@ -1,9 +1,9 @@ -default_registry('docker.stackable.tech') +default_registry("docker.stackable.tech/sandbox") custom_build( - 'docker.stackable.tech/teozkr/lb-operator', - 'nix run -f . crate2nix generate && nix-build . -A docker --arg dockerTag null --argstr dockerRegistry k3d-registry.localhost:11337 && ./result/load-image | docker load', - deps=['rust', 'Cargo.toml', 'Cargo.lock', 'default.nix', 'build.rs', 'vendor'], + 'docker.stackable.tech/sandbox/lb-operator', + 'nix run -f . crate2nix generate && nix-build . -A docker --argstr dockerName "${EXPECTED_REGISTRY}/lb-operator" && ./result/load-image | docker load', + deps=['rust', 'Cargo.toml', 'Cargo.lock', 'default.nix', "nix", 'build.rs', 'vendor'], # ignore=['result*', 'Cargo.nix', 'target', *.yaml], outputs_image_ref_to='result/ref', ) @@ -19,7 +19,7 @@ helm_crds, helm_non_crds = filter_yaml( 'deploy/helm/lb-operator', name='lb-operator', set=[ - 'image.repository=docker.stackable.tech/teozkr/lb-operator', + 'image.repository=docker.stackable.tech/sandbox/lb-operator', ], ), api_version = "^apiextensions\\.k8s\\.io/.*$", diff --git a/default.nix b/default.nix index c6b97f0a..e9bec3ce 100644 --- a/default.nix +++ b/default.nix @@ -1,4 +1,5 @@ -{ nixpkgs ? +{ sources ? import ./nix/sources.nix # managed by https://github.com/nmattia/niv +, nixpkgs ? sources.nixpkgs , pkgs ? import nixpkgs {} , cargo ? import ./Cargo.nix { inherit nixpkgs pkgs; release = false; @@ -14,26 +15,25 @@ }; }; } -, dockerRegistry ? "docker.stackable.tech" -, dockerRepo ? "${dockerRegistry}/teozkr/lb-operator" -, dockerTag ? "latest" +, dockerName ? "docker.stackable.tech/sandbox/lb-operator" +, dockerTag ? null }: rec { build = cargo.rootCrate.build; - crds = pkgs.runCommand "lb-provisioner-crds.yaml" {} + crds = pkgs.runCommand "lb-operator-crds.yaml" {} '' ${build}/bin/stackable-lb-operator crd > $out ''; dockerImage = pkgs.dockerTools.streamLayeredImage { - name = dockerRepo; + name = dockerName; tag = dockerTag; contents = [ pkgs.bashInteractive pkgs.coreutils pkgs.util-linuxMinimal ]; config = { Cmd = [ (build+"/bin/stackable-lb-operator") "run" ]; }; }; - docker = pkgs.linkFarm "lb-provisioner-docker" [ + docker = pkgs.linkFarm "lb-operator-docker" [ { name = "load-image"; path = dockerImage; diff --git a/nix/sources.json b/nix/sources.json new file mode 100644 index 00000000..681cc2d3 --- /dev/null +++ b/nix/sources.json @@ -0,0 +1,14 @@ +{ + "nixpkgs": { + "branch": "nixpkgs-unstable", + "description": "Nix Packages collection", + "homepage": "", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3bbb296d9a0088c314ce83038b896753bbe33acb", + "sha256": "0dlq1zjcki30k2afg749a7c34vyb86sx1irab48l2g214nhj83hw", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/3bbb296d9a0088c314ce83038b896753bbe33acb.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + } +} diff --git a/nix/sources.nix b/nix/sources.nix new file mode 100644 index 00000000..9a01c8ac --- /dev/null +++ b/nix/sources.nix @@ -0,0 +1,194 @@ +# This file has been generated by Niv. + +let + + # + # The fetchers. fetch_ fetches specs of type . + # + + fetch_file = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchurl { inherit (spec) url sha256; name = name'; } + else + pkgs.fetchurl { inherit (spec) url sha256; name = name'; }; + + fetch_tarball = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchTarball { name = name'; inherit (spec) url sha256; } + else + pkgs.fetchzip { name = name'; inherit (spec) url sha256; }; + + fetch_git = name: spec: + let + ref = + if spec ? ref then spec.ref else + if spec ? branch then "refs/heads/${spec.branch}" else + if spec ? tag then "refs/tags/${spec.tag}" else + abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; + submodules = if spec ? submodules then spec.submodules else false; + submoduleArg = + let + nixSupportsSubmodules = builtins.compareVersions builtins.nixVersion "2.4" >= 0; + emptyArgWithWarning = + if submodules == true + then + builtins.trace + ( + "The niv input \"${name}\" uses submodules " + + "but your nix's (${builtins.nixVersion}) builtins.fetchGit " + + "does not support them" + ) + {} + else {}; + in + if nixSupportsSubmodules + then { inherit submodules; } + else emptyArgWithWarning; + in + builtins.fetchGit + ({ url = spec.repo; inherit (spec) rev; inherit ref; } // submoduleArg); + + fetch_local = spec: spec.path; + + fetch_builtin-tarball = name: throw + ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=tarball -a builtin=true''; + + fetch_builtin-url = name: throw + ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=file -a builtin=true''; + + # + # Various helpers + # + + # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 + sanitizeName = name: + ( + concatMapStrings (s: if builtins.isList s then "-" else s) + ( + builtins.split "[^[:alnum:]+._?=-]+" + ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) + ) + ); + + # The set of packages used when specs are fetched using non-builtins. + mkPkgs = sources: system: + let + sourcesNixpkgs = + import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; }; + hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; + hasThisAsNixpkgsPath = == ./.; + in + if builtins.hasAttr "nixpkgs" sources + then sourcesNixpkgs + else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then + import {} + else + abort + '' + Please specify either (through -I or NIX_PATH=nixpkgs=...) or + add a package called "nixpkgs" to your sources.json. + ''; + + # The actual fetching function. + fetch = pkgs: name: spec: + + if ! builtins.hasAttr "type" spec then + abort "ERROR: niv spec ${name} does not have a 'type' attribute" + else if spec.type == "file" then fetch_file pkgs name spec + else if spec.type == "tarball" then fetch_tarball pkgs name spec + else if spec.type == "git" then fetch_git name spec + else if spec.type == "local" then fetch_local spec + else if spec.type == "builtin-tarball" then fetch_builtin-tarball name + else if spec.type == "builtin-url" then fetch_builtin-url name + else + abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; + + # If the environment variable NIV_OVERRIDE_${name} is set, then use + # the path directly as opposed to the fetched source. + replace = name: drv: + let + saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; + ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; + in + if ersatz == "" then drv else + # this turns the string into an actual Nix path (for both absolute and + # relative paths) + if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}"; + + # Ports of functions for older nix versions + + # a Nix version of mapAttrs if the built-in doesn't exist + mapAttrs = builtins.mapAttrs or ( + f: set: with builtins; + listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) + ); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 + range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 + stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 + stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); + concatMapStrings = f: list: concatStrings (map f list); + concatStrings = builtins.concatStringsSep ""; + + # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 + optionalAttrs = cond: as: if cond then as else {}; + + # fetchTarball version that is compatible between all the versions of Nix + builtins_fetchTarball = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchTarball; + in + if lessThan nixVersion "1.12" then + fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchTarball attrs; + + # fetchurl version that is compatible between all the versions of Nix + builtins_fetchurl = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchurl; + in + if lessThan nixVersion "1.12" then + fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchurl attrs; + + # Create the final "sources" from the config + mkSources = config: + mapAttrs ( + name: spec: + if builtins.hasAttr "outPath" spec + then abort + "The values in sources.json should not have an 'outPath' attribute" + else + spec // { outPath = replace name (fetch config.pkgs name spec); } + ) config.sources; + + # The "config" used by the fetchers + mkConfig = + { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null + , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile) + , system ? builtins.currentSystem + , pkgs ? mkPkgs sources system + }: rec { + # The sources, i.e. the attribute set of spec name to spec + inherit sources; + + # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers + inherit pkgs; + }; + +in +mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); } From 6a671e6c04420cd25ebf726ea75dfdd412ad3ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 2 Aug 2022 15:35:31 +0200 Subject: [PATCH 07/99] Fix mounting preprovisioned LBs --- Tiltfile | 2 +- rust/lb-operator/src/csi_server/controller.rs | 33 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Tiltfile b/Tiltfile index b269ad07..d9bc371b 100644 --- a/Tiltfile +++ b/Tiltfile @@ -31,4 +31,4 @@ k8s_yaml(helm_non_crds) k8s_yaml('examples/nginx-nodeport.yaml') k8s_yaml('examples/nginx-lb.yaml') # use case currently broken... -#k8s_yaml('examples/nginx-preprovisioned-lb.yaml') +k8s_yaml('examples/nginx-preprovisioned-lb.yaml') diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs index 1ca5c0af..3510ff0a 100644 --- a/rust/lb-operator/src/csi_server/controller.rs +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -2,7 +2,7 @@ use stackable_operator::k8s_openapi::api::core::v1::PersistentVolumeClaim; use tonic::{Request, Response, Status}; use crate::{ - crd::{LoadBalancerClass, ServiceType}, + crd::{LoadBalancer, LoadBalancerClass, ServiceType}, grpc::csi, }; @@ -34,6 +34,10 @@ impl csi::v1::controller_server::Controller for LbOperatorController { request: Request, ) -> Result, Status> { let request = request.into_inner(); + let ns = request + .parameters + .get("csi.storage.k8s.io/pvc/namespace") + .unwrap(); let pvc = self .client .get::( @@ -41,22 +45,29 @@ impl csi::v1::controller_server::Controller for LbOperatorController { .parameters .get("csi.storage.k8s.io/pvc/name") .unwrap(), - Some( - request - .parameters - .get("csi.storage.k8s.io/pvc/namespace") - .unwrap(), - ), + Some(ns), ) .await .unwrap(); let volume_context = pvc.metadata.annotations.unwrap_or_default(); + let lb_name = volume_context.get("lb.stackable.tech/lb-name"); + let lb_class_name = if let Some(lb_name) = lb_name { + self.client + .get::(lb_name, Some(ns)) + .await + .unwrap() + .spec + .class_name + .unwrap() + } else { + volume_context + .get("lb.stackable.tech/lb-class") + .unwrap() + .to_string() + }; let lb_class = self .client - .get::( - volume_context.get("lb.stackable.tech/lb-class").unwrap(), - None, - ) + .get::(&lb_class_name, None) .await .unwrap(); Ok(Response::new(csi::v1::CreateVolumeResponse { From efb3002f9a8b35baf26e6d38093c23a71b292a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 2 Aug 2022 17:26:46 +0200 Subject: [PATCH 08/99] Fix conflict with secret-operator --- deploy/helm/lb-operator/templates/daemonset.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/helm/lb-operator/templates/daemonset.yaml b/deploy/helm/lb-operator/templates/daemonset.yaml index 387036d2..e6cdb3bd 100644 --- a/deploy/helm/lb-operator/templates/daemonset.yaml +++ b/deploy/helm/lb-operator/templates/daemonset.yaml @@ -60,7 +60,7 @@ spec: image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0 args: - --csi-address=/csi/csi.sock - - --kubelet-registration-path=/var/lib/kubelet/plugins/secrets.stackable.tech/csi.sock + - --kubelet-registration-path=/var/lib/kubelet/plugins/lb.stackable.tech/csi.sock volumeMounts: - name: registration-sock mountPath: /registration @@ -69,10 +69,10 @@ spec: volumes: - name: registration-sock hostPath: - path: /var/lib/kubelet/plugins_registry/secrets.stackable.tech-reg.sock + path: /var/lib/kubelet/plugins_registry/lb.stackable.tech-reg.sock - name: csi hostPath: - path: /var/lib/kubelet/plugins/secrets.stackable.tech/ + path: /var/lib/kubelet/plugins/lb.stackable.tech/ - name: mountpoint hostPath: path: /var/lib/kubelet/pods/ From 424dcd0ecc0eb7747f447ff3c4367ffbe15cf26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 4 Aug 2022 16:33:03 +0200 Subject: [PATCH 09/99] Fix catch 22 where pods have no known ingress addresses before they are inited --- Cargo.lock | 412 ++++++++++-------------- Cargo.toml | 5 +- rust/lb-operator/Cargo.toml | 3 +- rust/lb-operator/src/crd.rs | 3 +- rust/lb-operator/src/csi_server/node.rs | 38 ++- rust/lb-operator/src/lb_controller.rs | 53 +-- 6 files changed, 245 insertions(+), 269 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index febf157d..738f3b54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,9 +33,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.57" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9" [[package]] name = "async-stream" @@ -60,9 +60,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ "proc-macro2", "quote", @@ -88,9 +88,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.5.7" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc47084705629d09d15060d70a8dbfce479c842303d05929ce29c74c995916ae" +checksum = "6b9496f0c1d1afb7a2af4338bbe1d969cddfead41d87a9fb3aaa6d0bbc7af648" dependencies = [ "async-trait", "axum-core", @@ -100,7 +100,7 @@ dependencies = [ "http", "http-body", "hyper", - "itoa 1.0.2", + "itoa 1.0.3", "matchit", "memchr", "mime", @@ -110,16 +110,16 @@ dependencies = [ "sync_wrapper", "tokio", "tower", - "tower-http 0.3.4", + "tower-http", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2efed1c501becea07ce48118786ebcf229531d0d3b28edf224a720020d9e106" +checksum = "e4f44a0e6200e9d11a1cdc989e4b358f6e3d354fbf48478f345a17f4e43f8635" dependencies = [ "async-trait", "bytes", @@ -148,9 +148,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bit-set" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] @@ -181,9 +181,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cc" @@ -212,16 +212,16 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.18" +version = "3.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", "indexmap", - "lazy_static", + "once_cell", "strsim", "termcolor", "textwrap", @@ -229,9 +229,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.1.18" +version = "3.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4" dependencies = [ "heck", "proc-macro-error", @@ -242,9 +242,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] @@ -260,9 +260,9 @@ dependencies = [ [[package]] name = "const_format" -version = "0.2.24" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a1316fa6a23fea1ee41cb80321590385e5f3e575e99f77c4d918ce5d44379d" +checksum = "939dc9e2eb9077e0679d2ce32de1ded8531779360b003b4a972a7a39ec263495" dependencies = [ "const_format_proc_macros", ] @@ -296,9 +296,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -306,22 +306,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", -] - -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", + "once_cell", ] [[package]] @@ -330,22 +320,8 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" dependencies = [ - "darling_core 0.14.1", - "darling_macro 0.14.1", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", + "darling_core", + "darling_macro", ] [[package]] @@ -362,24 +338,13 @@ dependencies = [ "syn", ] -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn", -] - [[package]] name = "darling_macro" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" dependencies = [ - "darling_core 0.14.1", + "darling_core", "quote", "syn", ] @@ -424,15 +389,15 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dyn-clone" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" +checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" [[package]] name = "either" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" [[package]] name = "encoding" @@ -510,18 +475,18 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] [[package]] name = "fixedbitset" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "fnv" @@ -645,13 +610,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -674,9 +639,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "heck" @@ -701,7 +666,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.2", + "itoa 1.0.3", ] [[package]] @@ -808,9 +773,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "1.8.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", @@ -827,9 +792,9 @@ dependencies = [ [[package]] name = "integer-encoding" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e85a1509a128c855368e135cffcde7eac17d8e1083f41e2b98c58bc1a5074be" +checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" [[package]] name = "itertools" @@ -848,9 +813,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "java-properties" @@ -865,9 +830,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" dependencies = [ "wasm-bindgen", ] @@ -896,9 +861,9 @@ dependencies = [ [[package]] name = "k8s-openapi" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0489fc937cc7616a9abfa61bf39c250d7e32e1325ef028c8d9278dd24ea395b3" +checksum = "d2ae2c04fcee6b01b04e3aadd56bb418932c8e0a9d8a93f48bc68c6bdcdb559d" dependencies = [ "base64", "bytes", @@ -911,9 +876,9 @@ dependencies = [ [[package]] name = "kube" -version = "0.71.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342744dfeb81fe186b84f485b33f12c6a15d3396987d933b06a566a3db52ca38" +checksum = "a527a8001a61d8d470dab27ac650889938760c243903e7cd90faaf7c60a34bdd" dependencies = [ "k8s-openapi", "kube-client", @@ -924,9 +889,9 @@ dependencies = [ [[package]] name = "kube-client" -version = "0.71.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f69a504997799340408635d6e351afb8aab2c34ca3165e162f41b3b34a69a79" +checksum = "c0d48f42df4e8342e9f488c4b97e3759d0042c4e7ab1a853cc285adb44409480" dependencies = [ "base64", "bytes", @@ -955,15 +920,15 @@ dependencies = [ "tokio-native-tls", "tokio-util 0.7.3", "tower", - "tower-http 0.2.5", + "tower-http", "tracing", ] [[package]] name = "kube-core" -version = "0.71.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a247487699941baaf93438d65b12d4e32450bea849d619d19ed394e8a4a645" +checksum = "91f56027f862fdcad265d2e9616af416a355e28a1c620bb709083494753e070d" dependencies = [ "chrono", "form_urlencoded", @@ -979,11 +944,11 @@ dependencies = [ [[package]] name = "kube-derive" -version = "0.71.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "203f7c5acf9d0dfb0b08d44ec1d66ace3d1dfe0cdd82e65e274f3f96615d666c" +checksum = "66d74121eb41af4480052901f31142d8d9bbdf1b7c6b856da43bcb02f5b1b177" dependencies = [ - "darling 0.13.4", + "darling", "proc-macro2", "quote", "serde_json", @@ -992,9 +957,9 @@ dependencies = [ [[package]] name = "kube-runtime" -version = "0.71.0" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02ea50e6ed56578e1d1d02548901b12fe6d3edbf110269a396955e285d487973" +checksum = "8fdcf5a20f968768e342ef1a457491bb5661fccd81119666d626c57500b16d99" dependencies = [ "ahash", "backoff", @@ -1022,15 +987,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linked_hash_set" @@ -1095,13 +1060,13 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mio" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys", ] @@ -1160,15 +1125,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" dependencies = [ "bitflags", "cfg-if", @@ -1198,9 +1163,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" dependencies = [ "autocfg", "cc", @@ -1274,9 +1239,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" [[package]] name = "parking_lot" @@ -1303,9 +1268,9 @@ dependencies = [ [[package]] name = "pem" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" +checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" dependencies = [ "base64", ] @@ -1328,18 +1293,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" dependencies = [ "proc-macro2", "quote", @@ -1372,9 +1337,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "prettyplease" -version = "0.1.11" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28f53e8b192565862cf99343194579a022eb9c7dd3a8d03134734803c7b3125" +checksum = "697ae720ee02011f439e0701db107ffe2916d83f718342d65d7f8bf7b8a5fee9" dependencies = [ "proc-macro2", "syn", @@ -1406,9 +1371,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ "unicode-ident", ] @@ -1486,9 +1451,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -1525,9 +1490,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -1545,9 +1510,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.6" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -1565,9 +1530,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "remove_dir_all" @@ -1580,15 +1545,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "schannel" @@ -1602,9 +1567,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b5a3c80cea1ab61f4260238409510e814e38b4b563c06044edf91e7dc070e3" +checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed" dependencies = [ "dyn-clone", "schemars_derive", @@ -1614,9 +1579,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ae4dce13e8614c46ac3c38ef1c0d668b101df6ac39817aebdaa26642ddae9b" +checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743" dependencies = [ "proc-macro2", "quote", @@ -1665,15 +1630,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.9" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" +checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" [[package]] name = "serde" -version = "1.0.137" +version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2" dependencies = [ "serde_derive", ] @@ -1690,9 +1655,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e" dependencies = [ "proc-macro2", "quote", @@ -1701,9 +1666,9 @@ dependencies = [ [[package]] name = "serde_derive_internals" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ "proc-macro2", "quote", @@ -1712,21 +1677,21 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" dependencies = [ "indexmap", - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap", "ryu", @@ -1754,15 +1719,18 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "snafu" @@ -1814,6 +1782,7 @@ dependencies = [ "snafu", "socket2", "stackable-operator", + "strum", "tokio", "tokio-stream", "tonic", @@ -1823,8 +1792,8 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.21.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.21.1#01b0aa2069580b9f2088a4409a63436f9917004b" +version = "0.24.0" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.24.0#8667365352e384e298caa8ebe9f99b2381c190ed" dependencies = [ "backoff", "chrono", @@ -1857,10 +1826,10 @@ dependencies = [ [[package]] name = "stackable-operator-derive" -version = "0.21.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.21.1#01b0aa2069580b9f2088a4409a63436f9917004b" +version = "0.24.0" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.24.0#8667365352e384e298caa8ebe9f99b2381c190ed" dependencies = [ - "darling 0.14.1", + "darling", "proc-macro2", "quote", "syn", @@ -1874,18 +1843,18 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.24.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" +checksum = "4faebde00e8ff94316c01800f9054fd2ba77d30d9e922541913051d1d978918b" dependencies = [ "heck", "proc-macro2", @@ -1896,9 +1865,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.96" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", @@ -1942,18 +1911,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" dependencies = [ "proc-macro2", "quote", @@ -1993,10 +1962,11 @@ dependencies = [ [[package]] name = "tokio" -version = "1.19.2" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" dependencies = [ + "autocfg", "bytes", "libc", "memchr", @@ -2156,9 +2126,9 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", @@ -2174,32 +2144,13 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower-http" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" -dependencies = [ - "base64", - "bitflags", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-range-header", - "pin-project-lite", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower-http" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba" dependencies = [ + "base64", "bitflags", "bytes", "futures-core", @@ -2211,6 +2162,7 @@ dependencies = [ "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -2221,15 +2173,15 @@ checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "log", @@ -2240,9 +2192,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" dependencies = [ "proc-macro2", "quote", @@ -2251,9 +2203,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", "valuable", @@ -2282,9 +2234,9 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.17.3" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93600c803bb15e2a32bd376001b8625587f268fe887669b5ac86af524637c242" +checksum = "fbbe89715c1dbbb790059e2565353978564924ee85017b5fff365c872ff6721f" dependencies = [ "once_cell", "opentelemetry", @@ -2296,13 +2248,13 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.11" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" dependencies = [ "ansi_term", - "lazy_static", "matchers", + "once_cell", "regex", "sharded-slab", "smallvec", @@ -2329,9 +2281,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] name = "unicode-xid" @@ -2367,12 +2319,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2381,9 +2327,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2391,13 +2337,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -2406,9 +2352,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2416,9 +2362,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" dependencies = [ "proc-macro2", "quote", @@ -2429,9 +2375,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "which" @@ -2535,6 +2481,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.5" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/Cargo.toml b/Cargo.toml index bcc6da07..961098d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,7 @@ members = ["rust/lb-operator"] [patch.crates-io] # Workaround for https://github.com/hyperium/tonic/issues/243 -h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } \ No newline at end of file +h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } + +# [patch."https://github.com/stackabletech/operator-rs.git"] +# stackable-operator = { path = "../operator-rs" } \ No newline at end of file diff --git a/rust/lb-operator/Cargo.toml b/rust/lb-operator/Cargo.toml index 2c85717c..621850ed 100644 --- a/rust/lb-operator/Cargo.toml +++ b/rust/lb-operator/Cargo.toml @@ -16,7 +16,7 @@ pin-project = "1.0.10" prost = "0.10.3" prost-types = "0.10.1" socket2 = { version = "0.4.4", features = ["all"] } -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.21.1" } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.24.0" } tokio = { version = "1.18.2", features = ["full"] } tokio-stream = { version = "0.1.8", features = ["net"] } tonic = "0.7.2" @@ -26,6 +26,7 @@ serde = "1.0.137" serde_json = "1.0.81" serde_yaml = "0.8.24" snafu = "0.7.1" +strum = "0.24.1" [build-dependencies] tonic-build = "0.7.2" diff --git a/rust/lb-operator/src/crd.rs b/rust/lb-operator/src/crd.rs index f3eecde7..2ffaef0c 100644 --- a/rust/lb-operator/src/crd.rs +++ b/rust/lb-operator/src/crd.rs @@ -23,7 +23,7 @@ pub struct LoadBalancerClassSpec { pub service_annotations: BTreeMap, } -#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)] pub enum ServiceType { NodePort, LoadBalancer, @@ -63,6 +63,7 @@ pub struct LoadBalancerPort { pub struct LoadBalancerStatus { pub service_name: Option, pub ingress_addresses: Option>, + pub node_ports: Option>, } #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index 77eb1564..fb4c777f 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -2,14 +2,13 @@ use std::path::PathBuf; use stackable_operator::{ builder::OwnerReferenceBuilder, - k8s_openapi::api::core::v1::{Node, PersistentVolume, Pod, Service, ServicePort, ServiceSpec}, + k8s_openapi::api::core::v1::{PersistentVolume, Pod}, kube::core::ObjectMeta, }; -use tokio::io::AsyncWriteExt; use tonic::{Request, Response, Status}; use crate::{ - crd::{LoadBalancer, LoadBalancerClass, LoadBalancerPort, LoadBalancerSpec, ServiceType}, + crd::{LoadBalancer, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec}, grpc::csi::{self, v1::Topology}, }; @@ -112,13 +111,28 @@ impl csi::v1::node_server::Node for LbOperatorNode { let target_path = PathBuf::from(&request.target_path); let addrs_path = target_path.join("addresses"); tokio::fs::create_dir_all(&addrs_path).await.unwrap(); - for addr in lb + // Prefer calculating a per-node address where possible, to ensure that the address at least tries to + // connect to the pod in question. + // We also can't rely on `ingress_addresses` being set yet, since the pod won't not have an IP address yet + // (and so can't be found in `Endpoints`) + let lb_addrs = if let Some(node_ports) = lb .status .as_ref() - .and_then(|lbs| lbs.ingress_addresses.as_ref()) - .into_iter() - .flatten() + .and_then(|status| status.node_ports.clone()) { + vec![LoadBalancerIngress { + address: pod.spec.as_ref().unwrap().node_name.clone().unwrap(), + ports: node_ports, + }] + } else { + lb.status + .as_ref() + .and_then(|lbs| lbs.ingress_addresses.as_ref()) + .cloned() + .unwrap_or_default() + }; + let mut default_addr_dir = None; + for addr in &lb_addrs { let addr_dir = addrs_path.join(&addr.address); let ports_dir = addr_dir.join("ports"); tokio::fs::create_dir_all(&ports_dir).await.unwrap(); @@ -130,7 +144,17 @@ impl csi::v1::node_server::Node for LbOperatorNode { .await .unwrap(); } + default_addr_dir.get_or_insert(addr_dir); } + tokio::fs::symlink( + default_addr_dir + .expect("no default lb addr set") + .strip_prefix(&target_path) + .expect("default addr dir is not inside target dir"), + target_path.join("default-address"), + ) + .await + .unwrap(); Ok(Response::new(csi::v1::NodePublishVolumeResponse {})) } diff --git a/rust/lb-operator/src/lb_controller.rs b/rust/lb-operator/src/lb_controller.rs index 22169c59..f8573310 100644 --- a/rust/lb-operator/src/lb_controller.rs +++ b/rust/lb-operator/src/lb_controller.rs @@ -3,19 +3,18 @@ use crate::crd::{ LoadBalancerStatus, ServiceType, }; use futures::StreamExt; -use snafu::Snafu; +use snafu::{ResultExt, Snafu}; use stackable_operator::{ builder::OwnerReferenceBuilder, - k8s_openapi::api::core::v1::{ - Endpoints, PersistentVolume, Pod, Service, ServicePort, ServiceSpec, - }, + k8s_openapi::api::core::v1::{Endpoints, Service, ServicePort, ServiceSpec}, kube::{ - api::{ListParams, ObjectMeta}, + api::{DynamicObject, ListParams, ObjectMeta}, runtime::{controller, reflector::ObjectRef}, }, logging::controller::{report_controller_reconciled, ReconcilerError}, }; use std::{collections::BTreeMap, sync::Arc, time::Duration}; +use strum::IntoStaticStr; const FIELD_MANAGER_SCOPE: &str = "loadbalancer"; @@ -45,7 +44,7 @@ pub async fn run(client: stackable_operator::client::Client) { .run( reconcile, error_policy, - controller::Context::new(Ctx { + Arc::new(Ctx { client: client.clone(), }), ) @@ -60,29 +59,26 @@ pub struct Ctx { pub client: stackable_operator::client::Client, } -#[derive(Debug, Snafu)] -pub enum Error {} +#[derive(Debug, Snafu, IntoStaticStr)] +pub enum Error { + ApplyService { + source: stackable_operator::error::Error, + svc: ObjectRef, + }, +} impl ReconcilerError for Error { fn category(&self) -> &'static str { - match *self {} + self.into() } - fn secondary_object( - &self, - ) -> Option< - stackable_operator::kube::runtime::reflector::ObjectRef< - stackable_operator::kube::api::DynamicObject, - >, - > { - match *self {} + fn secondary_object(&self) -> Option> { + match self { + Self::ApplyService { source: _, svc } => Some(svc.clone().erase()), + } } } -pub async fn reconcile( - lb: Arc, - ctx: controller::Context, -) -> Result { - let ctx = ctx.get_ref(); +pub async fn reconcile(lb: Arc, ctx: Arc) -> Result { let ns = lb.metadata.namespace.clone().unwrap(); let lb_class = ctx .client @@ -125,6 +121,7 @@ pub async fn reconcile( ), external_traffic_policy: Some("Local".to_string()), selector: lb.spec.pod_selector.clone(), + publish_not_ready_addresses: Some(true), ..Default::default() }), ..Default::default() @@ -133,7 +130,9 @@ pub async fn reconcile( .client .apply_patch(FIELD_MANAGER_SCOPE, &svc, &svc) .await - .unwrap(); + .with_context(|_| ApplyServiceSnafu { + svc: ObjectRef::from_obj(&svc), + })?; let addresses: Vec<_>; let ports: BTreeMap; @@ -141,9 +140,10 @@ pub async fn reconcile( ServiceType::NodePort => { let endpoints = ctx .client - .get::(svc.metadata.name.as_deref().unwrap(), Some(&ns)) + .get_opt::(svc.metadata.name.as_deref().unwrap(), Some(&ns)) .await - .unwrap(); + .unwrap() + .unwrap_or_default(); addresses = endpoints .subsets .into_iter() @@ -205,6 +205,7 @@ pub async fn reconcile( }) .collect(), ), + node_ports: (lb_class.spec.service_type == ServiceType::NodePort).then(|| ports), }; ctx.client .apply_patch_status(FIELD_MANAGER_SCOPE, &lb_status_meta, &lb_status) @@ -214,6 +215,6 @@ pub async fn reconcile( Ok(controller::Action::await_change()) } -pub fn error_policy(err: &Error, ctx: controller::Context) -> controller::Action { +pub fn error_policy(_err: &Error, _ctx: Arc) -> controller::Action { controller::Action::requeue(Duration::from_secs(5)) } From d23befca800ef2e08bb784c1b4eda8ca1f7000c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 4 Aug 2022 16:36:59 +0200 Subject: [PATCH 10/99] Don't panic when LoadBalancer is deleted during reconcile --- rust/lb-operator/src/lb_controller.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rust/lb-operator/src/lb_controller.rs b/rust/lb-operator/src/lb_controller.rs index f8573310..fc6d0cee 100644 --- a/rust/lb-operator/src/lb_controller.rs +++ b/rust/lb-operator/src/lb_controller.rs @@ -65,6 +65,9 @@ pub enum Error { source: stackable_operator::error::Error, svc: ObjectRef, }, + ApplyStatus { + source: stackable_operator::error::Error, + }, } impl ReconcilerError for Error { fn category(&self) -> &'static str { @@ -74,6 +77,7 @@ impl ReconcilerError for Error { fn secondary_object(&self) -> Option> { match self { Self::ApplyService { source: _, svc } => Some(svc.clone().erase()), + Self::ApplyStatus { source: _ } => None, } } } @@ -210,7 +214,7 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result Date: Mon, 8 Aug 2022 14:26:21 +0200 Subject: [PATCH 11/99] Deduplicate ports when building LoadBalancer --- rust/lb-operator/src/lb_controller.rs | 50 ++++++++++++++++----------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/rust/lb-operator/src/lb_controller.rs b/rust/lb-operator/src/lb_controller.rs index fc6d0cee..06a4099f 100644 --- a/rust/lb-operator/src/lb_controller.rs +++ b/rust/lb-operator/src/lb_controller.rs @@ -13,7 +13,11 @@ use stackable_operator::{ }, logging::controller::{report_controller_reconciled, ReconcilerError}, }; -use std::{collections::BTreeMap, sync::Arc, time::Duration}; +use std::{ + collections::{BTreeMap, BTreeSet}, + sync::Arc, + time::Duration, +}; use strum::IntoStaticStr; const FIELD_MANAGER_SCOPE: &str = "loadbalancer"; @@ -89,6 +93,30 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result(lb.spec.class_name.as_deref().unwrap(), None) .await .unwrap(); + let pod_ports = lb + .spec + .ports + .iter() + .flatten() + .map( + |LoadBalancerPort { + name, + port, + protocol, + }| { + ( + (protocol, name), + ServicePort { + name: Some(name.clone()), + protocol: protocol.clone(), + port: *port, + ..Default::default() + }, + ) + }, + ) + // Deduplicate ports by (protocol, name) + .collect::>(); let svc = Service { metadata: ObjectMeta { namespace: Some(ns.clone()), @@ -104,25 +132,7 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result "NodePort".to_string(), ServiceType::LoadBalancer => "LoadBalancer".to_string(), }), - ports: Some( - lb.spec - .ports - .iter() - .flatten() - .map( - |LoadBalancerPort { - name, - port, - protocol, - }| ServicePort { - name: Some(name.clone()), - protocol: protocol.clone(), - port: *port, - ..Default::default() - }, - ) - .collect(), - ), + ports: Some(pod_ports.into_values().collect()), external_traffic_policy: Some("Local".to_string()), selector: lb.spec.pod_selector.clone(), publish_not_ready_addresses: Some(true), From 548cac51c185cbf82d51d23d155fdde78a5c34f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 8 Aug 2022 14:27:10 +0200 Subject: [PATCH 12/99] Add permission to create events --- deploy/helm/lb-operator/templates/roles.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/deploy/helm/lb-operator/templates/roles.yaml b/deploy/helm/lb-operator/templates/roles.yaml index 21110457..bb284dca 100644 --- a/deploy/helm/lb-operator/templates/roles.yaml +++ b/deploy/helm/lb-operator/templates/roles.yaml @@ -52,6 +52,12 @@ rules: verbs: - get - patch + - apiGroups: + - events.k8s.io + resources: + - events + verbs: + - create - apiGroups: - lb.stackable.tech resources: From 9f13ebc7d26a95940fd74b736d1abf2d7406dfc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 15 Aug 2022 11:19:48 +0200 Subject: [PATCH 13/99] Name LBs after the PVC rather than PV --- rust/lb-operator/src/csi_server/node.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index fb4c777f..a93107f5 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -73,7 +73,10 @@ impl csi::v1::node_server::Node for LbOperatorNode { let lb = LoadBalancer { metadata: ObjectMeta { namespace: Some(ns.clone()), - name: Some(request.volume_id.clone()), + name: pv + .spec + .as_ref() + .and_then(|pv_spec| pv_spec.claim_ref.as_ref()?.name.clone()), owner_references: Some(vec![OwnerReferenceBuilder::new() .initialize_from_resource(&pv) .build() From e964e99cc9cafae4a00495b6d03719f0646136ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 15 Aug 2022 11:20:50 +0200 Subject: [PATCH 14/99] Expose CRD as library crate --- rust/lb-operator/src/lib.rs | 1 + 1 file changed, 1 insertion(+) create mode 100644 rust/lb-operator/src/lib.rs diff --git a/rust/lb-operator/src/lib.rs b/rust/lb-operator/src/lib.rs new file mode 100644 index 00000000..b89e9789 --- /dev/null +++ b/rust/lb-operator/src/lib.rs @@ -0,0 +1 @@ +pub mod crd; From 87d9eef70c55a2a74c1b16bd2866c4b596d2f32a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 15 Aug 2022 11:21:07 +0200 Subject: [PATCH 15/99] Prefer exposing node IP address over hostname --- rust/lb-operator/src/lb_controller.rs | 33 +++++++++++++++++++-------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/rust/lb-operator/src/lb_controller.rs b/rust/lb-operator/src/lb_controller.rs index 06a4099f..39f062d6 100644 --- a/rust/lb-operator/src/lb_controller.rs +++ b/rust/lb-operator/src/lb_controller.rs @@ -2,22 +2,18 @@ use crate::crd::{ LoadBalancer, LoadBalancerClass, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec, LoadBalancerStatus, ServiceType, }; -use futures::StreamExt; +use futures::{future::try_join_all, StreamExt}; use snafu::{ResultExt, Snafu}; use stackable_operator::{ builder::OwnerReferenceBuilder, - k8s_openapi::api::core::v1::{Endpoints, Service, ServicePort, ServiceSpec}, + k8s_openapi::api::core::v1::{Endpoints, Node, Service, ServicePort, ServiceSpec}, kube::{ api::{DynamicObject, ListParams, ObjectMeta}, runtime::{controller, reflector::ObjectRef}, }, logging::controller::{report_controller_reconciled, ReconcilerError}, }; -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, - time::Duration, -}; +use std::{collections::BTreeMap, sync::Arc, time::Duration}; use strum::IntoStaticStr; const FIELD_MANAGER_SCOPE: &str = "loadbalancer"; @@ -148,7 +144,7 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result; + let addresses: Vec; let ports: BTreeMap; match lb_class.spec.service_type { ServiceType::NodePort => { @@ -158,13 +154,32 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result>(); + let nodes = try_join_all( + node_names + .iter() + .map(|node_name| ctx.client.get::(node_name, None)), + ) + .await + .unwrap(); + addresses = nodes + .into_iter() + .flat_map(|node| { + let addrs = node.status.and_then(|s| s.addresses).unwrap_or_default(); + addrs + .iter() + .find(|addr| addr.type_ == "ExternalIP") + .or_else(|| addrs.iter().find(|addr| addr.type_ == "InternalIP")) + .or_else(|| addrs.iter().find(|addr| addr.type_ == "Hostname")) + .map(|addr| addr.address.clone()) + }) .collect(); ports = svc .spec From 7dd215ea9750e4a29877632b822a5b201208c16a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 15 Aug 2022 18:18:34 +0200 Subject: [PATCH 16/99] Use serde to unpack storage params --- rust/lb-operator/src/csi_server/controller.rs | 51 ++++---- rust/lb-operator/src/csi_server/mod.rs | 16 +++ rust/lb-operator/src/csi_server/node.rs | 111 ++++++++++-------- 3 files changed, 106 insertions(+), 72 deletions(-) diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs index 3510ff0a..6fd2cd83 100644 --- a/rust/lb-operator/src/csi_server/controller.rs +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -1,3 +1,4 @@ +use serde::{de::IntoDeserializer, Deserialize}; use stackable_operator::k8s_openapi::api::core::v1::PersistentVolumeClaim; use tonic::{Request, Response, Status}; @@ -6,10 +7,20 @@ use crate::{ grpc::csi, }; +use super::{LbSelector, LbVolumeContext}; + pub struct LbOperatorController { pub client: stackable_operator::client::Client, } +#[derive(Deserialize)] +struct ControllerVolumeParams { + #[serde(rename = "csi.storage.k8s.io/pvc/name")] + pvc_name: String, + #[serde(rename = "csi.storage.k8s.io/pvc/namespace")] + pvc_namespace: String, +} + #[tonic::async_trait] impl csi::v1::controller_server::Controller for LbOperatorController { async fn controller_get_capabilities( @@ -34,36 +45,32 @@ impl csi::v1::controller_server::Controller for LbOperatorController { request: Request, ) -> Result, Status> { let request = request.into_inner(); - let ns = request - .parameters - .get("csi.storage.k8s.io/pvc/namespace") + let ControllerVolumeParams { + pvc_name, + pvc_namespace: ns, + } = ControllerVolumeParams::deserialize(request.parameters.into_deserializer()) + .map_err(|e: serde::de::value::Error| e) .unwrap(); let pvc = self .client - .get::( - request - .parameters - .get("csi.storage.k8s.io/pvc/name") - .unwrap(), - Some(ns), - ) + .get::(&pvc_name, Some(&ns)) .await .unwrap(); - let volume_context = pvc.metadata.annotations.unwrap_or_default(); - let lb_name = volume_context.get("lb.stackable.tech/lb-name"); - let lb_class_name = if let Some(lb_name) = lb_name { - self.client - .get::(lb_name, Some(ns)) + let raw_volume_context = pvc.metadata.annotations.unwrap_or_default(); + let LbVolumeContext { lb_selector } = + LbVolumeContext::deserialize(raw_volume_context.clone().into_deserializer()) + .map_err(|e: serde::de::value::Error| e) + .unwrap(); + let lb_class_name = match lb_selector { + LbSelector::Lb(lb_name) => self + .client + .get::(&lb_name, Some(&ns)) .await .unwrap() .spec .class_name - .unwrap() - } else { - volume_context - .get("lb.stackable.tech/lb-class") - .unwrap() - .to_string() + .unwrap(), + LbSelector::LbClass(lb_class) => lb_class, }; let lb_class = self .client @@ -74,7 +81,7 @@ impl csi::v1::controller_server::Controller for LbOperatorController { volume: Some(csi::v1::Volume { capacity_bytes: 0, volume_id: request.name, - volume_context: volume_context.into_iter().collect(), + volume_context: raw_volume_context.into_iter().collect(), content_source: None, accessible_topology: match lb_class.spec.service_type { ServiceType::NodePort => vec![request diff --git a/rust/lb-operator/src/csi_server/mod.rs b/rust/lb-operator/src/csi_server/mod.rs index c3af2f16..0f1c0316 100644 --- a/rust/lb-operator/src/csi_server/mod.rs +++ b/rust/lb-operator/src/csi_server/mod.rs @@ -1,3 +1,19 @@ +use serde::Deserialize; + pub mod controller; pub mod identity; pub mod node; + +#[derive(Deserialize)] +enum LbSelector { + #[serde(rename = "lb.stackable.tech/lb-class")] + LbClass(String), + #[serde(rename = "lb.stackable.tech/lb-name")] + Lb(String), +} + +#[derive(Deserialize)] +struct LbVolumeContext { + #[serde(flatten)] + lb_selector: LbSelector, +} diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index a93107f5..716cc020 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; +use serde::{de::IntoDeserializer, Deserialize}; use stackable_operator::{ builder::OwnerReferenceBuilder, k8s_openapi::api::core::v1::{PersistentVolume, Pod}, @@ -12,6 +13,8 @@ use crate::{ grpc::csi::{self, v1::Topology}, }; +use super::{LbSelector, LbVolumeContext}; + const FIELD_MANAGER_SCOPE: &str = "volume"; pub struct LbOperatorNode { @@ -19,6 +22,17 @@ pub struct LbOperatorNode { pub node_name: String, } +#[derive(Deserialize)] +struct LbNodeVolumeContext { + #[serde(rename = "csi.storage.k8s.io/pod.namespace")] + pod_namespace: String, + #[serde(rename = "csi.storage.k8s.io/pod.name")] + pod_name: String, + + #[serde(flatten)] + common: LbVolumeContext, +} + #[tonic::async_trait] impl csi::v1::node_server::Node for LbOperatorNode { async fn node_get_info( @@ -52,63 +66,60 @@ impl csi::v1::node_server::Node for LbOperatorNode { request: Request, ) -> Result, Status> { let request = request.into_inner(); - let ns = request - .volume_context - .get("csi.storage.k8s.io/pod.namespace") - .unwrap(); - let pod_name = request - .volume_context - .get("csi.storage.k8s.io/pod.name") + let LbNodeVolumeContext { + pod_namespace: ns, + pod_name, + common: LbVolumeContext { lb_selector }, + } = LbNodeVolumeContext::deserialize(request.volume_context.into_deserializer()) + .map_err(|e: serde::de::value::Error| e) .unwrap(); let pv = self .client .get::(&request.volume_id, None) .await .unwrap(); - let pod = self.client.get::(pod_name, Some(ns)).await.unwrap(); + let pod = self.client.get::(&pod_name, Some(&ns)).await.unwrap(); - let lb = if let Some(lb_name) = request.volume_context.get("lb.stackable.tech/lb-name") { - self.client.get(lb_name, Some(ns)).await.unwrap() - } else { - let lb = LoadBalancer { - metadata: ObjectMeta { - namespace: Some(ns.clone()), - name: pv - .spec - .as_ref() - .and_then(|pv_spec| pv_spec.claim_ref.as_ref()?.name.clone()), - owner_references: Some(vec![OwnerReferenceBuilder::new() - .initialize_from_resource(&pv) - .build() - .unwrap()]), - ..Default::default() - }, - spec: LoadBalancerSpec { - class_name: request - .volume_context - .get("lb.stackable.tech/lb-class") - .cloned(), - ports: Some( - pod.spec - .iter() - .flat_map(|ps| &ps.containers) - .flat_map(|ctr| &ctr.ports) - .flatten() - .map(|port| LoadBalancerPort { - name: port.name.clone().unwrap(), - protocol: port.protocol.clone(), - port: port.container_port, - }) - .collect(), - ), - pod_selector: pod.metadata.labels, - }, - status: None, - }; - self.client - .apply_patch(FIELD_MANAGER_SCOPE, &lb, &lb) - .await - .unwrap() + let lb = match lb_selector { + LbSelector::Lb(lb_name) => self.client.get(&lb_name, Some(&ns)).await.unwrap(), + LbSelector::LbClass(lb_class_name) => { + let lb = LoadBalancer { + metadata: ObjectMeta { + namespace: Some(ns.clone()), + name: pv + .spec + .as_ref() + .and_then(|pv_spec| pv_spec.claim_ref.as_ref()?.name.clone()), + owner_references: Some(vec![OwnerReferenceBuilder::new() + .initialize_from_resource(&pv) + .build() + .unwrap()]), + ..Default::default() + }, + spec: LoadBalancerSpec { + class_name: Some(lb_class_name), + ports: Some( + pod.spec + .iter() + .flat_map(|ps| &ps.containers) + .flat_map(|ctr| &ctr.ports) + .flatten() + .map(|port| LoadBalancerPort { + name: port.name.clone().unwrap(), + protocol: port.protocol.clone(), + port: port.container_port, + }) + .collect(), + ), + pod_selector: pod.metadata.labels, + }, + status: None, + }; + self.client + .apply_patch(FIELD_MANAGER_SCOPE, &lb, &lb) + .await + .unwrap() + } }; let target_path = PathBuf::from(&request.target_path); From b19e7f3e42b2a3668d30a77c56fd6912d54351c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 15 Aug 2022 18:36:32 +0200 Subject: [PATCH 17/99] Start migrating towards snafuified errors --- rust/lb-operator/src/csi_server/controller.rs | 91 +++++++++++++++---- 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs index 6fd2cd83..114323cc 100644 --- a/rust/lb-operator/src/csi_server/controller.rs +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -1,10 +1,14 @@ use serde::{de::IntoDeserializer, Deserialize}; -use stackable_operator::k8s_openapi::api::core::v1::PersistentVolumeClaim; +use snafu::{OptionExt, ResultExt, Snafu}; +use stackable_operator::{ + k8s_openapi::api::core::v1::PersistentVolumeClaim, kube::runtime::reflector::ObjectRef, +}; use tonic::{Request, Response, Status}; use crate::{ crd::{LoadBalancer, LoadBalancerClass, ServiceType}, grpc::csi, + utils::error_full_message, }; use super::{LbSelector, LbVolumeContext}; @@ -21,6 +25,47 @@ struct ControllerVolumeParams { pvc_namespace: String, } +#[derive(Snafu, Debug)] +#[snafu(module)] +enum CreateVolumeError { + DecodeRequestParams { + source: serde::de::value::Error, + }, + GetPvc { + source: stackable_operator::error::Error, + pvc: ObjectRef, + }, + DecodeVolumeContext { + source: serde::de::value::Error, + }, + GetLoadBalancer { + source: stackable_operator::error::Error, + lb: ObjectRef, + }, + NoLoadBalancerClass { + lb: ObjectRef, + }, + GetLoadBalancerClass { + source: stackable_operator::error::Error, + lb_class: ObjectRef, + }, +} + +impl From for Status { + fn from(err: CreateVolumeError) -> Self { + let full_msg = error_full_message(&err); + // Convert to an appropriate tonic::Status representation and include full error message + match err { + CreateVolumeError::DecodeRequestParams { .. } => Status::invalid_argument(full_msg), + CreateVolumeError::DecodeVolumeContext { .. } => Status::invalid_argument(full_msg), + CreateVolumeError::NoLoadBalancerClass { .. } => Status::invalid_argument(full_msg), + CreateVolumeError::GetPvc { .. } => Status::unavailable(full_msg), + CreateVolumeError::GetLoadBalancer { .. } => Status::unavailable(full_msg), + CreateVolumeError::GetLoadBalancerClass { .. } => Status::unavailable(full_msg), + } + } +} + #[tonic::async_trait] impl csi::v1::controller_server::Controller for LbOperatorController { async fn controller_get_capabilities( @@ -49,34 +94,42 @@ impl csi::v1::controller_server::Controller for LbOperatorController { pvc_name, pvc_namespace: ns, } = ControllerVolumeParams::deserialize(request.parameters.into_deserializer()) - .map_err(|e: serde::de::value::Error| e) - .unwrap(); + .context(create_volume_error::DecodeRequestParamsSnafu)?; let pvc = self .client .get::(&pvc_name, Some(&ns)) .await - .unwrap(); + .with_context(|_| create_volume_error::GetPvcSnafu { + pvc: ObjectRef::new(&pvc_name).within(&ns), + })?; let raw_volume_context = pvc.metadata.annotations.unwrap_or_default(); let LbVolumeContext { lb_selector } = LbVolumeContext::deserialize(raw_volume_context.clone().into_deserializer()) - .map_err(|e: serde::de::value::Error| e) - .unwrap(); + .context(create_volume_error::DecodeVolumeContextSnafu)?; let lb_class_name = match lb_selector { - LbSelector::Lb(lb_name) => self - .client - .get::(&lb_name, Some(&ns)) - .await - .unwrap() - .spec - .class_name - .unwrap(), + LbSelector::Lb(lb_name) => { + let lb = self + .client + .get::(&lb_name, Some(&ns)) + .await + .with_context(|_| create_volume_error::GetLoadBalancerSnafu { + lb: ObjectRef::new(&lb_name).within(&ns), + })?; + lb.spec.class_name.clone().with_context(|| { + create_volume_error::NoLoadBalancerClassSnafu { + lb: ObjectRef::from_obj(&lb), + } + })? + } LbSelector::LbClass(lb_class) => lb_class, }; let lb_class = self .client .get::(&lb_class_name, None) .await - .unwrap(); + .with_context(|_| create_volume_error::GetLoadBalancerClassSnafu { + lb_class: ObjectRef::new(&lb_class_name).within(&ns), + })?; Ok(Response::new(csi::v1::CreateVolumeResponse { volume: Some(csi::v1::Volume { capacity_bytes: 0, @@ -84,13 +137,13 @@ impl csi::v1::controller_server::Controller for LbOperatorController { volume_context: raw_volume_context.into_iter().collect(), content_source: None, accessible_topology: match lb_class.spec.service_type { - ServiceType::NodePort => vec![request + ServiceType::NodePort => request .accessibility_requirements .unwrap_or_default() .preferred - .first() - .unwrap() - .clone()], + .into_iter() + .take(1) + .collect(), ServiceType::LoadBalancer => Vec::new(), }, }), From db96972251178b1caab02f033cb7de94bde28379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 16 Aug 2022 16:18:33 +0200 Subject: [PATCH 18/99] Cleaned up CSI error messages --- rust/lb-operator/src/csi_server/controller.rs | 92 +++---- rust/lb-operator/src/csi_server/mod.rs | 6 + rust/lb-operator/src/csi_server/node.rs | 233 +++++++++++++----- 3 files changed, 230 insertions(+), 101 deletions(-) diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs index 114323cc..bdd4eeb4 100644 --- a/rust/lb-operator/src/csi_server/controller.rs +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -1,7 +1,8 @@ use serde::{de::IntoDeserializer, Deserialize}; use snafu::{OptionExt, ResultExt, Snafu}; use stackable_operator::{ - k8s_openapi::api::core::v1::PersistentVolumeClaim, kube::runtime::reflector::ObjectRef, + k8s_openapi::api::core::v1::PersistentVolumeClaim, + kube::{core::DynamicObject, runtime::reflector::ObjectRef}, }; use tonic::{Request, Response, Status}; @@ -11,7 +12,7 @@ use crate::{ utils::error_full_message, }; -use super::{LbSelector, LbVolumeContext}; +use super::{tonic_unimplemented, LbSelector, LbVolumeContext}; pub struct LbOperatorController { pub client: stackable_operator::client::Client, @@ -28,27 +29,22 @@ struct ControllerVolumeParams { #[derive(Snafu, Debug)] #[snafu(module)] enum CreateVolumeError { + #[snafu(display("failed to decode request parameters"))] DecodeRequestParams { source: serde::de::value::Error, }, - GetPvc { + #[snafu(display("failed to get {obj}"))] + GetObject { source: stackable_operator::error::Error, - pvc: ObjectRef, + obj: Box>, }, + #[snafu(display("failed to decode volume context"))] DecodeVolumeContext { source: serde::de::value::Error, }, - GetLoadBalancer { - source: stackable_operator::error::Error, - lb: ObjectRef, - }, NoLoadBalancerClass { lb: ObjectRef, }, - GetLoadBalancerClass { - source: stackable_operator::error::Error, - lb_class: ObjectRef, - }, } impl From for Status { @@ -59,9 +55,7 @@ impl From for Status { CreateVolumeError::DecodeRequestParams { .. } => Status::invalid_argument(full_msg), CreateVolumeError::DecodeVolumeContext { .. } => Status::invalid_argument(full_msg), CreateVolumeError::NoLoadBalancerClass { .. } => Status::invalid_argument(full_msg), - CreateVolumeError::GetPvc { .. } => Status::unavailable(full_msg), - CreateVolumeError::GetLoadBalancer { .. } => Status::unavailable(full_msg), - CreateVolumeError::GetLoadBalancerClass { .. } => Status::unavailable(full_msg), + CreateVolumeError::GetObject { .. } => Status::unavailable(full_msg), } } } @@ -89,6 +83,7 @@ impl csi::v1::controller_server::Controller for LbOperatorController { &self, request: Request, ) -> Result, Status> { + use create_volume_error::*; let request = request.into_inner(); let ControllerVolumeParams { pvc_name, @@ -99,8 +94,10 @@ impl csi::v1::controller_server::Controller for LbOperatorController { .client .get::(&pvc_name, Some(&ns)) .await - .with_context(|_| create_volume_error::GetPvcSnafu { - pvc: ObjectRef::new(&pvc_name).within(&ns), + .with_context(|_| GetObjectSnafu { + obj: ObjectRef::::new(&pvc_name) + .within(&ns) + .erase(), })?; let raw_volume_context = pvc.metadata.annotations.unwrap_or_default(); let LbVolumeContext { lb_selector } = @@ -112,14 +109,15 @@ impl csi::v1::controller_server::Controller for LbOperatorController { .client .get::(&lb_name, Some(&ns)) .await - .with_context(|_| create_volume_error::GetLoadBalancerSnafu { - lb: ObjectRef::new(&lb_name).within(&ns), + .with_context(|_| GetObjectSnafu { + obj: ObjectRef::::new(&lb_name).within(&ns).erase(), })?; - lb.spec.class_name.clone().with_context(|| { - create_volume_error::NoLoadBalancerClassSnafu { + lb.spec + .class_name + .clone() + .with_context(|| NoLoadBalancerClassSnafu { lb: ObjectRef::from_obj(&lb), - } - })? + })? } LbSelector::LbClass(lb_class) => lb_class, }; @@ -127,8 +125,10 @@ impl csi::v1::controller_server::Controller for LbOperatorController { .client .get::(&lb_class_name, None) .await - .with_context(|_| create_volume_error::GetLoadBalancerClassSnafu { - lb_class: ObjectRef::new(&lb_class_name).within(&ns), + .with_context(|_| GetObjectSnafu { + obj: ObjectRef::::new(&lb_class_name) + .within(&ns) + .erase(), })?; Ok(Response::new(csi::v1::CreateVolumeResponse { volume: Some(csi::v1::Volume { @@ -152,78 +152,78 @@ impl csi::v1::controller_server::Controller for LbOperatorController { async fn delete_volume( &self, - request: Request, + _request: Request, ) -> Result, Status> { Ok(Response::new(csi::v1::DeleteVolumeResponse {})) } async fn controller_publish_volume( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn controller_unpublish_volume( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn validate_volume_capabilities( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn list_volumes( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn get_capacity( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn create_snapshot( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn delete_snapshot( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn list_snapshots( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn controller_expand_volume( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn controller_get_volume( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } } diff --git a/rust/lb-operator/src/csi_server/mod.rs b/rust/lb-operator/src/csi_server/mod.rs index 0f1c0316..f8bf62de 100644 --- a/rust/lb-operator/src/csi_server/mod.rs +++ b/rust/lb-operator/src/csi_server/mod.rs @@ -17,3 +17,9 @@ struct LbVolumeContext { #[serde(flatten)] lb_selector: LbSelector, } + +fn tonic_unimplemented() -> Result { + Err(tonic::Status::unimplemented( + "this endpoint is not implemented", + )) +} diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index 716cc020..8364166c 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -1,19 +1,28 @@ -use std::path::PathBuf; +use std::{fmt::Debug, path::PathBuf}; -use serde::{de::IntoDeserializer, Deserialize}; +use serde::{ + de::{DeserializeOwned, IntoDeserializer}, + Deserialize, +}; +use snafu::{OptionExt, ResultExt, Snafu}; use stackable_operator::{ builder::OwnerReferenceBuilder, k8s_openapi::api::core::v1::{PersistentVolume, Pod}, - kube::core::ObjectMeta, + kube::{ + core::{DynamicObject, ObjectMeta}, + runtime::reflector::ObjectRef, + Resource, + }, }; use tonic::{Request, Response, Status}; use crate::{ crd::{LoadBalancer, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec}, grpc::csi::{self, v1::Topology}, + utils::error_full_message, }; -use super::{LbSelector, LbVolumeContext}; +use super::{tonic_unimplemented, LbSelector, LbVolumeContext}; const FIELD_MANAGER_SCOPE: &str = "volume"; @@ -33,6 +42,69 @@ struct LbNodeVolumeContext { common: LbVolumeContext, } +#[derive(Snafu, Debug)] +#[snafu(module)] +enum PublishVolumeError { + #[snafu(display("failed to decode volume context"))] + DecodeVolumeContext { source: serde::de::value::Error }, + #[snafu(display("failed to get {obj}"))] + GetObject { + source: stackable_operator::error::Error, + obj: ObjectRef, + }, + #[snafu(display("{pod} has not been scheduled to a node yet"))] + PodHasNoNode { pod: ObjectRef }, + #[snafu(display("failed to build LoadBalancer's owner reference"))] + BuildLbOwnerRef { + source: stackable_operator::error::Error, + }, + #[snafu(display("failed to apply {lb}"))] + ApplyLb { + source: stackable_operator::error::Error, + lb: ObjectRef, + }, + #[snafu(display("failed to prepare pod dir at {target_path:?}"))] + PreparePodDir { + source: pod_dir::Error, + target_path: PathBuf, + }, +} + +impl From for Status { + fn from(err: PublishVolumeError) -> Self { + let full_msg = error_full_message(&err); + // Convert to an appropriate tonic::Status representation and include full error message + match err { + PublishVolumeError::DecodeVolumeContext { .. } => Status::invalid_argument(full_msg), + PublishVolumeError::GetObject { .. } => Status::unavailable(full_msg), + PublishVolumeError::PodHasNoNode { .. } => Status::unavailable(full_msg), + PublishVolumeError::BuildLbOwnerRef { .. } => Status::unavailable(full_msg), + PublishVolumeError::ApplyLb { .. } => Status::unavailable(full_msg), + PublishVolumeError::PreparePodDir { .. } => Status::internal(full_msg), + } + } +} + +#[derive(Snafu, Debug)] +#[snafu(module)] +enum UnpublishVolumeError { + #[snafu(display("failed to clean up volume data at {path:?}"))] + CleanupData { + source: std::io::Error, + path: PathBuf, + }, +} + +impl From for Status { + fn from(err: UnpublishVolumeError) -> Self { + let full_msg = error_full_message(&err); + // Convert to an appropriate tonic::Status representation and include full error message + match err { + UnpublishVolumeError::CleanupData { .. } => Status::internal(full_msg), + } + } +} + #[tonic::async_trait] impl csi::v1::node_server::Node for LbOperatorNode { async fn node_get_info( @@ -65,23 +137,39 @@ impl csi::v1::node_server::Node for LbOperatorNode { &self, request: Request, ) -> Result, Status> { + use publish_volume_error::*; + async fn get_obj + DeserializeOwned + Clone + Debug>( + client: &stackable_operator::client::Client, + name: &str, + ns: Option<&str>, + ) -> Result { + client.get(name, ns).await.with_context(|_| GetObjectSnafu { + obj: { + let mut obj = ObjectRef::::new(name); + if let Some(ns) = ns { + obj = obj.within(ns); + } + obj.erase() + }, + }) + } + // let get_obj = |name: &str, ns: Option<&str>| self.client.get(name, ns); + let request = request.into_inner(); let LbNodeVolumeContext { pod_namespace: ns, pod_name, common: LbVolumeContext { lb_selector }, } = LbNodeVolumeContext::deserialize(request.volume_context.into_deserializer()) - .map_err(|e: serde::de::value::Error| e) - .unwrap(); - let pv = self - .client - .get::(&request.volume_id, None) - .await - .unwrap(); - let pod = self.client.get::(&pod_name, Some(&ns)).await.unwrap(); + .context(DecodeVolumeContextSnafu)?; + let pv_name = &request.volume_id; + let pv = get_obj::(&self.client, pv_name, None).await?; + let pod = get_obj::(&self.client, &pod_name, Some(&ns)).await?; let lb = match lb_selector { - LbSelector::Lb(lb_name) => self.client.get(&lb_name, Some(&ns)).await.unwrap(), + LbSelector::Lb(lb_name) => { + get_obj::(&self.client, &lb_name, Some(&ns)).await? + } LbSelector::LbClass(lb_class_name) => { let lb = LoadBalancer { metadata: ObjectMeta { @@ -93,7 +181,7 @@ impl csi::v1::node_server::Node for LbOperatorNode { owner_references: Some(vec![OwnerReferenceBuilder::new() .initialize_from_resource(&pv) .build() - .unwrap()]), + .context(BuildLbOwnerRefSnafu)?]), ..Default::default() }, spec: LoadBalancerSpec { @@ -105,26 +193,28 @@ impl csi::v1::node_server::Node for LbOperatorNode { .flat_map(|ctr| &ctr.ports) .flatten() .map(|port| LoadBalancerPort { - name: port.name.clone().unwrap(), + name: port + .name + .clone() + .unwrap_or_else(|| format!("port-{}", port.container_port)), protocol: port.protocol.clone(), port: port.container_port, }) .collect(), ), - pod_selector: pod.metadata.labels, + pod_selector: pod.metadata.labels.clone(), }, status: None, }; self.client .apply_patch(FIELD_MANAGER_SCOPE, &lb, &lb) .await - .unwrap() + .with_context(|_| ApplyLbSnafu { + lb: ObjectRef::from_obj(&lb), + })? } }; - let target_path = PathBuf::from(&request.target_path); - let addrs_path = target_path.join("addresses"); - tokio::fs::create_dir_all(&addrs_path).await.unwrap(); // Prefer calculating a per-node address where possible, to ensure that the address at least tries to // connect to the pod in question. // We also can't rely on `ingress_addresses` being set yet, since the pod won't not have an IP address yet @@ -135,7 +225,13 @@ impl csi::v1::node_server::Node for LbOperatorNode { .and_then(|status| status.node_ports.clone()) { vec![LoadBalancerIngress { - address: pod.spec.as_ref().unwrap().node_name.clone().unwrap(), + address: pod + .spec + .as_ref() + .and_then(|s| s.node_name.clone()) + .with_context(|| PodHasNoNodeSnafu { + pod: ObjectRef::from_obj(&pod), + })?, ports: node_ports, }] } else { @@ -145,30 +241,11 @@ impl csi::v1::node_server::Node for LbOperatorNode { .cloned() .unwrap_or_default() }; - let mut default_addr_dir = None; - for addr in &lb_addrs { - let addr_dir = addrs_path.join(&addr.address); - let ports_dir = addr_dir.join("ports"); - tokio::fs::create_dir_all(&ports_dir).await.unwrap(); - tokio::fs::write(addr_dir.join("address"), addr.address.as_bytes()) - .await - .unwrap(); - for (port_name, port) in &addr.ports { - tokio::fs::write(ports_dir.join(port_name), port.to_string().as_bytes()) - .await - .unwrap(); - } - default_addr_dir.get_or_insert(addr_dir); - } - tokio::fs::symlink( - default_addr_dir - .expect("no default lb addr set") - .strip_prefix(&target_path) - .expect("default addr dir is not inside target dir"), - target_path.join("default-address"), - ) - .await - .unwrap(); + + let target_path = PathBuf::from(request.target_path); + pod_dir::write_lb_info_to_pod_dir(&target_path, &lb_addrs) + .await + .context(PreparePodDirSnafu { target_path })?; Ok(Response::new(csi::v1::NodePublishVolumeResponse {})) } @@ -178,41 +255,87 @@ impl csi::v1::node_server::Node for LbOperatorNode { request: Request, ) -> Result, Status> { let request = request.into_inner(); - match tokio::fs::remove_dir_all(request.target_path).await { + let path = PathBuf::from(request.target_path); + match tokio::fs::remove_dir_all(&path).await { Ok(()) => {} Err(err) if err.kind() == std::io::ErrorKind::NotFound => { // already deleted => nothing to do } - Err(err) => Err(err).unwrap(), + Err(err) => Err(err).context(unpublish_volume_error::CleanupDataSnafu { path })?, } Ok(Response::new(csi::v1::NodeUnpublishVolumeResponse {})) } async fn node_stage_volume( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn node_unstage_volume( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn node_get_volume_stats( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() } async fn node_expand_volume( &self, - request: Request, + _request: Request, ) -> Result, Status> { - todo!() + tonic_unimplemented() + } +} + +mod pod_dir { + use std::path::Path; + + use crate::crd::LoadBalancerIngress; + use snafu::{OptionExt, ResultExt, Snafu}; + + #[derive(Snafu, Debug)] + pub enum Error { + #[snafu(context(false))] + Fs { source: std::io::Error }, + #[snafu(display("load balancer has no address yet"))] + NoDefaultLb, + #[snafu(display("default address folder is outside of the volume root"))] + DefaultAddrIsOutsideRoot { source: std::path::StripPrefixError }, + } + + pub async fn write_lb_info_to_pod_dir( + target_path: &Path, + lb_addrs: &[LoadBalancerIngress], + ) -> Result<(), Error> { + let addrs_path = target_path.join("addresses"); + tokio::fs::create_dir_all(&addrs_path).await?; + let mut default_addr_dir = None; + for addr in lb_addrs { + let addr_dir = addrs_path.join(&addr.address); + let ports_dir = addr_dir.join("ports"); + tokio::fs::create_dir_all(&ports_dir).await?; + tokio::fs::write(addr_dir.join("address"), addr.address.as_bytes()).await?; + for (port_name, port) in &addr.ports { + tokio::fs::write(ports_dir.join(port_name), port.to_string().as_bytes()).await?; + } + default_addr_dir.get_or_insert(addr_dir); + } + tokio::fs::symlink( + default_addr_dir + .context(NoDefaultLbSnafu)? + .strip_prefix(&target_path) + .context(DefaultAddrIsOutsideRootSnafu)?, + target_path.join("default-address"), + ) + .await?; + Ok(()) } } From 723f879d70d507519e6df9d652f3f4c5e4bd64a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 16 Aug 2022 16:36:05 +0200 Subject: [PATCH 19/99] Convert controller to use SNAFU errors too --- rust/lb-operator/src/lb_controller.rs | 81 ++++++++++++++++++--------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/rust/lb-operator/src/lb_controller.rs b/rust/lb-operator/src/lb_controller.rs index 39f062d6..7456e0ac 100644 --- a/rust/lb-operator/src/lb_controller.rs +++ b/rust/lb-operator/src/lb_controller.rs @@ -3,7 +3,7 @@ use crate::crd::{ LoadBalancerStatus, ServiceType, }; use futures::{future::try_join_all, StreamExt}; -use snafu::{ResultExt, Snafu}; +use snafu::{OptionExt, ResultExt, Snafu}; use stackable_operator::{ builder::OwnerReferenceBuilder, k8s_openapi::api::core::v1::{Endpoints, Node, Service, ServicePort, ServiceSpec}, @@ -61,10 +61,27 @@ pub struct Ctx { #[derive(Debug, Snafu, IntoStaticStr)] pub enum Error { + #[snafu(display("object has no namespace"))] + NoNs, + #[snafu(display("object has no name"))] + NoName, + #[snafu(display("object has no LoadBalancerClass (.spec.class_name)"))] + NoLbClass, + #[snafu(display("failed to get {obj}"))] + GetObject { + source: stackable_operator::error::Error, + obj: ObjectRef, + }, + #[snafu(display("failed to build owner reference to LoadBalancer"))] + BuildLbOwnerRef { + source: stackable_operator::error::Error, + }, + #[snafu(display("failed to apply {svc}"))] ApplyService { source: stackable_operator::error::Error, svc: ObjectRef, }, + #[snafu(display("failed to apply status for LoadBalancer"))] ApplyStatus { source: stackable_operator::error::Error, }, @@ -76,6 +93,11 @@ impl ReconcilerError for Error { fn secondary_object(&self) -> Option> { match self { + Self::NoNs => None, + Self::NoName => None, + Self::NoLbClass => None, + Self::GetObject { source: _, obj } => Some(obj.clone()), + Self::BuildLbOwnerRef { .. } => None, Self::ApplyService { source: _, svc } => Some(svc.clone().erase()), Self::ApplyStatus { source: _ } => None, } @@ -83,12 +105,15 @@ impl ReconcilerError for Error { } pub async fn reconcile(lb: Arc, ctx: Arc) -> Result { - let ns = lb.metadata.namespace.clone().unwrap(); + let ns = lb.metadata.namespace.clone().context(NoNsSnafu)?; + let lb_class_name = lb.spec.class_name.as_deref().context(NoLbClassSnafu)?; let lb_class = ctx .client - .get::(lb.spec.class_name.as_deref().unwrap(), None) + .get::(lb_class_name, None) .await - .unwrap(); + .with_context(|_| GetObjectSnafu { + obj: ObjectRef::::new(lb_class_name).erase(), + })?; let pod_ports = lb .spec .ports @@ -113,14 +138,15 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result>(); + let svc_name = lb.metadata.name.clone().context(NoNameSnafu)?; let svc = Service { metadata: ObjectMeta { namespace: Some(ns.clone()), - name: lb.metadata.name.clone(), + name: Some(svc_name.clone()), owner_references: Some(vec![OwnerReferenceBuilder::new() .initialize_from_resource(&*lb) .build() - .unwrap()]), + .context(BuildLbOwnerRefSnafu)?]), ..Default::default() }, spec: Some(ServiceSpec { @@ -150,9 +176,12 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result { let endpoints = ctx .client - .get_opt::(svc.metadata.name.as_deref().unwrap(), Some(&ns)) + .get_opt::(&svc_name, Some(&ns)) .await - .unwrap() + .with_context(|_| GetObjectSnafu { + obj: ObjectRef::::new(&svc_name).within(&ns).erase(), + })? + // Endpoints object may not yet be created by its respective controller .unwrap_or_default(); let node_names = endpoints .subsets @@ -162,13 +191,15 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result>(); - let nodes = try_join_all( - node_names - .iter() - .map(|node_name| ctx.client.get::(node_name, None)), - ) - .await - .unwrap(); + let nodes = try_join_all(node_names.iter().map(|node_name| async { + ctx.client + .get::(node_name, None) + .await + .context(GetObjectSnafu { + obj: ObjectRef::::new(node_name).erase(), + }) + })) + .await?; addresses = nodes .into_iter() .flat_map(|node| { @@ -184,12 +215,10 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result { @@ -203,12 +232,10 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result Date: Tue, 16 Aug 2022 16:49:53 +0200 Subject: [PATCH 20/99] Fix clippy warnings --- rust/lb-operator/src/grpc.rs | 2 ++ rust/lb-operator/src/utils.rs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/rust/lb-operator/src/grpc.rs b/rust/lb-operator/src/grpc.rs index c5adf86a..7a59f196 100644 --- a/rust/lb-operator/src/grpc.rs +++ b/rust/lb-operator/src/grpc.rs @@ -3,6 +3,8 @@ pub static FILE_DESCRIPTOR_SET_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/file_descriptor_set.bin")); +// Trivial warnings that come from prost-generated code +#[allow(clippy::derive_partial_eq_without_eq)] pub mod csi { pub mod v1 { tonic::include_proto!("csi.v1"); diff --git a/rust/lb-operator/src/utils.rs b/rust/lb-operator/src/utils.rs index d309bcc2..a98a163f 100644 --- a/rust/lb-operator/src/utils.rs +++ b/rust/lb-operator/src/utils.rs @@ -99,12 +99,13 @@ impl LowerHex for FmtByteSlice<'_> { /// Combines the messages of an error and its sources into a [`String`] of the form `"error: source 1: source 2: root error"` pub fn error_full_message(err: &dyn std::error::Error) -> String { + use std::fmt::Write; // Build the full hierarchy of error messages by walking up the stack until an error // without `source` set is encountered and concatenating all encountered error strings. let mut full_msg = format!("{}", err); let mut curr_err = err.source(); while let Some(curr_source) = curr_err { - full_msg.push_str(&format!(": {}", curr_source)); + write!(full_msg, ": {curr_source}").expect("string formatting should be infallible"); curr_err = curr_source.source(); } full_msg From d67ccea4475845e5eff6165a2f2020e4530c77c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 18 Aug 2022 17:00:08 +0200 Subject: [PATCH 21/99] Prioritize exposing node IP over CSI too --- rust/lb-operator/src/csi_server/node.rs | 30 ++++++++++++++----------- rust/lb-operator/src/lb_controller.rs | 19 ++++++---------- rust/lb-operator/src/utils.rs | 22 ++++++++++++++++++ 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index 8364166c..02fbea25 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -7,7 +7,7 @@ use serde::{ use snafu::{OptionExt, ResultExt, Snafu}; use stackable_operator::{ builder::OwnerReferenceBuilder, - k8s_openapi::api::core::v1::{PersistentVolume, Pod}, + k8s_openapi::api::core::v1::{Node, PersistentVolume, Pod}, kube::{ core::{DynamicObject, ObjectMeta}, runtime::reflector::ObjectRef, @@ -19,7 +19,7 @@ use tonic::{Request, Response, Status}; use crate::{ crd::{LoadBalancer, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec}, grpc::csi::{self, v1::Topology}, - utils::error_full_message, + utils::{error_full_message, node_primary_address}, }; use super::{tonic_unimplemented, LbSelector, LbVolumeContext}; @@ -153,7 +153,6 @@ impl csi::v1::node_server::Node for LbOperatorNode { }, }) } - // let get_obj = |name: &str, ns: Option<&str>| self.client.get(name, ns); let request = request.into_inner(); let LbNodeVolumeContext { @@ -224,16 +223,21 @@ impl csi::v1::node_server::Node for LbOperatorNode { .as_ref() .and_then(|status| status.node_ports.clone()) { - vec![LoadBalancerIngress { - address: pod - .spec - .as_ref() - .and_then(|s| s.node_name.clone()) - .with_context(|| PodHasNoNodeSnafu { - pod: ObjectRef::from_obj(&pod), - })?, - ports: node_ports, - }] + let node_name = pod + .spec + .as_ref() + .and_then(|s| s.node_name.as_deref()) + .with_context(|| PodHasNoNodeSnafu { + pod: ObjectRef::from_obj(&pod), + })?; + let node = get_obj::(&self.client, node_name, None).await?; + node_primary_address(&node) + .map(|address| LoadBalancerIngress { + address: address.to_string(), + ports: node_ports, + }) + .into_iter() + .collect() } else { lb.status .as_ref() diff --git a/rust/lb-operator/src/lb_controller.rs b/rust/lb-operator/src/lb_controller.rs index 7456e0ac..7be6c70d 100644 --- a/rust/lb-operator/src/lb_controller.rs +++ b/rust/lb-operator/src/lb_controller.rs @@ -1,6 +1,9 @@ -use crate::crd::{ - LoadBalancer, LoadBalancerClass, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec, - LoadBalancerStatus, ServiceType, +use crate::{ + crd::{ + LoadBalancer, LoadBalancerClass, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec, + LoadBalancerStatus, ServiceType, + }, + utils::node_primary_address, }; use futures::{future::try_join_all, StreamExt}; use snafu::{OptionExt, ResultExt, Snafu}; @@ -202,15 +205,7 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result String { full_msg } +pub fn node_primary_address(node: &Node) -> Option<&str> { + let addrs = node.status.as_ref().and_then(|s| s.addresses.as_ref()); + addrs + .into_iter() + .flatten() + .find(|addr| addr.type_ == "ExternalIP") + .or_else(|| { + addrs + .into_iter() + .flatten() + .find(|addr| addr.type_ == "InternalIP") + }) + .or_else(|| { + addrs + .into_iter() + .flatten() + .find(|addr| addr.type_ == "Hostname") + }) + .map(|addr| addr.address.as_str()) +} + #[cfg(test)] mod tests { use crate::utils::{error_full_message, FmtByteSlice}; From f194176a39128f041a9f64f73cb6be99a8cba3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 22 Aug 2022 11:08:09 +0200 Subject: [PATCH 22/99] CRD docs --- rust/lb-operator/src/crd.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/rust/lb-operator/src/crd.rs b/rust/lb-operator/src/crd.rs index 2ffaef0c..37bee59e 100644 --- a/rust/lb-operator/src/crd.rs +++ b/rust/lb-operator/src/crd.rs @@ -4,6 +4,10 @@ use serde::{Deserialize, Serialize}; use stackable_operator::kube::CustomResource; use stackable_operator::schemars::{self, JsonSchema}; +#[cfg(rustdoc)] +use stackable_operator::k8s_openapi::api::core::v1::{Pod, Service}; + +/// Defines a policy for how [`LoadBalancer`]s should be exposed. #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)] #[kube( group = "lb.stackable.tech", @@ -19,16 +23,25 @@ use stackable_operator::schemars::{self, JsonSchema}; #[serde(rename_all = "camelCase")] pub struct LoadBalancerClassSpec { pub service_type: ServiceType, + /// Annotations that should be added to the [`Service`] object. #[serde(default)] pub service_annotations: BTreeMap, } +/// The method used to access the services. #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)] pub enum ServiceType { + /// Reserve a port on each node. NodePort, + /// Provision a dedicated load balancer. LoadBalancer, } +/// Exposes a set of pods to the outside world. +/// +/// Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: +/// 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works +/// 2. It has a consistent API for reading back the exposed address(es) of the servuce #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default)] #[kube( group = "lb.stackable.tech", @@ -45,30 +58,48 @@ pub enum ServiceType { )] #[serde(rename_all = "camelCase")] pub struct LoadBalancerSpec { + /// The name of the [`LoadBalancerClass`]. pub class_name: Option, + /// Labels that the [`Pod`]s must share in order to be exposed. pub pod_selector: Option>, + /// Ports that should be exposed. pub ports: Option>, } #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct LoadBalancerPort { + /// The name of the port. + /// + /// The name of each port *must* be unique within a single [`LoadBalancer`]. pub name: String, + /// The port number. pub port: i32, + /// The layer-4 protocol (`TCP` or `UDP`). pub protocol: Option, } +/// Informs users about how to reach the [`LoadBalancer`]. #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct LoadBalancerStatus { + /// The backing Kubernetes [`Service`]. pub service_name: Option, + /// All addresses that the [`LoadBalancer`] is currently reachable from. pub ingress_addresses: Option>, + /// Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on. + /// + /// This is only intended for internal use by lb-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does + /// not require [`Node`]-local access. pub node_ports: Option>, } +/// One address that a [`LoadBalancer`] is accessible from. #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct LoadBalancerIngress { + /// The hostname or IP address to the [`LoadBalancer`]. pub address: String, + /// Port mapping table. pub ports: BTreeMap, } From e48db370c2cdd5fcad10a87fa6965bb034fdc6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 23 Aug 2022 16:43:59 +0200 Subject: [PATCH 23/99] Docs --- docs/antora.yml | 7 ++ .../ROOT/examples/lbclass-internal-gke.yaml | 9 ++ .../ROOT/examples/lbclass-public-gke.yaml | 7 ++ .../ROOT/examples/lbclass-public-onprem.yaml | 7 ++ docs/modules/ROOT/examples/usage-pod.yaml | 26 ++++++ docs/modules/ROOT/nav.adoc | 9 ++ docs/modules/ROOT/pages/building.adoc | 83 +++++++++++++++++++ docs/modules/ROOT/pages/commandline_args.adoc | 11 +++ docs/modules/ROOT/pages/configuration.adoc | 6 ++ docs/modules/ROOT/pages/index.adoc | 3 + docs/modules/ROOT/pages/installation.adoc | 29 +++++++ docs/modules/ROOT/pages/loadbalancer.adoc | 37 +++++++++ .../modules/ROOT/pages/loadbalancerclass.adoc | 28 +++++++ docs/modules/ROOT/pages/usage.adoc | 27 ++++++ docs/modules/ROOT/pages/volume.adoc | 6 ++ rust/lb-operator/src/csi_server/controller.rs | 3 + 16 files changed, 298 insertions(+) create mode 100644 docs/antora.yml create mode 100644 docs/modules/ROOT/examples/lbclass-internal-gke.yaml create mode 100644 docs/modules/ROOT/examples/lbclass-public-gke.yaml create mode 100644 docs/modules/ROOT/examples/lbclass-public-onprem.yaml create mode 100644 docs/modules/ROOT/examples/usage-pod.yaml create mode 100644 docs/modules/ROOT/nav.adoc create mode 100644 docs/modules/ROOT/pages/building.adoc create mode 100644 docs/modules/ROOT/pages/commandline_args.adoc create mode 100644 docs/modules/ROOT/pages/configuration.adoc create mode 100644 docs/modules/ROOT/pages/index.adoc create mode 100644 docs/modules/ROOT/pages/installation.adoc create mode 100644 docs/modules/ROOT/pages/loadbalancer.adoc create mode 100644 docs/modules/ROOT/pages/loadbalancerclass.adoc create mode 100644 docs/modules/ROOT/pages/usage.adoc create mode 100644 docs/modules/ROOT/pages/volume.adoc diff --git a/docs/antora.yml b/docs/antora.yml new file mode 100644 index 00000000..55024b97 --- /dev/null +++ b/docs/antora.yml @@ -0,0 +1,7 @@ +--- +name: lb-operator +version: "nightly" +title: Stackable LB Operator +nav: + - modules/ROOT/nav.adoc +prerelease: true diff --git a/docs/modules/ROOT/examples/lbclass-internal-gke.yaml b/docs/modules/ROOT/examples/lbclass-internal-gke.yaml new file mode 100644 index 00000000..4e796542 --- /dev/null +++ b/docs/modules/ROOT/examples/lbclass-internal-gke.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancerClass +metadata: + name: internal +spec: + serviceType: LoadBalancer + serviceAnnotations: + networking.gke.io/load-balancer-type: Internal diff --git a/docs/modules/ROOT/examples/lbclass-public-gke.yaml b/docs/modules/ROOT/examples/lbclass-public-gke.yaml new file mode 100644 index 00000000..66ad418d --- /dev/null +++ b/docs/modules/ROOT/examples/lbclass-public-gke.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancerClass +metadata: + name: public +spec: + serviceType: LoadBalancer diff --git a/docs/modules/ROOT/examples/lbclass-public-onprem.yaml b/docs/modules/ROOT/examples/lbclass-public-onprem.yaml new file mode 100644 index 00000000..ad238c75 --- /dev/null +++ b/docs/modules/ROOT/examples/lbclass-public-onprem.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancerClass +metadata: + name: public +spec: + serviceType: NodePort diff --git a/docs/modules/ROOT/examples/usage-pod.yaml b/docs/modules/ROOT/examples/usage-pod.yaml new file mode 100644 index 00000000..2436d3e1 --- /dev/null +++ b/docs/modules/ROOT/examples/usage-pod.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: v1 +kind: Pod +metadata: + name: example-secret-consumer +spec: + volumes: + - name: lb + ephemeral: # <1> + volumeClaimTemplate: + metadata: + annotations: + lb.stackable.tech/lb-class: public # <2> + spec: + storageClassName: lb.stackable.tech + accessModes: + - ReadWriteMany + resources: + requests: + storage: "1" + containers: + - name: nginx + image: nginx + volumeMounts: + - name: lb + mountPath: /lb # <3> diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc new file mode 100644 index 00000000..58dbb7e2 --- /dev/null +++ b/docs/modules/ROOT/nav.adoc @@ -0,0 +1,9 @@ +* xref:building.adoc[] +* xref:installation.adoc[] +* xref:configuration.adoc[] +* xref:usage.adoc[] +* Concepts +** xref:loadbalancer.adoc[] +** xref:loadbalancerclass.adoc[] +** xref:volume.adoc[] + diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc new file mode 100644 index 00000000..cb8a8b5a --- /dev/null +++ b/docs/modules/ROOT/pages/building.adoc @@ -0,0 +1,83 @@ += Building the Operator + +This operator is written in Rust. + +It is developed against the latest stable Rust release, and we currently don't support any older versions. + +However, the LB Operator is a https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface (CSI)] provider plugin +for the local Kubelet, which means that it should only be executed inside of a Kubernetes `Pod`. We currently support two ways of building the +Secret Operator: `docker build` and https://nixos.org/[Nix]. `docker build` is currently our primary deployment target, and our official images are built +using it. However, Nix has much faster incremental build and deploy times, making it ideal for local development. + +== Docker + +To build and deploy to the active Kind cluster, run: + +[source,console] +---- +$ echo Building with Docker +# Ensure that all submodules are up-to-date +$ git submodule update --recursive --init +# Update the Chart metadata and CRD definitions +$ make compile-chart +# Create a unique image ID +$ REPO=lb-operator +$ TAG="$(uuidgen)" +# Build the image +$ docker build . -f docker/Dockerfile -t "$REPO:$TAG" +# Load the image onto the Kind nodes +$ kind load docker-image "$REPO:$TAG" +# Deploy +$ helm upgrade lb-operator deploy/helm/lb-operator \ + --install \ + --set-string "image.repository=$REPO,image.tag=$TAG" +---- + +== Nix + +To build and deploy to the active Kind cluster, run: + +[source,console] +---- +$ echo Building with Nix +# Ensure that all submodules are up-to-date +$ git submodule update --recursive --init +# Ensure that the Cargo.lock is up-to-date +# This is not required if you use a tool that invokes Cargo regularly anyway, such as Rust-Analyzer +$ cargo generate-lockfile +# Use crate2nix (https://github.com/kolloch/crate2nix) to convert Cargo.lock into a Nix derivation +$ nix run -f . crate2nix generate +# Build the Docker images +$ nix build -f . docker +# Load the images onto the Kind nodes +# Nix does not use the Docker daemon, instead it builds individual layers, as well as a script (`result/load-image`) that combines them into a Docker image archive +$ kind load image-archive <(./result/load-image) +# Deploy +$ kubectl apply -f result/crds.yaml -f provisioner.yaml +$ kubectl rollout restart ds/lb-provisioner +---- + +You may need to add `extra-experimental-features = nix-command` to `/etc/nix/nix.conf`, or add `--experimental-features nix-command` to the Nix commands. + +You can also use https://tilt.dev/[Tilt] to automatically recompile and redeploy when files are changed: + +[source,console] +---- +$ nix run -f . tilt up +---- + +== K3d + +Secret-Operator, as with most CSI providers, requires the Kubernetes node's root folder to be mounted as `rshared`. K3d does not do this by default, +but can be prodded into doing this by running `mount --make-rshared /` in each node container. + +To do this for each running node K3d node, run the following script: + +[source,console] +---- +for i in $(k3d node list -o json | jq -r .[].name); do + docker exec -it $i mount --make-rshared / +done +---- + +NOTE: This is _not_ persistent, and must be re-executed every time the cluster (or a node in it) is restarted. diff --git a/docs/modules/ROOT/pages/commandline_args.adoc b/docs/modules/ROOT/pages/commandline_args.adoc new file mode 100644 index 00000000..e8828831 --- /dev/null +++ b/docs/modules/ROOT/pages/commandline_args.adoc @@ -0,0 +1,11 @@ +=== --csi-endpoint + +*Required*: true + +*Multiple values*: false + +*Environment variable:* `CSI_ENDPOINT` + +The path to the https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface] Unix Domain Socket +that the operator should listen on. + diff --git a/docs/modules/ROOT/pages/configuration.adoc b/docs/modules/ROOT/pages/configuration.adoc new file mode 100644 index 00000000..c347061a --- /dev/null +++ b/docs/modules/ROOT/pages/configuration.adoc @@ -0,0 +1,6 @@ += Configuration + +== Command Line Parameters +This operator accepts the following command line parameters: + +include::commandline_args.adoc[] diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc new file mode 100644 index 00000000..866a3c00 --- /dev/null +++ b/docs/modules/ROOT/pages/index.adoc @@ -0,0 +1,3 @@ += Stackable LB Operator + +This is an operator for Kubernetes that provisions load balancers and injects connection parameters into Pods. diff --git a/docs/modules/ROOT/pages/installation.adoc b/docs/modules/ROOT/pages/installation.adoc new file mode 100644 index 00000000..6f434deb --- /dev/null +++ b/docs/modules/ROOT/pages/installation.adoc @@ -0,0 +1,29 @@ += Installation + +There are two ways to run the Stackable LB Operator: + +1. Helm managed Docker container deployment on Kubernetes + +2. Build from source + + +== Helm +Helm allows you to download and deploy Stackable operators on Kubernetes and is by far the easiest installation method. First ensure that you have installed the Stackable Operators Helm repository: + +[source,console] +---- +$ helm repo add stackable https://repo.stackable.tech/repository/helm-stable/ +---- + +Then install the Stackable LB Operator + +[source,console] +---- +$ helm install lb-operator stackable/lb-operator +---- + +Helm will deploy the operator in Kubernetes containers and apply the CRDs. You're now ready to expose services! + +== Building the operator from source + +See xref:building.adoc[] for more information. diff --git a/docs/modules/ROOT/pages/loadbalancer.adoc b/docs/modules/ROOT/pages/loadbalancer.adoc new file mode 100644 index 00000000..ab50ff05 --- /dev/null +++ b/docs/modules/ROOT/pages/loadbalancer.adoc @@ -0,0 +1,37 @@ += `LoadBalancer` + +A `LoadBalancer` object exposes a set of `Pod`s according to the rules of a xref:loadbalancerclass.adoc[], but it also adds a couple of other +features that are useful for the Stackable platform at large. + +== `LoadBalancerClass` + +The exact rules of pod exposure is dictated by the specified xref:loadbalancerclass.adoc[], which allows a single `LoadBalancer` definition +to be reused exactly between many clusters, regardless of the Kubernetes distribution or cloud provider. + +== Address API + +`LoadBalancer` writes back all addresses that it can be reached on to `LoadBalancer.status.ingress_addresses`, which can then be used to generate +discovery information. Contrary to Kubernetes' `Service`, this is done regardless of the type of service, and transparently also contains information +about remapped ports. + +== Address volume projection + +`LoadBalancer` objects can be mounted into a `Pod` as a `PersistentVolumeClaim`, which contains information about how the `Pod` should request that +external clients refer to it. + +For example, if the volume is mounted to `/stackable/lb`, the primary address can be read from `/stackable/lb/default-address/address`, and the +public `http` port number can be read from `/stackable/lb/default-address/ports/http`. + +== Per-replica LBs + +A `LoadBalancer` PVC can also specify a xref:loadbalancerclass.adoc[] rather than a `LoadBalancer`, in which case a `LoadBalancer` object is created +automatically. These PVCs can automatically be created for each replica using either `StatefulSet` 's `volumeClaimTemplates` (for long-lived LBs that will +be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` (for temporary LBs that will be deleted when their corresponding `Pod` is). + +== Sticky scheduling + +When mounting a `LoadBalancer` PVC, it will be made "sticky" to that node if the xref:loadbalancerclass.adoc[] uses a strategy that depends on the node +that the workload is running on. + +Keep in mind that this will only work correctly when using long-lived PVCs (such as via `StatefulSet` 's `volumeClaimTemplates). Ephemeral PVCs +will be "reset" for every pod that is created, even if they refer to a long-lived `LoadBalancer` object. diff --git a/docs/modules/ROOT/pages/loadbalancerclass.adoc b/docs/modules/ROOT/pages/loadbalancerclass.adoc new file mode 100644 index 00000000..4323d036 --- /dev/null +++ b/docs/modules/ROOT/pages/loadbalancerclass.adoc @@ -0,0 +1,28 @@ += `LoadBalancerClass` + +A `LoadBalancerClass` defines a category of load balancers. For example, this could be "VPC-internal service", "internet-accessible service", or "K8s-internal service". +The `LoadBalancerClass` then defines how this intent is realized in a given cluster. + +For example, a Google Kubernetes Engine (GKE) cluster might want to expose all internet-facing services using a xref:loadbalancer.adoc[], since GKE nodes are +relatively short-lived and don't have stable addresses: + +[source,yaml] +---- +include::example$lbclass-public-gke.yaml[] +---- + +On the other hand, an on-premise cluster might not have dedicated load balancer infrastructure at all, but has "pet" Nodes with lifetimes on the orders +of years. This might lead administrators of such systems to prefer exposing node ports directly instead: + +[source,yaml] +---- +include::example$lbclass-public-onprem.yaml[] +---- + +Finally, it can be desirable to add additional annotations to a `Service`. For example, a user might want to only expose some services inside of a given +cloud vendor VPC. How exactly this is accomplished depends on the cloud provider in question, but for GKE this requires the annotation `networking.gke.io/load-balancer-type`: + +[source,yaml] +---- +include::example$lbclass-internal-gke.yaml[] +---- diff --git a/docs/modules/ROOT/pages/usage.adoc b/docs/modules/ROOT/pages/usage.adoc new file mode 100644 index 00000000..23fc2736 --- /dev/null +++ b/docs/modules/ROOT/pages/usage.adoc @@ -0,0 +1,27 @@ += Usage + +The operator creates a xref:loadbalancer.adoc[] for each mounted CSI volume with `driver: lb.stackable.tech`. + +A minimal exposed `Pod` looks like this: + +[source,yaml] +---- +include::example$usage-pod.yaml[] +---- +<1> Defines an _ephemeral_ load balancer, meaning that it will automatically be deleted when the `Pod` is. +<2> Defines that we want to expose this pod by automatically creating a service according to the xref:loadbalancerclass.adoc[] `public`. +<3> Mounts metadata about the `LoadBalancer` (such as the port mapping and IP address) into `/lb`. The volume *must* be mounted, even if this data is never used by the `Pod` itself. + +The exact xref:loadbalancerclass.adoc[] is going to depend on the Kubernetes environment, but should often look like this for public clouds: + +[source,yaml] +---- +include::example$lbclass-public-gke.yaml[] +---- + +Or like this for on-premise environments: + +[source,yaml] +---- +include::example$lbclass-public-onprem.yaml[] +---- diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc new file mode 100644 index 00000000..90a7c203 --- /dev/null +++ b/docs/modules/ROOT/pages/volume.adoc @@ -0,0 +1,6 @@ += Volume + +TODO: Expand severely. + +lb-operator acts as a CSI `PersistentVolume`, which helps it stabilize network addresses, inject pod metadata, and exposing individual pods. + diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs index bdd4eeb4..d6b2f9f9 100644 --- a/rust/lb-operator/src/csi_server/controller.rs +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -137,6 +137,8 @@ impl csi::v1::controller_server::Controller for LbOperatorController { volume_context: raw_volume_context.into_iter().collect(), content_source: None, accessible_topology: match lb_class.spec.service_type { + // Pick the top node (as selected by the CSI client) and "stick" to that + // Since we want clients to have a stable address to connect to ServiceType::NodePort => request .accessibility_requirements .unwrap_or_default() @@ -144,6 +146,7 @@ impl csi::v1::controller_server::Controller for LbOperatorController { .into_iter() .take(1) .collect(), + // Load balancers have no relationship to any particular node, so don't try to be sticky ServiceType::LoadBalancer => Vec::new(), }, }), From 6db022a11f792e8307d89925afe7ada937be0816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 24 Aug 2022 11:14:03 +0200 Subject: [PATCH 24/99] LB volume documentation --- docs/modules/ROOT/pages/volume.adoc | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index 90a7c203..129458b4 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -4,3 +4,57 @@ TODO: Expand severely. lb-operator acts as a CSI `PersistentVolume`, which helps it stabilize network addresses, inject pod metadata, and exposing individual pods. +== Stable addresses + +Some xref:loadbalancerclass.adoc[] strategies, such as `NodePort`, tie the public address to the Kubernetes node that the `Pod` is running on. When this address must be configured statically in clients +(such as for HDFS NameNodes), then Kubernetes' default "floating" scheduling either requires all clients to be reconfigured every time something moves, or for all clients to proxy their traffic through +a single static node, which then becomes a single point of failure (along with the node that the workload is running on). + +Mounting load balancers into Pods as `PersistentVolume` allows lb-operator to pin these workloads to one node. Note that this only happens for xref:loadbalancerclass.adoc[] es that actually benefit +from pinning. + +== Pod metadata injection + +Some services (such as Kafka) need to know their external address, so that they can advertise it to their own replica discovery mechanism. xref:loadbalancer.adoc[] volumes contain a file tree that exposes +this information: + +[source] +---- +- `default-address/`- symlink to `addresses/\{primary address\}` +- `addresses/` - Contains information about all addresses associated with this xref:loadbalancer.adoc[] + - `\{address\}/` - A folder is created for each address + - `address` - Contains the Pod's address (IP address or hostname) + - `ports/` - Contains port numbers for each named port + - `\{port name\}` - Contains the public port number for this named port +---- + +== Individual pod exposure + +Sometimes each replica much be exposed individually, for example because clients need to access data on a specific shard. `PersistentVolumeClaim` templates can be used to provision this automatically. + +=== `StatefulSet` `volumeClaimTemplates` + +`volumeClaimTemplates` allows volumes to be provisioned for each `StatefulSet` replica. These volumes are _persistent_, and will not be deleted when the `Pod` or `StatefulSet` is. This makes them +useful for provisioning addresses that must be hard-coded into client configuration. + +=== Pod-scoped ephemeral volumes + +`Pod.spec.volumes[].ephemeral` allows volumes to be provisioned for each `Pod`. These volumes are tied to the lifetime of the `Pod` and will be deleted when it is. This makes them useful for provisioning +temporary addresses that will be discovered out of band (such as for HDFS DataNodes). + +== Reference + +All configuration must be specified as `annotations` on the `PersistentVolumeClaim`. The following attributes are currently supported: + +=== `lb.stackable.tech/lb-name` + +*Required*: If `lb.stackable.tech/lb-class` is not specified + +Provisions metadata about an existing xref:loadbalancer.adoc[] that was created manually. + +=== `lb.stackable.tech/lb-class` + +*Required*: If `lb.stackable.tech/lb-name` is not specified + +Provisions a new xref:loadbalancer.adoc[] using the specified xref:loadbalancerclass.adoc[]. The created xref:loadbalancer.adoc[] will expose +all of the `Pod` 's ports. From 2ad7bd396d78dfbc400e48e921c913fe598286c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 24 Aug 2022 14:24:45 +0200 Subject: [PATCH 25/99] Change example pod name to something more appropriate --- docs/modules/ROOT/examples/usage-pod.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/examples/usage-pod.yaml b/docs/modules/ROOT/examples/usage-pod.yaml index 2436d3e1..1237f94b 100644 --- a/docs/modules/ROOT/examples/usage-pod.yaml +++ b/docs/modules/ROOT/examples/usage-pod.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Pod metadata: - name: example-secret-consumer + name: example-public-pod spec: volumes: - name: lb From 8b3d8828423e617da6024d816d7a4a3f8413ca31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 24 Aug 2022 14:50:53 +0200 Subject: [PATCH 26/99] Initial templating --- .dockerignore | 9 + .flake8 | 2 + .github/ISSUE_TEMPLATE/bug_report.yml | 49 +++ .github/ISSUE_TEMPLATE/config.yml | 12 + .github/ISSUE_TEMPLATE/new_version.md | 34 ++ .github/pull_request_template.md | 18 + .github/workflows/build.yml | 356 ++++++++++++++++++ .github/workflows/daily_security.yml | 20 + .github/workflows/reviewdog.yaml | 62 +++ .gitignore | 15 +- .markdownlint.yaml | 20 + .pre-commit-config.yaml | 35 ++ .pylintrc | 9 + .yamllint.yaml | 14 + Makefile | 70 ++++ bors.toml | 9 + deny.toml | 62 +++ deploy/DO_NOT_EDIT.md | 10 + deploy/helm/ct.yaml | 8 + deploy/helm/lb-operator/Chart.yaml | 6 +- deploy/helm/lb-operator/README.md | 4 +- deploy/helm/lb-operator/crds/crds.yaml | 182 ++++++--- .../helm/lb-operator/templates/configmap.yaml | 2 +- .../lb-operator/templates/serviceaccount.yaml | 8 +- deploy/manifests/Kustomization | 8 + deploy/manifests/configmap.yaml | 10 + deploy/manifests/crds.yaml | 153 ++++++++ deploy/manifests/csidriver.yaml | 12 + deploy/manifests/daemonset.yaml | 73 ++++ deploy/manifests/deployment.yaml | 3 + deploy/manifests/lb-classes.yaml | 14 + deploy/manifests/roles.yaml | 77 ++++ deploy/manifests/serviceaccount.yaml | 27 ++ deploy/manifests/storageclass.yaml | 7 + docker/Dockerfile | 35 ++ docs/antora.yml | 4 +- python/cargo_version.py | 197 ++++++++++ python/requirements.txt | 2 + renovate.json | 32 ++ scripts/docs_templating.sh | 41 ++ scripts/generate-manifests.sh | 21 ++ scripts/run_tests.sh | 29 ++ tests/README-templating.md | 83 ++++ tests/ansible/playbook.yaml | 6 + tests/ansible/requirements.yaml | 4 + tests/kuttl-test.yaml.jinja2 | 11 + tests/templates/.gitkeep | 0 47 files changed, 1794 insertions(+), 71 deletions(-) create mode 100644 .dockerignore create mode 100644 .flake8 create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/new_version.md create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/daily_security.yml create mode 100644 .github/workflows/reviewdog.yaml create mode 100644 .markdownlint.yaml create mode 100644 .pre-commit-config.yaml create mode 100644 .pylintrc create mode 100644 .yamllint.yaml create mode 100644 Makefile create mode 100644 bors.toml create mode 100644 deny.toml create mode 100644 deploy/DO_NOT_EDIT.md create mode 100644 deploy/helm/ct.yaml create mode 100644 deploy/manifests/Kustomization create mode 100644 deploy/manifests/configmap.yaml create mode 100644 deploy/manifests/crds.yaml create mode 100644 deploy/manifests/csidriver.yaml create mode 100644 deploy/manifests/daemonset.yaml create mode 100644 deploy/manifests/deployment.yaml create mode 100644 deploy/manifests/lb-classes.yaml create mode 100644 deploy/manifests/roles.yaml create mode 100644 deploy/manifests/serviceaccount.yaml create mode 100644 deploy/manifests/storageclass.yaml create mode 100644 docker/Dockerfile create mode 100755 python/cargo_version.py create mode 100644 python/requirements.txt create mode 100644 renovate.json create mode 100755 scripts/docs_templating.sh create mode 100755 scripts/generate-manifests.sh create mode 100755 scripts/run_tests.sh create mode 100644 tests/README-templating.md create mode 100644 tests/ansible/playbook.yaml create mode 100644 tests/ansible/requirements.yaml create mode 100644 tests/kuttl-test.yaml.jinja2 create mode 100644 tests/templates/.gitkeep diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..38ad1963 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +debug/ +target/ +**/*.rs.bk + +.idea/ +*.iws + +# We do NOT want to ignore .git because we use the `built` crate to gather the current git commit hash at built time +# This means we need the .git directory in our Docker image, it will be thrown away and won't be included in the final image diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..ea6646f3 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +ignore = E111,E501,E114 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..465d3a9a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,49 @@ +--- +name: "🐛 Bug Report" +description: "If something isn't working as expected 🤔." +labels: ["type/bug"] +body: + - type: markdown + attributes: + value: Thanks for taking the time to file a bug report! Please fill out this form as completely as possible. + + - type: input + attributes: + label: Affected version + description: Which version do you see this bug in? + + - type: textarea + attributes: + label: Current and expected behavior + description: A clear and concise description of what the operator is doing and what you would expect. + validations: + required: true + + - type: textarea + attributes: + label: Possible solution + description: "If you have suggestions on a fix for the bug." + + - type: textarea + attributes: + label: Additional context + description: "Add any other context about the problem here. Or a screenshot if applicable." + + - type: textarea + attributes: + label: Environment + description: | + What type of kubernetes cluster you are running aginst (k3s/eks/aks/gke/other) and any other information about your environment? + placeholder: | + Examples: + Output of `kubectl version --short` + + - type: dropdown + attributes: + label: Would you like to work on fixing this bug? + description: | + **NOTE**: Let us know if you would like to submit a PR for this. We are more than happy to help you through the process. + options: + - "yes" + - "no" + - "maybe" diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..54e2c297 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,12 @@ +--- +blank_issues_enabled: true +contact_links: + - name: Feature request + about: 🚀 Suggest an idea for this project + url: https://github.com/stackabletech/lb-operator/discussions/new?category=ideas + - name: 🙋🏾 Question + about: Use this to ask a question about this project + url: https://github.com/stackabletech/lb-operator/discussions/new?category=q-a + - name: Other issue + about: Open an issue that doesn't fit any other category + url: https://github.com/stackabletech/lb-operator/issues/new diff --git a/.github/ISSUE_TEMPLATE/new_version.md b/.github/ISSUE_TEMPLATE/new_version.md new file mode 100644 index 00000000..ea1a5075 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new_version.md @@ -0,0 +1,34 @@ +--- +name: New Version +about: Request support for a new product version +title: "[NEW VERSION]" +labels: '' +assignees: '' + +--- + +**Which new version of Stackable Load Balancer Operator should we support?** + +Please specify the version, version range or version numbers to support, please also add these to the issue title + +**Additional information** + +If possible, provide a link to release notes/changelog + +**Changes required** + +Are there any upstream changes that we need to support? +e.g. new features, changed features, deprecated features etc. + + + +**Implementation checklist** + +Please don't change anything in this list. +Not all of these steps are necessary for all versions. + +- [ ] Update the Docker image +- [ ] Update documentation to include supported version(s) +- [ ] Update operator to support the new version (if needed) +- [ ] Update integration tests to test use the new versions (in addition or replacing old versions +- [ ] Update examples to use new versions diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..c2dd7295 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,18 @@ + +# Description + +*Please add a description here. This will become the commit message of the merge request later.* + + + +## Review Checklist + +- [ ] Code contains useful comments +- [ ] CRD change approved (or not applicable) +- [ ] (Integration-)Test cases added (or not applicable) +- [ ] Documentation added (or not applicable) +- [ ] Changelog updated (or not applicable) +- [ ] Cargo.toml only contains references to git tags (not specific commits or branches) +- [ ] Helm chart can be installed and deployed operator works (or not applicable) + +Once the review is done, comment `bors r+` (or `bors merge`) to merge. [Further information](https://bors.tech/documentation/getting-started/#reviewing-pull-requests) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..036993fb --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,356 @@ +--- +name: Stackable Build Pipeline + +on: + push: + branches: + - main + - staging + - trying + - "renovate/**" + tags: + - "*" + pull_request: + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: '0' + CARGO_PROFILE_DEV_DEBUG: '0' + RUSTFLAGS: "-D warnings" + RUSTDOCFLAGS: "-D warnings" + RUST_LOG: "info" + OPERATOR_NAME: "lb-operator" + PRODUCT_NAME: "lb-operator" + DEV_REPO_HELM_URL: https://repo.stackable.tech/repository/helm-dev + TEST_REPO_HELM_URL: https://repo.stackable.tech/repository/helm-test + STABLE_REPO_HELM_URL: https://repo.stackable.tech/repository/helm-stable + +jobs: + # Identify unused dependencies + run_udeps: + name: Run Cargo Udeps + runs-on: ubuntu-latest + env: + RUSTC_BOOTSTRAP: 1 + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # renovate: tag=v1.0.7 + with: + profile: minimal + toolchain: stable + override: true + - uses: Swatinem/rust-cache@6720f05bc48b77f96918929a9019fb2203ff71f8 # tag=v2.0.0 + with: + key: udeps + - uses: actions-rs/cargo@844f36862e911db73fe0815f00a4a2602c279505 # renovate: tag=v1.0.3 + with: + command: install + args: cargo-udeps --locked + - uses: actions-rs/cargo@844f36862e911db73fe0815f00a4a2602c279505 # renovate: tag=v1.0.3 + with: + command: udeps + + prerelease_job: + name: Returns the pre-release string from the version of the cargo workspace. + runs-on: ubuntu-latest + outputs: + str: ${{ steps.prerelease.outputs.str }} + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # tag=v4 + - name: Install requirements for version tool + run: pip install -r python/requirements.txt + - id: prerelease + name: Extract the pre-release string. Might be empty. + run: | + PRERELEASE=$(python/cargo_version.py -o | sed "s/^[0-9]\+\.[0-9]\+\.[0-9]\+-\?//g") + echo "::set-output name=str::$PRERELEASE" + + # This job evaluates the github environment to determine why this action is running and selects the appropriate + # target repository for published Helm charts based on this. + # + # The following scenarios are identified: + # - pull request: + # condition: github.event_name == "pull_request" + # repository: test + # + # - release (aka a tag was created): + # condition: github.event_name == 'create' & github.ref.startswith('refs/tags/') + # repository: stable + # + # - merge of pr to main branch and pre release is nightly: + # condition: github.event_name == 'push' & github.ref == 'refs/heads/main' & needs.prerelease_job.outputs.str == 'nightly' + # repository: dev + # + # Any other scenarios will cause the publish step to be skipped, most commonly this is expected to happen for the + # branches that bors uses internally (staging, trying) for which the checks need to run, but we do not want artifacts + # to be published. + select_repo: + name: Select target repository based on action trigger + runs-on: ubuntu-latest + outputs: + repository: ${{ steps.selectrepo.outputs.repo }} + needs: prerelease_job + steps: + - id: selectrepo + env: + TRIGGER: ${{ github.event_name }} + GITHUB_REF: ${{ github.ref }} + PRERELEASE: ${{ needs.prerelease_job.outputs.str }} + run: | + if [[ $TRIGGER == "pull_request" ]]; then + echo "exporting test as target repo: ${{ env.TEST_REPO_HELM_URL }}" + echo "::set-output name=repo::${{ env.TEST_REPO_HELM_URL }}" + elif [[ $TRIGGER == "push" && $GITHUB_REF == "refs/heads/main" && $PRERELEASE == 'nightly' ]]; then + echo "exporting dev as target repo: ${{ env.DEV_REPO_HELM_URL }}" + echo "::set-output name=repo::${{ env.DEV_REPO_HELM_URL }}" + elif [[ ( $TRIGGER == "create" || $TRIGGER == "push" ) && $GITHUB_REF == refs/tags/* ]]; then + echo "exporting stable as target repo: ${{ env.STABLE_REPO_HELM_URL }}" + echo "::set-output name=repo::${{ env.STABLE_REPO_HELM_URL }}" + else + echo "Unknown trigger and ref combination encountered, skipping publish step: $TRIGGER $GITHUB_REF" + echo "::set-output name=repo::skip" + fi + + run_cargodeny: + name: Run Cargo Deny + runs-on: ubuntu-latest + strategy: + matrix: + checks: + - advisories + - bans licenses sources + + # Prevent sudden announcement of a new advisory from failing ci: + continue-on-error: ${{ matrix.checks == 'advisories' }} + + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - uses: EmbarkStudios/cargo-deny-action@7257a18a9c2fe3f92b85d41ae473520dff953c97 # tag=v1.3.2 + with: + command: check ${{ matrix.checks }} + + run_rustfmt: + name: Run Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # renovate: tag=v1.0.7 + with: + profile: minimal + toolchain: stable + components: rustfmt + override: true + - uses: actions-rs/cargo@844f36862e911db73fe0815f00a4a2602c279505 # renovate: tag=v1.0.3 + with: + command: fmt + args: --all -- --check + + run_clippy: + name: Run Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # renovate: tag=v1.0.7 + with: + profile: minimal + toolchain: stable + components: clippy + override: true + - uses: Swatinem/rust-cache@6720f05bc48b77f96918929a9019fb2203ff71f8 # tag=v2.0.0 + with: + key: clippy + - name: Run clippy action to produce annotations + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: actions-rs/clippy-check@b5b5f21f4797c02da247df37026fcd0a5024aa4d # renovate: tag=v1.0.7 + if: env.GITHUB_TOKEN != null + with: + args: --all-targets -- -D warnings + token: ${{ secrets.GITHUB_TOKEN }} + - name: Run clippy manually without annotations + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: env.GITHUB_TOKEN == null + run: cargo clippy --all-targets -- -D warnings + + run_rustdoc: + name: Run RustDoc + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # renovate: tag=v1.0.7 + with: + profile: minimal + toolchain: stable + components: rustfmt + override: true + - uses: Swatinem/rust-cache@6720f05bc48b77f96918929a9019fb2203ff71f8 # tag=v2.0.0 + with: + key: doc + - uses: actions-rs/cargo@844f36862e911db73fe0815f00a4a2602c279505 # renovate: tag=v1.0.3 + with: + command: doc + args: --document-private-items + + run_tests: + name: Run Cargo Tests + needs: + - run_cargodeny + - run_clippy + - run_rustfmt + - run_rustdoc + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # renovate: tag=v1.0.7 + with: + profile: minimal + toolchain: stable + override: true + - uses: Swatinem/rust-cache@6720f05bc48b77f96918929a9019fb2203ff71f8 # tag=v2.0.0 + with: + key: test + - uses: actions-rs/cargo@844f36862e911db73fe0815f00a4a2602c279505 # renovate: tag=v1.0.3 + with: + command: test + + # This job cleans up the CRDs, Helm charts and Kustomize manifests, followed by rebuilding them + # It then runs a `git diff` and fails the entire workflow, if any difference is encountered. + # + # Since CRD files are generated during the 'cargo build' process we need to run this once after + # removing the CRD files to ensure that the checked in versions match what the code expects. + # + # The reason for this step is, that developers are expected to check in up-to-date versions of charts + # and manifests, as we'd otherwise have to build these in CI and commit them back to the PR, which + # creates all kinds of problems. + # Therefor this failsafe simply aborts anything that has not had charts and manifests rebuilt before pushing. + check_charts: + name: Check if committed Helm & Kustomize Charts were up to date + needs: + - run_cargodeny + - run_clippy + - run_rustfmt + - run_rustdoc + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - name: Set up Helm + uses: azure/setup-helm@b5b231a831f96336bbfeccc1329990f0005c5bb1 # tag=v3.3 + with: + version: v3.6.2 + - name: Set up cargo + uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # renovate: tag=v1.0.7 + with: + profile: minimal + toolchain: stable + override: true + - name: Set up rust-cache + uses: Swatinem/rust-cache@6720f05bc48b77f96918929a9019fb2203ff71f8 # tag=v2.0.0 + with: + key: charts + - name: Regenerate charts + run: make regenerate-charts + - name: Check if committed charts were up to date + run: git diff --exit-code + - name: Git Diff showed uncommitted changes + if: ${{ failure() }} + uses: actions/github-script@d50f485531ba88479582bc2da03ff424389af5c1 # tag=v6 + with: + script: | + core.setFailed('Committed charts were not up to date, please regenerate and re-commit!') + + test_charts: + name: Run Chart Tests + needs: + - check_charts + - run_tests + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - name: placeholder + run: echo Tests will go here + + tests_passed: + name: All tests passed + needs: + - test_charts + - run_udeps + runs-on: ubuntu-latest + steps: + - name: log + run: echo All tests have passed! + + package_and_publish: + name: Package Charts, Build Docker Image and publish them + needs: + - tests_passed + - select_repo + runs-on: ubuntu-latest + env: + NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} + REPO: ${{ needs.select_repo.outputs.repository }} + if: needs.select_repo.outputs.repository != 'skip' + steps: + - name: Checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + with: + submodules: recursive + - uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # tag=v4 + if: ${{ github.event_name == 'pull_request' }} + - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # renovate: tag=v1.0.7 + with: + profile: minimal + toolchain: stable + components: rustfmt + override: true + - name: Install requirements for version tool + if: ${{ github.event_name == 'pull_request' }} + run: pip install -r python/requirements.txt + + # This step checks if the current run was triggered by a push to a pr (or a pr being created). + # If this is the case it changes the version of this project in all Cargo.toml files to include the suffix + # "-pr" so that the published artifacts can be linked to this PR. + - name: Update version if PR + if: ${{ github.event_name == 'pull_request' }} + run: python/cargo_version.py -m pr${{ github.event.pull_request.number }} + + # Recreate charts with changed version if needed + - name: Clean charts + if: ${{ github.event_name == 'pull_request' }} + run: make chart-clean clean-manifests compile-chart generate-manifests + + # Package and publish charts + - name: Package Chart + run: mkdir -p target/helm && helm package --destination target/helm deploy/helm/${{ env.OPERATOR_NAME }} + - name: Build Docker image + if: env.NEXUS_PASSWORD != null # pragma: allowlist secret + run: make docker + - name: Publish Chart + if: env.NEXUS_PASSWORD != null # pragma: allowlist secret + run: >- + /usr/bin/curl + --fail + -u 'github:${{ secrets.NEXUS_PASSWORD }}' + --upload-file "./$(find target/helm/ -name '*.tgz')" + "${{ env.REPO }}/" diff --git a/.github/workflows/daily_security.yml b/.github/workflows/daily_security.yml new file mode 100644 index 00000000..b609d366 --- /dev/null +++ b/.github/workflows/daily_security.yml @@ -0,0 +1,20 @@ +# ============= +# This file is automatically generated from the templates in stackabletech/operator-templating +# DON'T MANUALLY EDIT THIS FILE +# ============= +--- +name: Security audit + +on: + schedule: + - cron: '15 4 * * *' + workflow_dispatch: + +jobs: + audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + - uses: actions-rs/audit-check@35b7b53b1e25b55642157ac01b4adceb5b9ebef3 # renovate: tag=v1.2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reviewdog.yaml b/.github/workflows/reviewdog.yaml new file mode 100644 index 00000000..67a11e40 --- /dev/null +++ b/.github/workflows/reviewdog.yaml @@ -0,0 +1,62 @@ +--- +name: reviewdog +on: + pull_request + +permissions: + contents: read + checks: write + pull-requests: write + issues: write + +jobs: + actionlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + - uses: reviewdog/action-actionlint@12f228ecba8c567a103efafb3fb0bf5b60dc16b7 # tag=v1.27.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + flake8: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + - uses: actions/setup-python@b55428b1882923874294fa556849718a1d7f2ca5 # tag=v4 + with: + python-version: "3.9" + - uses: reviewdog/action-flake8@b6435e67f0cfda225b9e0c9283cfb7ea7c551bdb # tag=v3.6.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + hadolint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + - uses: reviewdog/action-hadolint@55be5d2c4b0b80d439247b128a9ded3747f92a29 # tag=v1.33.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + markdownlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + - uses: reviewdog/action-markdownlint@b8f945b8bee2a2967214f35956209bc31d3c4d26 # tag=v0.7.1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + shellcheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + - uses: reviewdog/action-shellcheck@66c9a47bf02255b250284a82251cb4cadf5043f5 # tag=v1.15.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + yamllint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 + - uses: reviewdog/action-yamllint@8c429dfe4fc47b1ce1fa99a64e94693880d5dc30 # tag=v1.6.1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 52d87385..65ef2553 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,15 @@ -/target -/result +tests/ansible/roles/ +tests/_work/ +debug/ +target/ +**/*.rs.bk + +.idea/ +*.iws +*.iml + +*.tgz + Cargo.nix crate-hashes.json +result diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 00000000..dbfa4558 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,20 @@ +--- +# All defaults or options can be checked here: +# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml + +# Default state for all rules +default: true + +# MD013/line-length - Line length +MD013: + # Number of characters + line_length: 9999 + # Number of characters for headings + heading_line_length: 9999 + # Number of characters for code blocks + code_block_line_length: 9999 + +# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content +MD024: + # Only check sibling headings + siblings_only: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..7153b386 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +--- +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.2.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: detect-aws-credentials + args: ["--allow-missing-credentials"] + - id: detect-private-key + + - repo: https://github.com/doublify/pre-commit-rust + rev: v1.0 + hooks: + - id: fmt + args: ["--all", "--", "--check"] + - id: clippy + args: ["--all-targets", "--", "-D", "warnings"] + + - repo: https://github.com/adrienverge/yamllint + rev: v1.26.3 + hooks: + - id: yamllint + + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.31.1 + hooks: + - id: markdownlint + + - repo: https://github.com/PyCQA/flake8 + rev: 4.0.1 + hooks: + - id: flake8 diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 00000000..5df27e82 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,9 @@ +[MESSAGES CONTROL] + +# These rules are for missing docstrings which doesn't matter much for most of our simple scripts +disable=C0114,C0115,C0116 + +[FORMAT] + +max-line-length=999 +indent-string=' ' diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 00000000..769cda16 --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,14 @@ +--- +extends: default + +ignore: | + deploy/helm/**/templates + +rules: + line-length: disable + truthy: + check-keys: false + comments: + min-spaces-from-content: 1 # Needed due to https://github.com/adrienverge/yamllint/issues/443 + indentation: + indent-sequences: consistent diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..8d6364f4 --- /dev/null +++ b/Makefile @@ -0,0 +1,70 @@ +# ============= +# This file is automatically generated from the templates in stackabletech/operator-templating +# DO NOT MANUALLY EDIT THIS FILE +# ============= + +# This script requires https://github.com/mikefarah/yq (not to be confused with https://github.com/kislyuk/yq) +# It is available from Nixpkgs as `yq-go` (`nix shell nixpkgs#yq-go`) + +.PHONY: docker chart-lint compile-chart + +TAG := $(shell git rev-parse --short HEAD) + +VERSION := $(shell cargo metadata --format-version 1 | jq -r '.packages[] | select(.name=="stackable-lb-operator") | .version') +IS_NIGHTLY := $(shell echo "${VERSION}" | grep -- '-nightly$$') +# When rendering docs we want to simplify the version number slightly, only rendering "nightly" for nightly branches +# (since we only render nightlies for the active development trunk anyway) and chopping off the semver patch version otherwise +DOCS_VERSION := $(if ${IS_NIGHTLY},nightly,$(shell echo "${VERSION}" | sed 's/^\([0-9]\+\.[0-9]\+\)\..*$$/\1/')) +export VERSION IS_NIGHTLY DOCS_VERSION + +SHELL=/usr/bin/env bash -euo pipefail + +## Docker related targets +docker-build: + docker build --force-rm --build-arg VERSION=${VERSION} -t "docker.stackable.tech/stackable/lb-operator:${VERSION}" -f docker/Dockerfile . + +docker-build-latest: docker-build + docker tag "docker.stackable.tech/stackable/lb-operator:${VERSION}" \ + "docker.stackable.tech/stackable/lb-operator:latest" + +docker-publish: + echo "${NEXUS_PASSWORD}" | docker login --username github --password-stdin docker.stackable.tech + docker push --all-tags docker.stackable.tech/stackable/lb-operator + +docker: docker-build docker-publish + +docker-release: docker-build-latest docker-publish + +## Chart related targets +compile-chart: version crds config + +chart-clean: + rm -rf deploy/helm/lb-operator/configs + rm -rf deploy/helm/lb-operator/crds + +version: + yq eval -i '.version = strenv(VERSION) | .appVersion = strenv(VERSION)' /dev/stdin < deploy/helm/lb-operator/Chart.yaml + yq eval -i '.version = strenv(DOCS_VERSION) | .prerelease = strenv(IS_NIGHTLY) != ""' /dev/stdin < docs/antora.yml + +config: + if [ -d "deploy/config-spec/" ]; then\ + mkdir -p deploy/helm/lb-operator/configs;\ + cp -r deploy/config-spec/* deploy/helm/lb-operator/configs;\ + fi + +crds: + mkdir -p deploy/helm/lb-operator/crds + cargo run --bin stackable-lb-operator -- crd | yq eval '.metadata.annotations["helm.sh/resource-policy"]="keep"' - > deploy/helm/lb-operator/crds/crds.yaml + +chart-lint: compile-chart + docker run -it -v $(shell pwd):/build/helm-charts -w /build/helm-charts quay.io/helmpack/chart-testing:v3.5.0 ct lint --config deploy/helm/ct.yaml + +## Manifest related targets +clean-manifests: + mkdir -p deploy/manifests + rm -rf $$(find deploy/manifests -maxdepth 1 -mindepth 1 -not -name Kustomization) + +generate-manifests: clean-manifests compile-chart + ./scripts/generate-manifests.sh + +regenerate-charts: chart-clean clean-manifests compile-chart generate-manifests diff --git a/bors.toml b/bors.toml new file mode 100644 index 00000000..420d30c8 --- /dev/null +++ b/bors.toml @@ -0,0 +1,9 @@ +status = [ + 'All tests passed' +] +delete_merged_branches = true +use_squash_merge = true +pr_status = [ 'license/cla' ] +timeout_sec = 7200 +cut_body_after = "" +required_approvals = 1 diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000..0363c332 --- /dev/null +++ b/deny.toml @@ -0,0 +1,62 @@ +targets = [ + { triple = "x86_64-unknown-linux-gnu" }, + { triple = "aarch64-unknown-linux-gnu" }, + { triple = "x86_64-unknown-linux-musl" }, + { triple = "aarch64-apple-darwin" }, + { triple = "x86_64-apple-darwin" }, +] + +[advisories] +vulnerability = "warn" +unmaintained = "allow" +unsound = "warn" +yanked = "warn" +notice = "warn" + +[bans] +multiple-versions = "allow" + +[licenses] +unlicensed = "deny" +copyleft = "deny" +allow-osi-fsf-free = "neither" +default = "deny" +confidence-threshold = 1.0 +allow = [ + "Apache-2.0", + "BSD-3-Clause", + "CC0-1.0", + "ISC", + "LicenseRef-ring", + "LicenseRef-webpki", + "MIT", + "Unicode-DFS-2016", + "Zlib" +] + +exceptions = [ + { name = "stackable-lb-operator-crd", allow = ["OSL-3.0"] }, + { name = "stackable-lb-operator", allow = ["OSL-3.0"] }, + { name = "stackable-lb-operator-binary", allow = ["OSL-3.0"] }, + ] + +[[licenses.clarify]] +name = "ring" +expression = "LicenseRef-ring" +license-files = [ + { path = "LICENSE", hash = 0xbd0eed23 }, +] + +[[licenses.clarify]] +name = "webpki" +expression = "LicenseRef-webpki" +license-files = [ + { path = "LICENSE", hash = 0x001c7e6c }, +] + +[sources] +unknown-registry = "deny" +unknown-git = "deny" + +[sources.allow-org] +github = ["stackabletech"] diff --git a/deploy/DO_NOT_EDIT.md b/deploy/DO_NOT_EDIT.md new file mode 100644 index 00000000..6fe1a0b9 --- /dev/null +++ b/deploy/DO_NOT_EDIT.md @@ -0,0 +1,10 @@ +These Helm charts and manifests are automatically generated. +Please do not edit anything except for files explicitly mentioned below in this +directory manually. + +The following files are ok to edit: + +- helm/lb-operator/templates/roles.yaml + +The details are in-motion but check this repository for a few details: + diff --git a/deploy/helm/ct.yaml b/deploy/helm/ct.yaml new file mode 100644 index 00000000..fbef6924 --- /dev/null +++ b/deploy/helm/ct.yaml @@ -0,0 +1,8 @@ +# This file is used for chart-testing (https://github.com/helm/chart-testing) +# The name "ct.yaml" is not very self-descriptive but it is the default that chart-testing is looking for +--- +remote: origin +target-branch: main +chart-dirs: + - deploy/helm +all: true diff --git a/deploy/helm/lb-operator/Chart.yaml b/deploy/helm/lb-operator/Chart.yaml index 26875c20..f4e79725 100644 --- a/deploy/helm/lb-operator/Chart.yaml +++ b/deploy/helm/lb-operator/Chart.yaml @@ -1,9 +1,9 @@ --- apiVersion: v2 name: lb-operator -version: 0.5.0-nightly -appVersion: "0.5.0-nightly" -description: The Stackable Operator for Stackable Load Balancing Operator +version: "0.1.0" +appVersion: "0.1.0" +description: The Stackable Operator for Stackable Load Balancer Operator home: https://github.com/stackabletech/lb-operator maintainers: - name: Stackable diff --git a/deploy/helm/lb-operator/README.md b/deploy/helm/lb-operator/README.md index adfad90f..df768fae 100644 --- a/deploy/helm/lb-operator/README.md +++ b/deploy/helm/lb-operator/README.md @@ -1,13 +1,13 @@ # Helm Chart for Stackable Operator for Stackable Load Balancer Operator -This Helm Chart can be used to install Custom Resource Definitions and the Operator for Stackable Load Balancer Operator. +This Helm Chart can be used to install Custom Resource Definitions and the Operator for Stackable Load Balancer Operator provided by Stackable. ## Requirements - Create a [Kubernetes Cluster](../Readme.md) - Install [Helm](https://helm.sh/docs/intro/install/) -## Install the Stackable Operator for Stackable Secret Operator +## Install the Stackable Operator for Stackable Load Balancer Operator ```bash # From the root of the operator repository diff --git a/deploy/helm/lb-operator/crds/crds.yaml b/deploy/helm/lb-operator/crds/crds.yaml index 46c56932..5b0e23eb 100644 --- a/deploy/helm/lb-operator/crds/crds.yaml +++ b/deploy/helm/lb-operator/crds/crds.yaml @@ -2,83 +2,151 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: secretclasses.secrets.stackable.tech + name: loadbalancerclasses.lb.stackable.tech annotations: helm.sh/resource-policy: keep spec: - group: secrets.stackable.tech + group: lb.stackable.tech names: categories: [] - kind: SecretClass - plural: secretclasses - shortNames: [] - singular: secretclass + kind: LoadBalancerClass + plural: loadbalancerclasses + shortNames: + - lbclass + singular: loadbalancerclass scope: Cluster versions: - additionalPrinterColumns: [] name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for SecretClassSpec via `CustomResource`" + description: "Auto-generated derived type for LoadBalancerClassSpec via `CustomResource`" properties: spec: + description: "Defines a policy for how [`LoadBalancer`]s should be exposed." properties: - backend: - oneOf: - - required: - - k8sSearch - - required: - - autoTls - properties: - autoTls: - properties: - ca: - properties: - autoGenerate: - default: false - description: Whether a new certificate authority should be generated if it does not already exist - type: boolean - secret: - description: SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace - properties: - name: - description: Name is unique within a namespace to reference a secret resource. - type: string - namespace: - description: Namespace defines the space within which the secret name must be unique. - type: string - type: object - required: - - secret - type: object - required: - - ca - type: object - k8sSearch: - properties: - searchNamespace: - oneOf: - - required: - - pod - - required: - - name - properties: - name: - type: string - pod: - type: object - type: object - required: - - searchNamespace - type: object + serviceAnnotations: + additionalProperties: + type: string + default: {} + description: "Annotations that should be added to the [`Service`] object." type: object + serviceType: + description: The method used to access the services. + enum: + - NodePort + - LoadBalancer + type: string required: - - backend + - serviceType type: object required: - spec - title: SecretClass + title: LoadBalancerClass type: object served: true storage: true subresources: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: loadbalancers.lb.stackable.tech + annotations: + helm.sh/resource-policy: keep +spec: + group: lb.stackable.tech + names: + categories: [] + kind: LoadBalancer + plural: loadbalancers + shortNames: + - lb + singular: loadbalancer + scope: Namespaced + versions: + - additionalPrinterColumns: [] + name: v1alpha1 + schema: + openAPIV3Schema: + description: "Auto-generated derived type for LoadBalancerSpec via `CustomResource`" + properties: + spec: + description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the servuce" + properties: + className: + description: "The name of the [`LoadBalancerClass`]." + nullable: true + type: string + podSelector: + additionalProperties: + type: string + description: "Labels that the [`Pod`]s must share in order to be exposed." + nullable: true + type: object + ports: + description: Ports that should be exposed. + items: + properties: + name: + description: "The name of the port.\n\nThe name of each port *must* be unique within a single [`LoadBalancer`]." + type: string + port: + description: The port number. + format: int32 + type: integer + protocol: + description: "The layer-4 protocol (`TCP` or `UDP`)." + nullable: true + type: string + required: + - name + - port + type: object + nullable: true + type: array + type: object + status: + description: "Informs users about how to reach the [`LoadBalancer`]." + nullable: true + properties: + ingressAddresses: + description: "All addresses that the [`LoadBalancer`] is currently reachable from." + items: + description: "One address that a [`LoadBalancer`] is accessible from." + properties: + address: + description: "The hostname or IP address to the [`LoadBalancer`]." + type: string + ports: + additionalProperties: + format: int32 + type: integer + description: Port mapping table. + type: object + required: + - address + - ports + type: object + nullable: true + type: array + nodePorts: + additionalProperties: + format: int32 + type: integer + description: "Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by lb-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does not require [`Node`]-local access." + nullable: true + type: object + serviceName: + description: "The backing Kubernetes [`Service`]." + nullable: true + type: string + type: object + required: + - spec + title: LoadBalancer + type: object + served: true + storage: true + subresources: + status: {} diff --git a/deploy/helm/lb-operator/templates/configmap.yaml b/deploy/helm/lb-operator/templates/configmap.yaml index 7fa8613d..e75acc25 100644 --- a/deploy/helm/lb-operator/templates/configmap.yaml +++ b/deploy/helm/lb-operator/templates/configmap.yaml @@ -4,6 +4,6 @@ data: {{ (.Files.Glob "configs/*").AsConfig | indent 2 }} kind: ConfigMap metadata: - name: {{ .Release.Name }}-configmap + name: {{ include "operator.fullname" . }}-configmap labels: {{- include "operator.labels" . | nindent 4 }} diff --git a/deploy/helm/lb-operator/templates/serviceaccount.yaml b/deploy/helm/lb-operator/templates/serviceaccount.yaml index ff2b7f8e..8ba0d58c 100644 --- a/deploy/helm/lb-operator/templates/serviceaccount.yaml +++ b/deploy/helm/lb-operator/templates/serviceaccount.yaml @@ -3,7 +3,7 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: {{ .Release.Name }}-serviceaccount + name: {{ include "operator.fullname" . }}-serviceaccount labels: {{- include "operator.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} @@ -15,15 +15,15 @@ apiVersion: rbac.authorization.k8s.io/v1 # This cluster role binding allows anyone in the "manager" group to read secrets in any namespace. kind: ClusterRoleBinding metadata: - name: {{ .Release.Name }}-clusterrolebinding + name: {{ include "operator.fullname" . }}-clusterrolebinding labels: {{- include "operator.labels" . | nindent 4 }} subjects: - kind: ServiceAccount - name: {{ .Release.Name }}-serviceaccount + name: {{ include "operator.fullname" . }}-serviceaccount namespace: {{ .Release.Namespace }} roleRef: kind: ClusterRole - name: {{ .Release.Name }}-clusterrole + name: {{ include "operator.fullname" . }}-clusterrole apiGroup: rbac.authorization.k8s.io {{- end }} diff --git a/deploy/manifests/Kustomization b/deploy/manifests/Kustomization new file mode 100644 index 00000000..0e1ce898 --- /dev/null +++ b/deploy/manifests/Kustomization @@ -0,0 +1,8 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - configmap.yaml + - deployment.yaml + - roles.yaml + - serviceaccount.yaml diff --git a/deploy/manifests/configmap.yaml b/deploy/manifests/configmap.yaml new file mode 100644 index 00000000..21b2b20c --- /dev/null +++ b/deploy/manifests/configmap.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +data: {} +kind: ConfigMap +metadata: + name: lb-operator-configmap + labels: + app.kubernetes.io/name: lb-operator + app.kubernetes.io/instance: lb-operator + app.kubernetes.io/version: "0.1.0" diff --git a/deploy/manifests/crds.yaml b/deploy/manifests/crds.yaml new file mode 100644 index 00000000..0aebbbb4 --- /dev/null +++ b/deploy/manifests/crds.yaml @@ -0,0 +1,153 @@ +--- +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: loadbalancerclasses.lb.stackable.tech + annotations: + helm.sh/resource-policy: keep +spec: + group: lb.stackable.tech + names: + categories: [] + kind: LoadBalancerClass + plural: loadbalancerclasses + shortNames: + - lbclass + singular: loadbalancerclass + scope: Cluster + versions: + - additionalPrinterColumns: [] + name: v1alpha1 + schema: + openAPIV3Schema: + description: "Auto-generated derived type for LoadBalancerClassSpec via `CustomResource`" + properties: + spec: + description: "Defines a policy for how [`LoadBalancer`]s should be exposed." + properties: + serviceAnnotations: + additionalProperties: + type: string + default: {} + description: "Annotations that should be added to the [`Service`] object." + type: object + serviceType: + description: The method used to access the services. + enum: + - NodePort + - LoadBalancer + type: string + required: + - serviceType + type: object + required: + - spec + title: LoadBalancerClass + type: object + served: true + storage: true + subresources: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: loadbalancers.lb.stackable.tech + annotations: + helm.sh/resource-policy: keep +spec: + group: lb.stackable.tech + names: + categories: [] + kind: LoadBalancer + plural: loadbalancers + shortNames: + - lb + singular: loadbalancer + scope: Namespaced + versions: + - additionalPrinterColumns: [] + name: v1alpha1 + schema: + openAPIV3Schema: + description: "Auto-generated derived type for LoadBalancerSpec via `CustomResource`" + properties: + spec: + description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the servuce" + properties: + className: + description: "The name of the [`LoadBalancerClass`]." + nullable: true + type: string + podSelector: + additionalProperties: + type: string + description: "Labels that the [`Pod`]s must share in order to be exposed." + nullable: true + type: object + ports: + description: Ports that should be exposed. + items: + properties: + name: + description: "The name of the port.\n\nThe name of each port *must* be unique within a single [`LoadBalancer`]." + type: string + port: + description: The port number. + format: int32 + type: integer + protocol: + description: "The layer-4 protocol (`TCP` or `UDP`)." + nullable: true + type: string + required: + - name + - port + type: object + nullable: true + type: array + type: object + status: + description: "Informs users about how to reach the [`LoadBalancer`]." + nullable: true + properties: + ingressAddresses: + description: "All addresses that the [`LoadBalancer`] is currently reachable from." + items: + description: "One address that a [`LoadBalancer`] is accessible from." + properties: + address: + description: "The hostname or IP address to the [`LoadBalancer`]." + type: string + ports: + additionalProperties: + format: int32 + type: integer + description: Port mapping table. + type: object + required: + - address + - ports + type: object + nullable: true + type: array + nodePorts: + additionalProperties: + format: int32 + type: integer + description: "Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by lb-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does not require [`Node`]-local access." + nullable: true + type: object + serviceName: + description: "The backing Kubernetes [`Service`]." + nullable: true + type: string + type: object + required: + - spec + title: LoadBalancer + type: object + served: true + storage: true + subresources: + status: {} diff --git a/deploy/manifests/csidriver.yaml b/deploy/manifests/csidriver.yaml new file mode 100644 index 00000000..d327cad3 --- /dev/null +++ b/deploy/manifests/csidriver.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: lb.stackable.tech +spec: + attachRequired: false + podInfoOnMount: true + fsGroupPolicy: File + volumeLifecycleModes: + - Ephemeral + - Persistent diff --git a/deploy/manifests/daemonset.yaml b/deploy/manifests/daemonset.yaml new file mode 100644 index 00000000..faab9afc --- /dev/null +++ b/deploy/manifests/daemonset.yaml @@ -0,0 +1,73 @@ +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: lb-operator-daemonset + labels: + app.kubernetes.io/name: lb-operator + app.kubernetes.io/instance: lb-operator + app.kubernetes.io/version: "0.1.0" +spec: + selector: + matchLabels: + app.kubernetes.io/name: lb-operator + app.kubernetes.io/instance: lb-operator + template: + metadata: + labels: + app.kubernetes.io/name: lb-operator + app.kubernetes.io/instance: lb-operator + spec: + serviceAccountName: lb-operator-serviceaccount + securityContext: {} + containers: + - name: lb-operator + securityContext: + privileged: true + runAsUser: 0 + image: "docker.stackable.tech/stackable/lb-operator:0.1.0" + imagePullPolicy: IfNotPresent + resources: {} + env: + - name: CSI_ENDPOINT + value: /csi/csi.sock + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + volumeMounts: + - name: csi + mountPath: /csi + - name: mountpoint + mountPath: /var/lib/kubelet/pods + mountPropagation: Bidirectional + - name: external-provisioner + image: k8s.gcr.io/sig-storage/csi-provisioner:v3.1.0 + args: + - --csi-address=/csi/csi.sock + - --feature-gates=Topology=true + - --extra-create-metadata + volumeMounts: + - name: csi + mountPath: /csi + - name: node-driver-registrar + image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0 + args: + - --csi-address=/csi/csi.sock + - --kubelet-registration-path=/var/lib/kubelet/plugins/lb.stackable.tech/csi.sock + volumeMounts: + - name: registration-sock + mountPath: /registration + - name: csi + mountPath: /csi + volumes: + - name: registration-sock + hostPath: + path: /var/lib/kubelet/plugins_registry/lb.stackable.tech-reg.sock + - name: csi + hostPath: + path: /var/lib/kubelet/plugins/lb.stackable.tech/ + - name: mountpoint + hostPath: + path: /var/lib/kubelet/pods/ diff --git a/deploy/manifests/deployment.yaml b/deploy/manifests/deployment.yaml new file mode 100644 index 00000000..0892575e --- /dev/null +++ b/deploy/manifests/deployment.yaml @@ -0,0 +1,3 @@ +--- +# Templated Deployment disabled for this operator + diff --git a/deploy/manifests/lb-classes.yaml b/deploy/manifests/lb-classes.yaml new file mode 100644 index 00000000..85c4e0fb --- /dev/null +++ b/deploy/manifests/lb-classes.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancerClass +metadata: + name: nodeport +spec: + serviceType: NodePort +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancerClass +metadata: + name: lb-external +spec: + serviceType: LoadBalancer diff --git a/deploy/manifests/roles.yaml b/deploy/manifests/roles.yaml new file mode 100644 index 00000000..ff932ec6 --- /dev/null +++ b/deploy/manifests/roles.yaml @@ -0,0 +1,77 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: lb-operator-clusterrole +rules: + - apiGroups: + - "" + resources: + - secrets + - events + - services + verbs: + - get + - list + - watch + - create + - patch + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - create + - delete + - apiGroups: + - "" + resources: + - nodes + - persistentvolumeclaims + - endpoints + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - csinodes + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - patch + - apiGroups: + - events.k8s.io + resources: + - events + verbs: + - create + - apiGroups: + - lb.stackable.tech + resources: + - loadbalancerclasses + - loadbalancers + verbs: + - get + - list + - watch + - apiGroups: + - lb.stackable.tech + resources: + - loadbalancers + - loadbalancers/status + verbs: + - patch + - create diff --git a/deploy/manifests/serviceaccount.yaml b/deploy/manifests/serviceaccount.yaml new file mode 100644 index 00000000..56e49eea --- /dev/null +++ b/deploy/manifests/serviceaccount.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: lb-operator-serviceaccount + labels: + app.kubernetes.io/name: lb-operator + app.kubernetes.io/instance: lb-operator + app.kubernetes.io/version: "0.1.0" +--- +apiVersion: rbac.authorization.k8s.io/v1 +# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace. +kind: ClusterRoleBinding +metadata: + name: lb-operator-clusterrolebinding + labels: + app.kubernetes.io/name: lb-operator + app.kubernetes.io/instance: lb-operator + app.kubernetes.io/version: "0.1.0" +subjects: + - kind: ServiceAccount + name: lb-operator-serviceaccount + namespace: default +roleRef: + kind: ClusterRole + name: lb-operator-clusterrole + apiGroup: rbac.authorization.k8s.io diff --git a/deploy/manifests/storageclass.yaml b/deploy/manifests/storageclass.yaml new file mode 100644 index 00000000..58074654 --- /dev/null +++ b/deploy/manifests/storageclass.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: lb.stackable.tech +provisioner: lb.stackable.tech +volumeBindingMode: WaitForFirstConsumer diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..9541181c --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,35 @@ +# ============= +# This file is automatically generated from the templates in stackabletech/operator-templating +# DON'T MANUALLY EDIT THIS FILE +# ============= +FROM docker.stackable.tech/stackable/ubi8-rust-builder AS builder + +FROM registry.access.redhat.com/ubi8/ubi-minimal AS operator + +ARG VERSION +ARG RELEASE="1" + +LABEL name="Stackable Operator for Stackable Load Balancer Operator" \ + maintainer="info@stackable.de" \ + vendor="Stackable GmbH" \ + version="${VERSION}" \ + release="${RELEASE}" \ + summary="Deploy and manage Stackable Load Balancer Operator clusters." \ + description="Deploy and manage Stackable Load Balancer Operator clusters." + +# Update image +RUN microdnf install -y yum \ + && yum -y update-minimal --security --sec-severity=Important --sec-severity=Critical \ + && yum clean all \ + && microdnf clean all + +COPY LICENSE /licenses/LICENSE + +COPY --from=builder /app/stackable-lb-operator / + +RUN groupadd -g 1000 stackable && adduser -u 1000 -g stackable -c 'Stackable Operator' stackable + +USER stackable:stackable + +ENTRYPOINT ["/stackable-lb-operator"] +CMD ["run"] diff --git a/docs/antora.yml b/docs/antora.yml index 55024b97..8d08c766 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,7 +1,7 @@ --- name: lb-operator -version: "nightly" +version: "0.1" title: Stackable LB Operator nav: - modules/ROOT/nav.adoc -prerelease: true +prerelease: false diff --git a/python/cargo_version.py b/python/cargo_version.py new file mode 100755 index 00000000..245e5e1c --- /dev/null +++ b/python/cargo_version.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +# +# Utility for viewing and managing versions of cargo workspaces and crates. +# For workspaces, it assumes that all crate members use a single shared version. +# +# usage: cargo-version.py [-h] [-p PROJECT] [-r] [-n {major,minor,patch}] [-s SET] [-o] [-m PRERELEASE] +# +import argparse + +import toml +import semver + + +class Crate: + def __init__(self, path, name, version, dependencies): + self.path = path + self.name = name + self.version = version + self.dependencies = dependencies + + def with_dependencies(self, names): + deps = {k: v for k, v in self.dependencies.items() if k in names} + return Crate(self.path, self.name, self.version, deps) + + @classmethod + def finalize(cls, version): + return str(semver.VersionInfo.parse(version).finalize_version()) + + @classmethod + def bump_level(cls, version, level): + ver = semver.VersionInfo.parse(version) + if level == "major": + return str(ver.bump_major()) + if level == "minor": + return str(ver.bump_minor()) + if level == "patch": + return str(ver.bump_patch()) + + return str(ver.bump_prerelease("nightly"))[ + :-2 + ] # remove the .1 suffix that semver always adds to the prererelease. + + @classmethod + def prerelease(cls, version, prerelease): + ver = semver.VersionInfo.parse(version) + return str(semver.VersionInfo(ver.major, ver.minor, ver.patch, prerelease)) + + def finalize_version(self): + return Crate( + self.path, self.name, Crate.finalize(self.version), self.dependencies.copy() + ) + + def bump_version(self, level): + return Crate( + self.path, + self.name, + Crate.bump_level(self.version, level), + self.dependencies.copy(), + ) + + def set_version(self, version): + return Crate(self.path, self.name, version, self.dependencies.copy()) + + def set_prerelease(self, prerelease): + return Crate( + self.path, + self.name, + Crate.prerelease(self.version, prerelease), + self.dependencies.copy(), + ) + + def next_version(self): + return Crate( + self.path, + self.name, + str(semver.VersionInfo.parse(self.version).next_version("patch")), + self.dependencies.copy(), + ) + + def show_version(self): + return self.version + + def save(self, previous): + contents = [] + cargo_file = f"{self.path}/Cargo.toml" + with open(cargo_file, "r", encoding="utf8") as ctl: + for line in ctl.readlines(): + if line.startswith("version"): + line = line.replace(previous.version, self.version) + else: + for dname, dversion in self.dependencies.items(): + if line.startswith(dname): + line = line.replace(previous.dependencies[dname], dversion) + contents.append(line) + with open(cargo_file, "w", encoding="utf8") as ctl: + ctl.write("".join(contents)) + + def __str__(self): + return f"Crate({self.path}, {self.name}, {self.version}, {self.dependencies})" + + +class Workspace: + def __init__(self, crates): + names = {c.name for c in crates} + self.crates = {c.name: c.with_dependencies(names) for c in crates} + + def finalize_version(self): + crates = {c.name: c.finalize_version() for c in self.crates.values()} + return Workspace(Workspace.update_dependencies(crates).values()) + + def bump_version(self, level): + crates = {c.name: c.bump_version(level) for c in self.crates.values()} + return Workspace(Workspace.update_dependencies(crates).values()) + + def set_version(self, version): + crates = {c.name: c.set_version(version) for c in self.crates.values()} + return Workspace(Workspace.update_dependencies(crates).values()) + + def set_prerelease(self, prerelease): + crates = {c.name: c.set_prerelease(prerelease) for c in self.crates.values()} + return Workspace(Workspace.update_dependencies(crates).values()) + + def next_version(self): + crates = {c.name: c.next_version() for c in self.crates.values()} + return Workspace(Workspace.update_dependencies(crates).values()) + + def show_version(self): + for cts in self.crates.values(): + return cts.show_version() + return "0.0.0" + + @classmethod + def update_dependencies(cls, crate_dict): + for crate in crate_dict.values(): + for dep in crate.dependencies.keys(): + crate.dependencies[dep] = crate_dict[dep].version + return crate_dict + + def __str__(self): + return f"Workspace({[str(c) for c in self.crates.values()]})" + + def save(self, previous): + for crn in self.crates.keys(): + self.crates[crn].save(previous.crates[crn]) + + +def load(root): + ctl = toml.load(f"{root}/Cargo.toml") + if "workspace" in ctl: + return Workspace( + [load(f"{root}/{path}") for path in ctl["workspace"]["members"]] + ) + + return Crate( + path=root, + name=ctl["package"]["name"], + version=ctl["package"]["version"], + dependencies={ + dn: ctl["dependencies"][dn]["version"] + for dn in ctl["dependencies"] + if "version" in ctl["dependencies"][dn] + }, + ) + + +def parse_args(): + parser = argparse.ArgumentParser(description="Change versions of cargo projects.") + parser.add_argument("-p", "--project", help="Project folder", default=".") + parser.add_argument("-r", "--release", help="Version", action="store_true") + parser.add_argument( + "-n", "--next", help="Version", choices=["major", "minor", "patch"] + ) + parser.add_argument("-s", "--set", help="Version") + parser.add_argument("-o", "--show", help="Version", action="store_true") + parser.add_argument("-m", "--prerelease", help="Set pre-prelease string.") + return parser.parse_args() + + +if __name__ == "__main__": + args = parse_args() + old = load(args.project.rstrip("/")) + if args.release: + new = old.finalize_version() + new.save(old) + elif args.next: + new = old.bump_version(args.next).bump_version("prerelease") + new.save(old) + elif args.set: + # sanity check + semver.VersionInfo.parse(args.set) + new = old.set_version(args.set) + new.save(old) + elif args.prerelease: + new = old.set_prerelease(args.prerelease) + new.save(old) + elif args.show: + print(old.show_version()) diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 00000000..143c5421 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,2 @@ +semver==2.13.0 +toml==0.10.2 diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..df34602d --- /dev/null +++ b/renovate.json @@ -0,0 +1,32 @@ +{ + "extends": [ + "helpers:pinGitHubActionDigests" + ], + "labels": [ + "dependencies" + ], + "prCreation": "not-pending", + "reviewers": [ + "team:developers" + ], + "rollbackPrs": true, + "schedule": [ + "after 5:00 and before 6:00 every weekday" + ], + "timezone": "Europe/Berlin", + "packageRules": [ + { + "matchUpdateTypes": [ + "patch" + ], + "groupName": "All dependencies (patch only)" + } + ], + "lockFileMaintenance": { + "enabled": true, + "schedule": [ + "after 5:00 and before 6:00 every weekday" + ] + }, + "ignorePaths": [".github/workflows/build.yml", ".github/workflows/daily_security.yml", ".github/workflows/reviewdog.yaml"] +} diff --git a/scripts/docs_templating.sh b/scripts/docs_templating.sh new file mode 100755 index 00000000..ed5b9b01 --- /dev/null +++ b/scripts/docs_templating.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Reads a file with variables to insert into templates, and templates all .*.j2 files +# in the 'docs' directory. +# +# dependencies +# pip install jinja2-cli + +docs_dir="$(dirname "$0")/../docs" +templating_vars_file="$docs_dir/templating_vars.yaml" + +# Check if files need templating +if [[ -z $(find "$docs_dir" -name '*.j2') ]]; +then + echo "No files need templating, exiting." + exit +fi + +# Check if jinja2 is there +if ! command -v jinja2 &> /dev/null +then + echo "jinja2 could not be found. Use 'pip install jinja2-cli' to install it." + exit +fi + +# Check if templating vars file exists +if [[ ! -f "$templating_vars_file" ]]; +then + echo "$templating_vars_file does not exist, cannot start templating." +fi + +find "$docs_dir" -name '*.j2' | +while read -r file +do + new_file_name=${file%.j2} # Remove .j2 suffix + echo "templating $new_file_name" + jinja2 "$file" "$templating_vars_file" -o "$new_file_name" +done + +echo "done" diff --git a/scripts/generate-manifests.sh b/scripts/generate-manifests.sh new file mode 100755 index 00000000..e0078e66 --- /dev/null +++ b/scripts/generate-manifests.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# This script reads a Helm chart from deploy/helm/lb-operator and +# generates manifest files into deploy/manifestss +set -e + +tmp=$(mktemp -d ./manifests-XXXXX) + +helm template --output-dir "$tmp" \ + --include-crds \ + --name-template lb-operator \ + deploy/helm/lb-operator + +for file in "$tmp"/lb-operator/*/*; do + yq eval -i 'del(.. | select(has("app.kubernetes.io/managed-by")) | ."app.kubernetes.io/managed-by")' /dev/stdin < "$file" + yq eval -i 'del(.. | select(has("helm.sh/chart")) | ."helm.sh/chart")' /dev/stdin < "$file" + sed -i '/# Source: .*/d' "$file" +done + +cp -r "$tmp"/lb-operator/*/* deploy/manifests/ + +rm -rf "$tmp" diff --git a/scripts/run_tests.sh b/scripts/run_tests.sh new file mode 100755 index 00000000..8fccb47f --- /dev/null +++ b/scripts/run_tests.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -e + +# Register absolute paths to pass to Ansible so the location of the role is irrelevant +# for the run +TESTDIR="$(pwd)/tests" +WORKDIR="$(pwd)/tests/_work" + +# Create dirs +mkdir -p tests/ansible/roles +mkdir -p "$WORKDIR" + +# Install Ansible role if needed +pushd tests/ansible +ansible-galaxy role install -r requirements.yaml -p ./roles + +# TODO: create pipenv in files for script thingy + +# Funnel via JSON to ensure that values are escaped properly +echo '{}' | jq '{work_dir: $WORKDIR, test_dir: $TESTDIR}' --arg WORKDIR "$WORKDIR" --arg TESTDIR "$TESTDIR" > "${WORKDIR}"/vars.json + +# Run playbook to generate test scenarios +ansible-playbook playbook.yaml --extra-vars "@${WORKDIR}/vars.json" +popd + +# Run tests +pushd tests/_work +kubectl kuttl test "$@" +popd diff --git a/tests/README-templating.md b/tests/README-templating.md new file mode 100644 index 00000000..97ca94e4 --- /dev/null +++ b/tests/README-templating.md @@ -0,0 +1,83 @@ +# Test Scenario Templating + +## Introduction + +The tests in this directory are designed to be expanded into multiple test scenarios based on test dimensions that can be defined in a dimensions file. + +## Defining Test Dimensions + +The dimensions file currently has to be named `test-definition.yaml` and reside in the same directory as the `kuttl-test.yaml.jinja2` file. + +An example of a minimal folder structure will be given further down in this file. + +An example of the content for the test definition file is shown here: + +````yaml +dimensions: + - name: spark + values: + - 3.2.1 + - 3.2.2 + - 3.2.3 + - name: hadoop + values: + - 3.1.0 + - 3.2.0 + - name: aws + - abc + - xyz +tests: + - name: spark-pi-public-s3 + dimensions: + - spark + - hadoop +```` + +This file defines three dimensions for this test to be considered. +It also defines one test case named _spark-pi-public-s3_ and the dimensions that this test case should use. +In this example the test case uses only two of the three dimensions defined, so a run of this test case would be expanded into the following test structure: + +````text +└── spark-pi-public-s3 + ├── spark-3.2.1_hadoop-3.1.0 + ├── spark-3.2.1_hadoop-3.2.0 + ├── spark-3.2.2_hadoop-3.1.0 + ├── spark-3.2.2_hadoop-3.2.0 + ├── spark-3.2.3_hadoop-3.1.0 + └── spark-3.2.3_hadoop-3.2.0 +```` + +The name of a test case defined under `tests` in this file has to refer back to a directory in the `templates/kuttl` directory, which will be used to create the test scenarios. + +Given the example of a test-definition.yaml shown above, the following folder structure would create the test scenarios shown above. + +````text +tests +├── kuttl-test.yaml.j2 +├── templates +│ └── kuttl +│ └── spark-pi-public-s3 +└── test-definition.yaml +```` + +The `kuttl-test.yaml.jinja2` cannot currently be edited, as it comes from the operator templating and any changes would be overwritten again. +This should be fairly easy to solve and we can look at this as soon as it becomes necessary. + +## Using + +### Requirements + +To run tests locally you need the following things installed: + +- python3 (version >= 3.9) + - pyyaml library installed +- ansible (tested with `2.10.8` and `2.12.5`) +- jq + +### Running + +To run tests please execute the following command from the gitroot of the operator repository: + +`scripts/run_tests.sh --parallel 2` + +This will install the necessary ansible role into `tests/ansible/roles`, expand the test templates into all defined test scenarios and execute kuttl to test these scenarios. Any arguments are passed on to `kuttl`. diff --git a/tests/ansible/playbook.yaml b/tests/ansible/playbook.yaml new file mode 100644 index 00000000..f580831f --- /dev/null +++ b/tests/ansible/playbook.yaml @@ -0,0 +1,6 @@ +--- +- name: Expand test templates into test scenarios by applying input dimensions + hosts: localhost + connection: local + roles: + - expand-tests diff --git a/tests/ansible/requirements.yaml b/tests/ansible/requirements.yaml new file mode 100644 index 00000000..d7aef5c1 --- /dev/null +++ b/tests/ansible/requirements.yaml @@ -0,0 +1,4 @@ +--- +- name: expand-tests + src: https://github.com/stackabletech/expand-tests.git + scm: git diff --git a/tests/kuttl-test.yaml.jinja2 b/tests/kuttl-test.yaml.jinja2 new file mode 100644 index 00000000..76b502aa --- /dev/null +++ b/tests/kuttl-test.yaml.jinja2 @@ -0,0 +1,11 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestSuite +testDirs: + {% for testcase in testinput.tests %} + - ./tests/{{ testcase.name }} + {% endfor %} + +startKIND: false +suppress: ["events"] +parallel: 2 diff --git a/tests/templates/.gitkeep b/tests/templates/.gitkeep new file mode 100644 index 00000000..e69de29b From 66297fce0841010422b0c016592abe97bf231c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 24 Aug 2022 14:53:08 +0200 Subject: [PATCH 27/99] Change version to nightly --- Cargo.lock | 2 +- deploy/helm/lb-operator/Chart.yaml | 4 ++-- deploy/manifests/configmap.yaml | 2 +- deploy/manifests/daemonset.yaml | 4 ++-- deploy/manifests/serviceaccount.yaml | 4 ++-- docs/antora.yml | 4 ++-- rust/lb-operator/Cargo.toml | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 738f3b54..7dfe730a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1766,7 +1766,7 @@ dependencies = [ [[package]] name = "stackable-lb-operator" -version = "0.1.0" +version = "0.1.0-nightly" dependencies = [ "anyhow", "clap", diff --git a/deploy/helm/lb-operator/Chart.yaml b/deploy/helm/lb-operator/Chart.yaml index f4e79725..3b72f72a 100644 --- a/deploy/helm/lb-operator/Chart.yaml +++ b/deploy/helm/lb-operator/Chart.yaml @@ -1,8 +1,8 @@ --- apiVersion: v2 name: lb-operator -version: "0.1.0" -appVersion: "0.1.0" +version: "0.1.0-nightly" +appVersion: "0.1.0-nightly" description: The Stackable Operator for Stackable Load Balancer Operator home: https://github.com/stackabletech/lb-operator maintainers: diff --git a/deploy/manifests/configmap.yaml b/deploy/manifests/configmap.yaml index 21b2b20c..7ed5816f 100644 --- a/deploy/manifests/configmap.yaml +++ b/deploy/manifests/configmap.yaml @@ -7,4 +7,4 @@ metadata: labels: app.kubernetes.io/name: lb-operator app.kubernetes.io/instance: lb-operator - app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/version: "0.1.0-nightly" diff --git a/deploy/manifests/daemonset.yaml b/deploy/manifests/daemonset.yaml index faab9afc..a6755f50 100644 --- a/deploy/manifests/daemonset.yaml +++ b/deploy/manifests/daemonset.yaml @@ -6,7 +6,7 @@ metadata: labels: app.kubernetes.io/name: lb-operator app.kubernetes.io/instance: lb-operator - app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/version: "0.1.0-nightly" spec: selector: matchLabels: @@ -25,7 +25,7 @@ spec: securityContext: privileged: true runAsUser: 0 - image: "docker.stackable.tech/stackable/lb-operator:0.1.0" + image: "docker.stackable.tech/stackable/lb-operator:0.1.0-nightly" imagePullPolicy: IfNotPresent resources: {} env: diff --git a/deploy/manifests/serviceaccount.yaml b/deploy/manifests/serviceaccount.yaml index 56e49eea..449784b6 100644 --- a/deploy/manifests/serviceaccount.yaml +++ b/deploy/manifests/serviceaccount.yaml @@ -6,7 +6,7 @@ metadata: labels: app.kubernetes.io/name: lb-operator app.kubernetes.io/instance: lb-operator - app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/version: "0.1.0-nightly" --- apiVersion: rbac.authorization.k8s.io/v1 # This cluster role binding allows anyone in the "manager" group to read secrets in any namespace. @@ -16,7 +16,7 @@ metadata: labels: app.kubernetes.io/name: lb-operator app.kubernetes.io/instance: lb-operator - app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/version: "0.1.0-nightly" subjects: - kind: ServiceAccount name: lb-operator-serviceaccount diff --git a/docs/antora.yml b/docs/antora.yml index 8d08c766..55024b97 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,7 +1,7 @@ --- name: lb-operator -version: "0.1" +version: "nightly" title: Stackable LB Operator nav: - modules/ROOT/nav.adoc -prerelease: false +prerelease: true diff --git a/rust/lb-operator/Cargo.toml b/rust/lb-operator/Cargo.toml index 621850ed..feb3f838 100644 --- a/rust/lb-operator/Cargo.toml +++ b/rust/lb-operator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stackable-lb-operator" -version = "0.1.0" +version = "0.1.0-nightly" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From cb1644ca33a452a53f855b6a4b9a2dcd38efd095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 24 Aug 2022 15:25:32 +0200 Subject: [PATCH 28/99] Add nodeport smoke test --- .../smoke-nodeport/00-create-lbclass.yaml | 7 +++ .../kuttl/smoke-nodeport/01-assert.yaml | 8 ++++ .../01-create-nginx-statefulset.yaml | 47 +++++++++++++++++++ .../kuttl/smoke-nodeport/02-assert.yaml | 6 +++ ...-validate-all-ingresses-are-reachable.yaml | 1 + tests/test-definition.yaml | 5 ++ 6 files changed, 74 insertions(+) create mode 100644 tests/templates/kuttl/smoke-nodeport/00-create-lbclass.yaml create mode 100644 tests/templates/kuttl/smoke-nodeport/01-assert.yaml create mode 100644 tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml create mode 100644 tests/templates/kuttl/smoke-nodeport/02-assert.yaml create mode 100644 tests/templates/kuttl/smoke-nodeport/02-validate-all-ingresses-are-reachable.yaml create mode 100644 tests/test-definition.yaml diff --git a/tests/templates/kuttl/smoke-nodeport/00-create-lbclass.yaml b/tests/templates/kuttl/smoke-nodeport/00-create-lbclass.yaml new file mode 100644 index 00000000..5a3e3d8c --- /dev/null +++ b/tests/templates/kuttl/smoke-nodeport/00-create-lbclass.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: lb.stackable.tech/v1alpha1 +kind: LoadBalancerClass +metadata: + name: lb-operator-test-smoke-nodeport +spec: + serviceType: NodePort diff --git a/tests/templates/kuttl/smoke-nodeport/01-assert.yaml b/tests/templates/kuttl/smoke-nodeport/01-assert.yaml new file mode 100644 index 00000000..f90121fe --- /dev/null +++ b/tests/templates/kuttl/smoke-nodeport/01-assert.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: nginx +status: + readyReplicas: 2 + replicas: 2 diff --git a/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml b/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml new file mode 100644 index 00000000..aea41a24 --- /dev/null +++ b/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml @@ -0,0 +1,47 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: nginx +spec: + serviceName: nginx + selector: + matchLabels: + app: nginx + replicas: 2 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.23.1 + ports: + - name: http + containerPort: 80 + volumeMounts: + - name: lb + mountPath: /lb + - name: metadata + mountPath: /usr/share/nginx/html/ + volumes: + - name: metadata + downwardAPI: + items: + - path: pod-name + fieldRef: + fieldPath: metadata.name + volumeClaimTemplates: + - metadata: + name: lb + annotations: + lb.stackable.tech/lb-class: lb-operator-test-smoke-nodeport + spec: + accessModes: + - ReadWriteMany + storageClassName: lb.stackable.tech + resources: + requests: + storage: 1 + diff --git a/tests/templates/kuttl/smoke-nodeport/02-assert.yaml b/tests/templates/kuttl/smoke-nodeport/02-assert.yaml new file mode 100644 index 00000000..2be11fe3 --- /dev/null +++ b/tests/templates/kuttl/smoke-nodeport/02-assert.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: curl $(kubectl -n $NAMESPACE get loadbalancer/lb-nginx-0 -o jsonpath='http://{.status.ingressAddresses[0].address}:{.status.ingressAddresses[0].ports.http}/pod-name') | grep nginx-0 + - script: curl $(kubectl -n $NAMESPACE get loadbalancer/lb-nginx-1 -o jsonpath='http://{.status.ingressAddresses[0].address}:{.status.ingressAddresses[0].ports.http}/pod-name') | grep nginx-1 diff --git a/tests/templates/kuttl/smoke-nodeport/02-validate-all-ingresses-are-reachable.yaml b/tests/templates/kuttl/smoke-nodeport/02-validate-all-ingresses-are-reachable.yaml new file mode 100644 index 00000000..3fde425f --- /dev/null +++ b/tests/templates/kuttl/smoke-nodeport/02-validate-all-ingresses-are-reachable.yaml @@ -0,0 +1 @@ +# Empty, see 02-assert.yaml diff --git a/tests/test-definition.yaml b/tests/test-definition.yaml new file mode 100644 index 00000000..b7671b2c --- /dev/null +++ b/tests/test-definition.yaml @@ -0,0 +1,5 @@ +--- +dimensions: [] +tests: + - name: smoke-nodeport + dimensions: [] From 0393cf683b72ca0e2443a41277f1c2de2ae1f27d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 24 Aug 2022 15:28:59 +0200 Subject: [PATCH 29/99] Lint fixes --- .../kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml b/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml index aea41a24..3bda7a97 100644 --- a/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml +++ b/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml @@ -39,9 +39,8 @@ spec: lb.stackable.tech/lb-class: lb-operator-test-smoke-nodeport spec: accessModes: - - ReadWriteMany + - ReadWriteMany storageClassName: lb.stackable.tech resources: requests: storage: 1 - From 4bd9ee939f065a3b63d3cfcd43b3bd23a5541560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 24 Aug 2022 16:59:01 +0200 Subject: [PATCH 30/99] s/secret-operator/lb-operator/ --- docs/modules/ROOT/pages/building.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index cb8a8b5a..149c91e8 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -6,7 +6,7 @@ It is developed against the latest stable Rust release, and we currently don't s However, the LB Operator is a https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface (CSI)] provider plugin for the local Kubelet, which means that it should only be executed inside of a Kubernetes `Pod`. We currently support two ways of building the -Secret Operator: `docker build` and https://nixos.org/[Nix]. `docker build` is currently our primary deployment target, and our official images are built +LB Operator: `docker build` and https://nixos.org/[Nix]. `docker build` is currently our primary deployment target, and our official images are built using it. However, Nix has much faster incremental build and deploy times, making it ideal for local development. == Docker @@ -68,7 +68,7 @@ $ nix run -f . tilt up == K3d -Secret-Operator, as with most CSI providers, requires the Kubernetes node's root folder to be mounted as `rshared`. K3d does not do this by default, +LB-Operator, as with most CSI providers, requires the Kubernetes node's root folder to be mounted as `rshared`. K3d does not do this by default, but can be prodded into doing this by running `mount --make-rshared /` in each node container. To do this for each running node K3d node, run the following script: From f53b431fa667e0f8ee045c958e24f21a225ba378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 26 Aug 2022 14:16:35 +0200 Subject: [PATCH 31/99] Add license --- LICENSE | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..1b9535c9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,43 @@ +Licensed under the Open Software License version 3.0 + +1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: + +a) to reproduce the Original Work in copies, either alone or as part of a collective work; + +b) to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; + +c) to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; + +d) to perform the Original Work publicly; and + +e) to display the Original Work publicly. + +2) Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. + +3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. + +4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. + +5) External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). + +6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. + +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. + +8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. + +9) Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). + +10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. + +12) Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. + +13) Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. + +14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. + +16) Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. From 614f6275a75b018f73723a16a0fadcaf2c4f4b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 26 Aug 2022 14:29:48 +0200 Subject: [PATCH 32/99] Apply suggestions from code review Co-authored-by: Malte Sander --- docs/modules/ROOT/pages/building.adoc | 14 +++++++++----- docs/modules/ROOT/pages/loadbalancer.adoc | 15 +++++---------- docs/modules/ROOT/pages/loadbalancerclass.adoc | 3 +-- docs/modules/ROOT/pages/volume.adoc | 12 +++++------- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index 149c91e8..1dd95c05 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -4,9 +4,13 @@ This operator is written in Rust. It is developed against the latest stable Rust release, and we currently don't support any older versions. -However, the LB Operator is a https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface (CSI)] provider plugin -for the local Kubelet, which means that it should only be executed inside of a Kubernetes `Pod`. We currently support two ways of building the -LB Operator: `docker build` and https://nixos.org/[Nix]. `docker build` is currently our primary deployment target, and our official images are built +The LB Operator is a https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface (CSI)] provider plugin +for the local Kubelet, which means that it should only be executed inside a Kubernetes `Pod`. Currently, the following ways are supported to build the LB Operator: + +* `docker build` +* https://nixos.org/[Nix] + +The `docker build`command is currently the primary deployment target, and the official images are built using it. However, Nix has much faster incremental build and deploy times, making it ideal for local development. == Docker @@ -68,10 +72,10 @@ $ nix run -f . tilt up == K3d -LB-Operator, as with most CSI providers, requires the Kubernetes node's root folder to be mounted as `rshared`. K3d does not do this by default, +The LB Operator, as with most CSI providers, requires the Kubernetes node's root folder to be mounted as `rshared`. K3d does not do this by default, but can be prodded into doing this by running `mount --make-rshared /` in each node container. -To do this for each running node K3d node, run the following script: +To do this for each running K3d node, run the following script: [source,console] ---- diff --git a/docs/modules/ROOT/pages/loadbalancer.adoc b/docs/modules/ROOT/pages/loadbalancer.adoc index ab50ff05..5580f7a7 100644 --- a/docs/modules/ROOT/pages/loadbalancer.adoc +++ b/docs/modules/ROOT/pages/loadbalancer.adoc @@ -5,28 +5,23 @@ features that are useful for the Stackable platform at large. == `LoadBalancerClass` -The exact rules of pod exposure is dictated by the specified xref:loadbalancerclass.adoc[], which allows a single `LoadBalancer` definition -to be reused exactly between many clusters, regardless of the Kubernetes distribution or cloud provider. +The exact rules of pod exposure are dictated by the specified xref:loadbalancerclass.adoc[], which allow a single `LoadBalancer` definition to be reused in different clusters, regardless of the Kubernetes distribution or cloud provider. == Address API -`LoadBalancer` writes back all addresses that it can be reached on to `LoadBalancer.status.ingress_addresses`, which can then be used to generate -discovery information. Contrary to Kubernetes' `Service`, this is done regardless of the type of service, and transparently also contains information -about remapped ports. +A `LoadBalancer` writes back all addresses that it can be reached on to `LoadBalancer.status.ingress_addresses`, which can then be used to generate discovery information. Contrary to Kubernetes' `Service`, this is done regardless of the type of service, and transparently also contains information about remapped ports. == Address volume projection -`LoadBalancer` objects can be mounted into a `Pod` as a `PersistentVolumeClaim`, which contains information about how the `Pod` should request that -external clients refer to it. +`LoadBalancer` objects can be mounted into a `Pod` as a `PersistentVolumeClaim`, which contains information about how the `Pod` should request that external clients refer to it. -For example, if the volume is mounted to `/stackable/lb`, the primary address can be read from `/stackable/lb/default-address/address`, and the -public `http` port number can be read from `/stackable/lb/default-address/ports/http`. +For example, if the volume is mounted to `/stackable/lb`, the primary address can be read from `/stackable/lb/default-address/address`, and the public `http` port number can be read from `/stackable/lb/default-address/ports/http`. == Per-replica LBs A `LoadBalancer` PVC can also specify a xref:loadbalancerclass.adoc[] rather than a `LoadBalancer`, in which case a `LoadBalancer` object is created automatically. These PVCs can automatically be created for each replica using either `StatefulSet` 's `volumeClaimTemplates` (for long-lived LBs that will -be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` (for temporary LBs that will be deleted when their corresponding `Pod` is). +be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` (for temporary LBs that are deleted when their corresponding `Pod` is deleted). == Sticky scheduling diff --git a/docs/modules/ROOT/pages/loadbalancerclass.adoc b/docs/modules/ROOT/pages/loadbalancerclass.adoc index 4323d036..adbb9dc7 100644 --- a/docs/modules/ROOT/pages/loadbalancerclass.adoc +++ b/docs/modules/ROOT/pages/loadbalancerclass.adoc @@ -19,8 +19,7 @@ of years. This might lead administrators of such systems to prefer exposing node include::example$lbclass-public-onprem.yaml[] ---- -Finally, it can be desirable to add additional annotations to a `Service`. For example, a user might want to only expose some services inside of a given -cloud vendor VPC. How exactly this is accomplished depends on the cloud provider in question, but for GKE this requires the annotation `networking.gke.io/load-balancer-type`: +Finally, it can be desirable to add additional annotations to a `Service`. For example, a user might want to only expose some services inside a given cloud vendor VPC. How exactly this is accomplished depends on the cloud provider in question, but for GKE this requires the annotation `networking.gke.io/load-balancer-type`: [source,yaml] ---- diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index 129458b4..88f11f47 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -2,7 +2,7 @@ TODO: Expand severely. -lb-operator acts as a CSI `PersistentVolume`, which helps it stabilize network addresses, inject pod metadata, and exposing individual pods. +The LB Operator acts as a CSI `PersistentVolume`, which helps it to stabilize network addresses, inject pod metadata and expose individual pods. == Stable addresses @@ -20,7 +20,7 @@ this information: [source] ---- -- `default-address/`- symlink to `addresses/\{primary address\}` +- `default-address/`- A symlink to `addresses/\{primary address\}` - `addresses/` - Contains information about all addresses associated with this xref:loadbalancer.adoc[] - `\{address\}/` - A folder is created for each address - `address` - Contains the Pod's address (IP address or hostname) @@ -30,17 +30,15 @@ this information: == Individual pod exposure -Sometimes each replica much be exposed individually, for example because clients need to access data on a specific shard. `PersistentVolumeClaim` templates can be used to provision this automatically. +Sometimes each replica must be exposed individually, for example because clients need to access data on a specific shard. `PersistentVolumeClaim` templates can be used to provision this automatically. === `StatefulSet` `volumeClaimTemplates` -`volumeClaimTemplates` allows volumes to be provisioned for each `StatefulSet` replica. These volumes are _persistent_, and will not be deleted when the `Pod` or `StatefulSet` is. This makes them -useful for provisioning addresses that must be hard-coded into client configuration. +The `volumeClaimTemplates` allow volumes to be provisioned for each `StatefulSet` replica. These volumes are _persistent_, and will not be deleted when the `Pod` or `StatefulSet` is. This makes them useful for provisioning addresses that must be hard-coded into client configuration. === Pod-scoped ephemeral volumes -`Pod.spec.volumes[].ephemeral` allows volumes to be provisioned for each `Pod`. These volumes are tied to the lifetime of the `Pod` and will be deleted when it is. This makes them useful for provisioning -temporary addresses that will be discovered out of band (such as for HDFS DataNodes). +`Pod.spec.volumes[].ephemeral` allows volumes to be provisioned for each `Pod`. These volumes are tied to the lifetime of the `Pod` and will be deleted along with it. This makes them useful for provisioning temporary addresses that will be discovered out of band (such as for HDFS DataNodes). == Reference From e4f800a0fad08935691e13e8abb27d78b1025ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 7 Sep 2022 14:24:59 +0200 Subject: [PATCH 33/99] Update rust/lb-operator/src/csi_server/node.rs Co-authored-by: Malte Sander --- rust/lb-operator/src/csi_server/node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index 02fbea25..90958b7f 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -216,7 +216,7 @@ impl csi::v1::node_server::Node for LbOperatorNode { // Prefer calculating a per-node address where possible, to ensure that the address at least tries to // connect to the pod in question. - // We also can't rely on `ingress_addresses` being set yet, since the pod won't not have an IP address yet + // We also can't rely on `ingress_addresses` being set yet, since the pod won't have an IP address yet // (and so can't be found in `Endpoints`) let lb_addrs = if let Some(node_ports) = lb .status From c5ec87b31582827570761889ed1481e90910c045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 7 Sep 2022 14:25:13 +0200 Subject: [PATCH 34/99] Update rust/lb-operator/Cargo.toml Co-authored-by: Malte Sander --- rust/lb-operator/Cargo.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rust/lb-operator/Cargo.toml b/rust/lb-operator/Cargo.toml index feb3f838..f98938f9 100644 --- a/rust/lb-operator/Cargo.toml +++ b/rust/lb-operator/Cargo.toml @@ -1,9 +1,11 @@ [package] name = "stackable-lb-operator" +authors = ["Stackable GmbH "] +description = "Stackable Operator for load balancing" +license = "OSL-3.0" version = "0.1.0-nightly" edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +repository = "https://github.com/stackabletech/lb-operator" [dependencies] # Need to keep this in sync with our patched h2 build From fc92264bdb928ccbbcd4400ead73b93ead12a07a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 7 Sep 2022 14:52:27 +0200 Subject: [PATCH 35/99] Update rust/lb-operator/src/crd.rs Co-authored-by: Malte Sander --- rust/lb-operator/src/crd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/lb-operator/src/crd.rs b/rust/lb-operator/src/crd.rs index 37bee59e..31992353 100644 --- a/rust/lb-operator/src/crd.rs +++ b/rust/lb-operator/src/crd.rs @@ -41,7 +41,7 @@ pub enum ServiceType { /// /// Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: /// 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works -/// 2. It has a consistent API for reading back the exposed address(es) of the servuce +/// 2. It has a consistent API for reading back the exposed address(es) of the service #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default)] #[kube( group = "lb.stackable.tech", From 64e32bd9f2a6d00df6e28ee634b0bf4d5373ed45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 7 Sep 2022 14:53:20 +0200 Subject: [PATCH 36/99] Update rust/lb-operator/src/csi_server/node.rs Co-authored-by: Malte Sander --- rust/lb-operator/src/csi_server/node.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index 90958b7f..a8f47a34 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -37,7 +37,6 @@ struct LbNodeVolumeContext { pod_namespace: String, #[serde(rename = "csi.storage.k8s.io/pod.name")] pod_name: String, - #[serde(flatten)] common: LbVolumeContext, } From cbf84bb52183c676916052245625de737684d2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 7 Sep 2022 14:55:11 +0200 Subject: [PATCH 37/99] Simplify and document `node_primary_address` a bit --- rust/lb-operator/src/utils.rs | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/rust/lb-operator/src/utils.rs b/rust/lb-operator/src/utils.rs index 3a173ec6..140496f8 100644 --- a/rust/lb-operator/src/utils.rs +++ b/rust/lb-operator/src/utils.rs @@ -112,24 +112,19 @@ pub fn error_full_message(err: &dyn std::error::Error) -> String { full_msg } +/// Try to guess the primary address of a Node, which it is expected that external clients should be able to reach it on pub fn node_primary_address(node: &Node) -> Option<&str> { - let addrs = node.status.as_ref().and_then(|s| s.addresses.as_ref()); + let addrs = node + .status + .as_ref() + .and_then(|s| s.addresses.as_deref()) + .unwrap_or_default(); + // IP addresses are currently preferred over hostnames since nodes don't always have resolvable hostnames addrs - .into_iter() - .flatten() + .iter() .find(|addr| addr.type_ == "ExternalIP") - .or_else(|| { - addrs - .into_iter() - .flatten() - .find(|addr| addr.type_ == "InternalIP") - }) - .or_else(|| { - addrs - .into_iter() - .flatten() - .find(|addr| addr.type_ == "Hostname") - }) + .or_else(|| addrs.iter().find(|addr| addr.type_ == "InternalIP")) + .or_else(|| addrs.iter().find(|addr| addr.type_ == "Hostname")) .map(|addr| addr.address.as_str()) } From 236cea396b9b971196d4666566b97d11bafd27a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 7 Sep 2022 14:56:58 +0200 Subject: [PATCH 38/99] Error message for missing LBClass --- rust/lb-operator/src/csi_server/controller.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/lb-operator/src/csi_server/controller.rs index bdd4eeb4..d923e56f 100644 --- a/rust/lb-operator/src/csi_server/controller.rs +++ b/rust/lb-operator/src/csi_server/controller.rs @@ -30,21 +30,16 @@ struct ControllerVolumeParams { #[snafu(module)] enum CreateVolumeError { #[snafu(display("failed to decode request parameters"))] - DecodeRequestParams { - source: serde::de::value::Error, - }, + DecodeRequestParams { source: serde::de::value::Error }, #[snafu(display("failed to get {obj}"))] GetObject { source: stackable_operator::error::Error, obj: Box>, }, #[snafu(display("failed to decode volume context"))] - DecodeVolumeContext { - source: serde::de::value::Error, - }, - NoLoadBalancerClass { - lb: ObjectRef, - }, + DecodeVolumeContext { source: serde::de::value::Error }, + #[snafu(display("{lb} does not specify a load balancer class"))] + NoLoadBalancerClass { lb: ObjectRef }, } impl From for Status { From 2cb40649877664b37321760b94ee80c7361c3f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 7 Sep 2022 15:01:06 +0200 Subject: [PATCH 39/99] Rename pod_dir::Error::Fs --- rust/lb-operator/src/csi_server/node.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/lb-operator/src/csi_server/node.rs index a8f47a34..69df0cbc 100644 --- a/rust/lb-operator/src/csi_server/node.rs +++ b/rust/lb-operator/src/csi_server/node.rs @@ -306,8 +306,8 @@ mod pod_dir { #[derive(Snafu, Debug)] pub enum Error { - #[snafu(context(false))] - Fs { source: std::io::Error }, + #[snafu(display("failed to write content"), context(false))] + WriteContent { source: std::io::Error }, #[snafu(display("load balancer has no address yet"))] NoDefaultLb, #[snafu(display("default address folder is outside of the volume root"))] From e0f2571bba8ce31f878cf697852598c47f61de6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 12:25:12 +0200 Subject: [PATCH 40/99] Update rust/lb-operator/src/crd.rs Co-authored-by: Malte Sander --- rust/lb-operator/src/crd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/lb-operator/src/crd.rs b/rust/lb-operator/src/crd.rs index 31992353..b6ede1b1 100644 --- a/rust/lb-operator/src/crd.rs +++ b/rust/lb-operator/src/crd.rs @@ -5,7 +5,7 @@ use stackable_operator::kube::CustomResource; use stackable_operator::schemars::{self, JsonSchema}; #[cfg(rustdoc)] -use stackable_operator::k8s_openapi::api::core::v1::{Pod, Service}; +use stackable_operator::k8s_openapi::api::core::v1::{Node, Pod, Service}; /// Defines a policy for how [`LoadBalancer`]s should be exposed. #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)] From abfc60ecf38a965efdaf14bdbef2dd78f9ede567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 12:31:24 +0200 Subject: [PATCH 41/99] Update docs/modules/ROOT/pages/loadbalancer.adoc Co-authored-by: Malte Sander --- docs/modules/ROOT/pages/loadbalancer.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/loadbalancer.adoc b/docs/modules/ROOT/pages/loadbalancer.adoc index 5580f7a7..c0f13df3 100644 --- a/docs/modules/ROOT/pages/loadbalancer.adoc +++ b/docs/modules/ROOT/pages/loadbalancer.adoc @@ -28,5 +28,5 @@ be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` When mounting a `LoadBalancer` PVC, it will be made "sticky" to that node if the xref:loadbalancerclass.adoc[] uses a strategy that depends on the node that the workload is running on. -Keep in mind that this will only work correctly when using long-lived PVCs (such as via `StatefulSet` 's `volumeClaimTemplates). Ephemeral PVCs +Keep in mind that this will only work correctly when using long-lived PVCs (such as via `StatefulSet` 's `volumeClaimTemplates`). Ephemeral PVCs will be "reset" for every pod that is created, even if they refer to a long-lived `LoadBalancer` object. From 930093ac1884e86420bb21026724e27a7ca4618a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 12:56:53 +0200 Subject: [PATCH 42/99] Rename stackable-lb-operator crate to stackable-listener-operator --- .gitmodules | 2 +- Cargo.lock | 2 +- Cargo.toml | 4 ++-- rust/{lb-operator => listener-operator}/Cargo.toml | 6 +++--- rust/{lb-operator => listener-operator}/build.rs | 0 rust/{lb-operator => listener-operator}/src/crd.rs | 0 .../src/csi_server/controller.rs | 0 .../src/csi_server/identity.rs | 0 .../src/csi_server/mod.rs | 0 .../src/csi_server/node.rs | 0 rust/{lb-operator => listener-operator}/src/grpc.rs | 0 .../{lb-operator => listener-operator}/src/lb_controller.rs | 0 rust/{lb-operator => listener-operator}/src/lib.rs | 0 rust/{lb-operator => listener-operator}/src/main.rs | 0 rust/{lb-operator => listener-operator}/src/utils.rs | 0 rust/{lb-operator => listener-operator}/vendor/csi | 0 16 files changed, 7 insertions(+), 7 deletions(-) rename rust/{lb-operator => listener-operator}/Cargo.toml (83%) rename rust/{lb-operator => listener-operator}/build.rs (100%) rename rust/{lb-operator => listener-operator}/src/crd.rs (100%) rename rust/{lb-operator => listener-operator}/src/csi_server/controller.rs (100%) rename rust/{lb-operator => listener-operator}/src/csi_server/identity.rs (100%) rename rust/{lb-operator => listener-operator}/src/csi_server/mod.rs (100%) rename rust/{lb-operator => listener-operator}/src/csi_server/node.rs (100%) rename rust/{lb-operator => listener-operator}/src/grpc.rs (100%) rename rust/{lb-operator => listener-operator}/src/lb_controller.rs (100%) rename rust/{lb-operator => listener-operator}/src/lib.rs (100%) rename rust/{lb-operator => listener-operator}/src/main.rs (100%) rename rust/{lb-operator => listener-operator}/src/utils.rs (100%) rename rust/{lb-operator => listener-operator}/vendor/csi (100%) diff --git a/.gitmodules b/.gitmodules index 2a810051..793e4fd1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "rust/lb-operator/vendor/csi"] - path = rust/lb-operator/vendor/csi + path = rust/listener-operator/vendor/csi url = https://github.com/container-storage-interface/spec diff --git a/Cargo.lock b/Cargo.lock index 7dfe730a..10734035 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1765,7 +1765,7 @@ dependencies = [ ] [[package]] -name = "stackable-lb-operator" +name = "stackable-listener-operator" version = "0.1.0-nightly" dependencies = [ "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 961098d5..5b4466fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = ["rust/lb-operator"] +members = ["rust/listener-operator"] [patch.crates-io] # Workaround for https://github.com/hyperium/tonic/issues/243 h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } # [patch."https://github.com/stackabletech/operator-rs.git"] -# stackable-operator = { path = "../operator-rs" } \ No newline at end of file +# stackable-operator = { path = "../operator-rs" } diff --git a/rust/lb-operator/Cargo.toml b/rust/listener-operator/Cargo.toml similarity index 83% rename from rust/lb-operator/Cargo.toml rename to rust/listener-operator/Cargo.toml index f98938f9..5f7ee0fc 100644 --- a/rust/lb-operator/Cargo.toml +++ b/rust/listener-operator/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "stackable-lb-operator" +name = "stackable-listener-operator" authors = ["Stackable GmbH "] -description = "Stackable Operator for load balancing" +description = "Stackable Operator for network listeners" license = "OSL-3.0" version = "0.1.0-nightly" edition = "2021" -repository = "https://github.com/stackabletech/lb-operator" +repository = "https://github.com/stackabletech/listener-operator" [dependencies] # Need to keep this in sync with our patched h2 build diff --git a/rust/lb-operator/build.rs b/rust/listener-operator/build.rs similarity index 100% rename from rust/lb-operator/build.rs rename to rust/listener-operator/build.rs diff --git a/rust/lb-operator/src/crd.rs b/rust/listener-operator/src/crd.rs similarity index 100% rename from rust/lb-operator/src/crd.rs rename to rust/listener-operator/src/crd.rs diff --git a/rust/lb-operator/src/csi_server/controller.rs b/rust/listener-operator/src/csi_server/controller.rs similarity index 100% rename from rust/lb-operator/src/csi_server/controller.rs rename to rust/listener-operator/src/csi_server/controller.rs diff --git a/rust/lb-operator/src/csi_server/identity.rs b/rust/listener-operator/src/csi_server/identity.rs similarity index 100% rename from rust/lb-operator/src/csi_server/identity.rs rename to rust/listener-operator/src/csi_server/identity.rs diff --git a/rust/lb-operator/src/csi_server/mod.rs b/rust/listener-operator/src/csi_server/mod.rs similarity index 100% rename from rust/lb-operator/src/csi_server/mod.rs rename to rust/listener-operator/src/csi_server/mod.rs diff --git a/rust/lb-operator/src/csi_server/node.rs b/rust/listener-operator/src/csi_server/node.rs similarity index 100% rename from rust/lb-operator/src/csi_server/node.rs rename to rust/listener-operator/src/csi_server/node.rs diff --git a/rust/lb-operator/src/grpc.rs b/rust/listener-operator/src/grpc.rs similarity index 100% rename from rust/lb-operator/src/grpc.rs rename to rust/listener-operator/src/grpc.rs diff --git a/rust/lb-operator/src/lb_controller.rs b/rust/listener-operator/src/lb_controller.rs similarity index 100% rename from rust/lb-operator/src/lb_controller.rs rename to rust/listener-operator/src/lb_controller.rs diff --git a/rust/lb-operator/src/lib.rs b/rust/listener-operator/src/lib.rs similarity index 100% rename from rust/lb-operator/src/lib.rs rename to rust/listener-operator/src/lib.rs diff --git a/rust/lb-operator/src/main.rs b/rust/listener-operator/src/main.rs similarity index 100% rename from rust/lb-operator/src/main.rs rename to rust/listener-operator/src/main.rs diff --git a/rust/lb-operator/src/utils.rs b/rust/listener-operator/src/utils.rs similarity index 100% rename from rust/lb-operator/src/utils.rs rename to rust/listener-operator/src/utils.rs diff --git a/rust/lb-operator/vendor/csi b/rust/listener-operator/vendor/csi similarity index 100% rename from rust/lb-operator/vendor/csi rename to rust/listener-operator/vendor/csi From 9f077b7b02aa43360570715c5eb1277a2db1b374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 13:01:10 +0200 Subject: [PATCH 43/99] Rename helm chart --- deploy/helm/lb-operator/Chart.yaml | 10 ---------- .../{lb-operator => listener-operator}/.helmignore | 0 deploy/helm/listener-operator/Chart.yaml | 10 ++++++++++ .../helm/{lb-operator => listener-operator}/README.md | 4 ++-- .../{lb-operator => listener-operator}/crds/crds.yaml | 0 .../templates/_helpers.tpl | 0 .../templates/configmap.yaml | 0 .../templates/csidriver.yaml | 0 .../templates/daemonset.yaml | 0 .../templates/deployment.yaml | 0 .../templates/lb-classes.yaml | 0 .../templates/roles.yaml | 0 .../templates/serviceaccount.yaml | 0 .../templates/storageclass.yaml | 0 .../{lb-operator => listener-operator}/values.yaml | 0 15 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 deploy/helm/lb-operator/Chart.yaml rename deploy/helm/{lb-operator => listener-operator}/.helmignore (100%) create mode 100644 deploy/helm/listener-operator/Chart.yaml rename deploy/helm/{lb-operator => listener-operator}/README.md (82%) rename deploy/helm/{lb-operator => listener-operator}/crds/crds.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/_helpers.tpl (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/configmap.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/csidriver.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/daemonset.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/deployment.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/lb-classes.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/roles.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/serviceaccount.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/templates/storageclass.yaml (100%) rename deploy/helm/{lb-operator => listener-operator}/values.yaml (100%) diff --git a/deploy/helm/lb-operator/Chart.yaml b/deploy/helm/lb-operator/Chart.yaml deleted file mode 100644 index 3b72f72a..00000000 --- a/deploy/helm/lb-operator/Chart.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -apiVersion: v2 -name: lb-operator -version: "0.1.0-nightly" -appVersion: "0.1.0-nightly" -description: The Stackable Operator for Stackable Load Balancer Operator -home: https://github.com/stackabletech/lb-operator -maintainers: - - name: Stackable - url: https://www.stackable.tech diff --git a/deploy/helm/lb-operator/.helmignore b/deploy/helm/listener-operator/.helmignore similarity index 100% rename from deploy/helm/lb-operator/.helmignore rename to deploy/helm/listener-operator/.helmignore diff --git a/deploy/helm/listener-operator/Chart.yaml b/deploy/helm/listener-operator/Chart.yaml new file mode 100644 index 00000000..e04ea22b --- /dev/null +++ b/deploy/helm/listener-operator/Chart.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v2 +name: listener-operator +version: "0.1.0-nightly" +appVersion: "0.1.0-nightly" +description: The Stackable Operator for Stackable Listener Operator +home: https://github.com/stackabletech/listener-operator +maintainers: + - name: Stackable + url: https://www.stackable.tech diff --git a/deploy/helm/lb-operator/README.md b/deploy/helm/listener-operator/README.md similarity index 82% rename from deploy/helm/lb-operator/README.md rename to deploy/helm/listener-operator/README.md index df768fae..7e46335c 100644 --- a/deploy/helm/lb-operator/README.md +++ b/deploy/helm/listener-operator/README.md @@ -1,6 +1,6 @@ -# Helm Chart for Stackable Operator for Stackable Load Balancer Operator +# Helm Chart for Stackable Operator for Stackable Listener Operator -This Helm Chart can be used to install Custom Resource Definitions and the Operator for Stackable Load Balancer Operator provided by Stackable. +This Helm Chart can be used to install Custom Resource Definitions and the Stackable Listener Operator. ## Requirements diff --git a/deploy/helm/lb-operator/crds/crds.yaml b/deploy/helm/listener-operator/crds/crds.yaml similarity index 100% rename from deploy/helm/lb-operator/crds/crds.yaml rename to deploy/helm/listener-operator/crds/crds.yaml diff --git a/deploy/helm/lb-operator/templates/_helpers.tpl b/deploy/helm/listener-operator/templates/_helpers.tpl similarity index 100% rename from deploy/helm/lb-operator/templates/_helpers.tpl rename to deploy/helm/listener-operator/templates/_helpers.tpl diff --git a/deploy/helm/lb-operator/templates/configmap.yaml b/deploy/helm/listener-operator/templates/configmap.yaml similarity index 100% rename from deploy/helm/lb-operator/templates/configmap.yaml rename to deploy/helm/listener-operator/templates/configmap.yaml diff --git a/deploy/helm/lb-operator/templates/csidriver.yaml b/deploy/helm/listener-operator/templates/csidriver.yaml similarity index 100% rename from deploy/helm/lb-operator/templates/csidriver.yaml rename to deploy/helm/listener-operator/templates/csidriver.yaml diff --git a/deploy/helm/lb-operator/templates/daemonset.yaml b/deploy/helm/listener-operator/templates/daemonset.yaml similarity index 100% rename from deploy/helm/lb-operator/templates/daemonset.yaml rename to deploy/helm/listener-operator/templates/daemonset.yaml diff --git a/deploy/helm/lb-operator/templates/deployment.yaml b/deploy/helm/listener-operator/templates/deployment.yaml similarity index 100% rename from deploy/helm/lb-operator/templates/deployment.yaml rename to deploy/helm/listener-operator/templates/deployment.yaml diff --git a/deploy/helm/lb-operator/templates/lb-classes.yaml b/deploy/helm/listener-operator/templates/lb-classes.yaml similarity index 100% rename from deploy/helm/lb-operator/templates/lb-classes.yaml rename to deploy/helm/listener-operator/templates/lb-classes.yaml diff --git a/deploy/helm/lb-operator/templates/roles.yaml b/deploy/helm/listener-operator/templates/roles.yaml similarity index 100% rename from deploy/helm/lb-operator/templates/roles.yaml rename to deploy/helm/listener-operator/templates/roles.yaml diff --git a/deploy/helm/lb-operator/templates/serviceaccount.yaml b/deploy/helm/listener-operator/templates/serviceaccount.yaml similarity index 100% rename from deploy/helm/lb-operator/templates/serviceaccount.yaml rename to deploy/helm/listener-operator/templates/serviceaccount.yaml diff --git a/deploy/helm/lb-operator/templates/storageclass.yaml b/deploy/helm/listener-operator/templates/storageclass.yaml similarity index 100% rename from deploy/helm/lb-operator/templates/storageclass.yaml rename to deploy/helm/listener-operator/templates/storageclass.yaml diff --git a/deploy/helm/lb-operator/values.yaml b/deploy/helm/listener-operator/values.yaml similarity index 100% rename from deploy/helm/lb-operator/values.yaml rename to deploy/helm/listener-operator/values.yaml From 2b52e96cbebcd4b6e7a816467b229abd6fb56c71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 13:04:42 +0200 Subject: [PATCH 44/99] Post-rebrand templating --- .github/ISSUE_TEMPLATE/config.yml | 6 ++--- .github/ISSUE_TEMPLATE/new_version.md | 2 +- .github/workflows/build.yml | 28 ++++++++++++++++++-- Makefile | 24 ++++++++--------- deny.toml | 6 ++--- deploy/DO_NOT_EDIT.md | 3 ++- deploy/helm/listener-operator/README.md | 12 ++++----- deploy/helm/listener-operator/crds/crds.yaml | 2 +- deploy/manifests/configmap.yaml | 6 ++--- deploy/manifests/crds.yaml | 2 +- deploy/manifests/daemonset.yaml | 18 ++++++------- deploy/manifests/roles.yaml | 2 +- deploy/manifests/serviceaccount.yaml | 16 +++++------ docker/Dockerfile | 10 +++---- scripts/generate-manifests.sh | 10 +++---- 15 files changed, 86 insertions(+), 61 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 54e2c297..6f1fa288 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,10 +3,10 @@ blank_issues_enabled: true contact_links: - name: Feature request about: 🚀 Suggest an idea for this project - url: https://github.com/stackabletech/lb-operator/discussions/new?category=ideas + url: https://github.com/stackabletech/listener-operator/discussions/new?category=ideas - name: 🙋🏾 Question about: Use this to ask a question about this project - url: https://github.com/stackabletech/lb-operator/discussions/new?category=q-a + url: https://github.com/stackabletech/listener-operator/discussions/new?category=q-a - name: Other issue about: Open an issue that doesn't fit any other category - url: https://github.com/stackabletech/lb-operator/issues/new + url: https://github.com/stackabletech/listener-operator/issues/new diff --git a/.github/ISSUE_TEMPLATE/new_version.md b/.github/ISSUE_TEMPLATE/new_version.md index ea1a5075..52550da8 100644 --- a/.github/ISSUE_TEMPLATE/new_version.md +++ b/.github/ISSUE_TEMPLATE/new_version.md @@ -7,7 +7,7 @@ assignees: '' --- -**Which new version of Stackable Load Balancer Operator should we support?** +**Which new version of Stackable Listener Operator should we support?** Please specify the version, version range or version numbers to support, please also add these to the issue title diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 036993fb..07c24436 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,8 +19,8 @@ env: RUSTFLAGS: "-D warnings" RUSTDOCFLAGS: "-D warnings" RUST_LOG: "info" - OPERATOR_NAME: "lb-operator" - PRODUCT_NAME: "lb-operator" + OPERATOR_NAME: "listener-operator" + PRODUCT_NAME: "listener-operator" DEV_REPO_HELM_URL: https://repo.stackable.tech/repository/helm-dev TEST_REPO_HELM_URL: https://repo.stackable.tech/repository/helm-test STABLE_REPO_HELM_URL: https://repo.stackable.tech/repository/helm-stable @@ -33,6 +33,10 @@ jobs: env: RUSTC_BOOTSTRAP: 1 steps: + - name: Install protoc + run: | + sudo apt-get update + sudo apt-get install protobuf-compiler - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 with: submodules: recursive @@ -158,6 +162,10 @@ jobs: name: Run Clippy runs-on: ubuntu-latest steps: + - name: Install protoc + run: | + sudo apt-get update + sudo apt-get install protobuf-compiler - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 with: submodules: recursive @@ -188,6 +196,10 @@ jobs: name: Run RustDoc runs-on: ubuntu-latest steps: + - name: Install protoc + run: | + sudo apt-get update + sudo apt-get install protobuf-compiler - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 with: submodules: recursive @@ -214,6 +226,10 @@ jobs: - run_rustdoc runs-on: ubuntu-latest steps: + - name: Install protoc + run: | + sudo apt-get update + sudo apt-get install protobuf-compiler - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 with: submodules: recursive @@ -248,6 +264,10 @@ jobs: - run_rustdoc runs-on: ubuntu-latest steps: + - name: Install protoc + run: | + sudo apt-get update + sudo apt-get install protobuf-compiler - name: Checkout uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 with: @@ -312,6 +332,10 @@ jobs: REPO: ${{ needs.select_repo.outputs.repository }} if: needs.select_repo.outputs.repository != 'skip' steps: + - name: Install protoc + run: | + sudo apt-get update + sudo apt-get install protobuf-compiler - name: Checkout uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 with: diff --git a/Makefile b/Makefile index 8d6364f4..4980f44d 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ TAG := $(shell git rev-parse --short HEAD) -VERSION := $(shell cargo metadata --format-version 1 | jq -r '.packages[] | select(.name=="stackable-lb-operator") | .version') +VERSION := $(shell cargo metadata --format-version 1 | jq -r '.packages[] | select(.name=="stackable-listener-operator") | .version') IS_NIGHTLY := $(shell echo "${VERSION}" | grep -- '-nightly$$') # When rendering docs we want to simplify the version number slightly, only rendering "nightly" for nightly branches # (since we only render nightlies for the active development trunk anyway) and chopping off the semver patch version otherwise @@ -21,15 +21,15 @@ SHELL=/usr/bin/env bash -euo pipefail ## Docker related targets docker-build: - docker build --force-rm --build-arg VERSION=${VERSION} -t "docker.stackable.tech/stackable/lb-operator:${VERSION}" -f docker/Dockerfile . + docker build --force-rm --build-arg VERSION=${VERSION} -t "docker.stackable.tech/stackable/listener-operator:${VERSION}" -f docker/Dockerfile . docker-build-latest: docker-build - docker tag "docker.stackable.tech/stackable/lb-operator:${VERSION}" \ - "docker.stackable.tech/stackable/lb-operator:latest" + docker tag "docker.stackable.tech/stackable/listener-operator:${VERSION}" \ + "docker.stackable.tech/stackable/listener-operator:latest" docker-publish: echo "${NEXUS_PASSWORD}" | docker login --username github --password-stdin docker.stackable.tech - docker push --all-tags docker.stackable.tech/stackable/lb-operator + docker push --all-tags docker.stackable.tech/stackable/listener-operator docker: docker-build docker-publish @@ -39,22 +39,22 @@ docker-release: docker-build-latest docker-publish compile-chart: version crds config chart-clean: - rm -rf deploy/helm/lb-operator/configs - rm -rf deploy/helm/lb-operator/crds + rm -rf deploy/helm/listener-operator/configs + rm -rf deploy/helm/listener-operator/crds version: - yq eval -i '.version = strenv(VERSION) | .appVersion = strenv(VERSION)' /dev/stdin < deploy/helm/lb-operator/Chart.yaml + yq eval -i '.version = strenv(VERSION) | .appVersion = strenv(VERSION)' /dev/stdin < deploy/helm/listener-operator/Chart.yaml yq eval -i '.version = strenv(DOCS_VERSION) | .prerelease = strenv(IS_NIGHTLY) != ""' /dev/stdin < docs/antora.yml config: if [ -d "deploy/config-spec/" ]; then\ - mkdir -p deploy/helm/lb-operator/configs;\ - cp -r deploy/config-spec/* deploy/helm/lb-operator/configs;\ + mkdir -p deploy/helm/listener-operator/configs;\ + cp -r deploy/config-spec/* deploy/helm/listener-operator/configs;\ fi crds: - mkdir -p deploy/helm/lb-operator/crds - cargo run --bin stackable-lb-operator -- crd | yq eval '.metadata.annotations["helm.sh/resource-policy"]="keep"' - > deploy/helm/lb-operator/crds/crds.yaml + mkdir -p deploy/helm/listener-operator/crds + cargo run --bin stackable-listener-operator -- crd | yq eval '.metadata.annotations["helm.sh/resource-policy"]="keep"' - > deploy/helm/listener-operator/crds/crds.yaml chart-lint: compile-chart docker run -it -v $(shell pwd):/build/helm-charts -w /build/helm-charts quay.io/helmpack/chart-testing:v3.5.0 ct lint --config deploy/helm/ct.yaml diff --git a/deny.toml b/deny.toml index 0363c332..e40902da 100644 --- a/deny.toml +++ b/deny.toml @@ -35,9 +35,9 @@ allow = [ ] exceptions = [ - { name = "stackable-lb-operator-crd", allow = ["OSL-3.0"] }, - { name = "stackable-lb-operator", allow = ["OSL-3.0"] }, - { name = "stackable-lb-operator-binary", allow = ["OSL-3.0"] }, + { name = "stackable-listener-operator-crd", allow = ["OSL-3.0"] }, + { name = "stackable-listener-operator", allow = ["OSL-3.0"] }, + { name = "stackable-listener-operator-binary", allow = ["OSL-3.0"] }, ] [[licenses.clarify]] diff --git a/deploy/DO_NOT_EDIT.md b/deploy/DO_NOT_EDIT.md index 6fe1a0b9..1b26fd50 100644 --- a/deploy/DO_NOT_EDIT.md +++ b/deploy/DO_NOT_EDIT.md @@ -4,7 +4,8 @@ directory manually. The following files are ok to edit: -- helm/lb-operator/templates/roles.yaml +- helm/listener-operator/templates/roles.yaml +- helm/listener-operator/values.yaml The details are in-motion but check this repository for a few details: diff --git a/deploy/helm/listener-operator/README.md b/deploy/helm/listener-operator/README.md index 7e46335c..90de9394 100644 --- a/deploy/helm/listener-operator/README.md +++ b/deploy/helm/listener-operator/README.md @@ -1,27 +1,27 @@ # Helm Chart for Stackable Operator for Stackable Listener Operator -This Helm Chart can be used to install Custom Resource Definitions and the Stackable Listener Operator. +This Helm Chart can be used to install Custom Resource Definitions and the Operator for Stackable Listener Operator provided by Stackable. ## Requirements - Create a [Kubernetes Cluster](../Readme.md) - Install [Helm](https://helm.sh/docs/intro/install/) -## Install the Stackable Operator for Stackable Load Balancer Operator +## Install the Stackable Operator for Stackable Listener Operator ```bash # From the root of the operator repository make compile-chart -helm install lb-operator deploy/helm/lb-operator +helm install listener-operator deploy/helm/listener-operator ``` ## Usage of the CRDs -The usage of this operator and its CRDs is described in the [documentation](https://docs.stackable.tech/lb-operator/index.html) +The usage of this operator and its CRDs is described in the [documentation](https://docs.stackable.tech/listener-operator/index.html) -The operator has example requests included in the [`/examples`](https://github.com/stackabletech/lb-operator/tree/main/examples) directory. +The operator has example requests included in the [`/examples`](https://github.com/stackabletech/listener-operator/tree/main/examples) directory. ## Links -https://github.com/stackabletech/lb-operator +https://github.com/stackabletech/listener-operator diff --git a/deploy/helm/listener-operator/crds/crds.yaml b/deploy/helm/listener-operator/crds/crds.yaml index 5b0e23eb..8977373d 100644 --- a/deploy/helm/listener-operator/crds/crds.yaml +++ b/deploy/helm/listener-operator/crds/crds.yaml @@ -72,7 +72,7 @@ spec: description: "Auto-generated derived type for LoadBalancerSpec via `CustomResource`" properties: spec: - description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the servuce" + description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" properties: className: description: "The name of the [`LoadBalancerClass`]." diff --git a/deploy/manifests/configmap.yaml b/deploy/manifests/configmap.yaml index 7ed5816f..010a21fe 100644 --- a/deploy/manifests/configmap.yaml +++ b/deploy/manifests/configmap.yaml @@ -3,8 +3,8 @@ apiVersion: v1 data: {} kind: ConfigMap metadata: - name: lb-operator-configmap + name: listener-operator-configmap labels: - app.kubernetes.io/name: lb-operator - app.kubernetes.io/instance: lb-operator + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator app.kubernetes.io/version: "0.1.0-nightly" diff --git a/deploy/manifests/crds.yaml b/deploy/manifests/crds.yaml index 0aebbbb4..46306ad7 100644 --- a/deploy/manifests/crds.yaml +++ b/deploy/manifests/crds.yaml @@ -73,7 +73,7 @@ spec: description: "Auto-generated derived type for LoadBalancerSpec via `CustomResource`" properties: spec: - description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the servuce" + description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" properties: className: description: "The name of the [`LoadBalancerClass`]." diff --git a/deploy/manifests/daemonset.yaml b/deploy/manifests/daemonset.yaml index a6755f50..5b4bfce7 100644 --- a/deploy/manifests/daemonset.yaml +++ b/deploy/manifests/daemonset.yaml @@ -2,26 +2,26 @@ apiVersion: apps/v1 kind: DaemonSet metadata: - name: lb-operator-daemonset + name: listener-operator-daemonset labels: - app.kubernetes.io/name: lb-operator - app.kubernetes.io/instance: lb-operator + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator app.kubernetes.io/version: "0.1.0-nightly" spec: selector: matchLabels: - app.kubernetes.io/name: lb-operator - app.kubernetes.io/instance: lb-operator + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator template: metadata: labels: - app.kubernetes.io/name: lb-operator - app.kubernetes.io/instance: lb-operator + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator spec: - serviceAccountName: lb-operator-serviceaccount + serviceAccountName: listener-operator-serviceaccount securityContext: {} containers: - - name: lb-operator + - name: listener-operator securityContext: privileged: true runAsUser: 0 diff --git a/deploy/manifests/roles.yaml b/deploy/manifests/roles.yaml index ff932ec6..f7e390a4 100644 --- a/deploy/manifests/roles.yaml +++ b/deploy/manifests/roles.yaml @@ -2,7 +2,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: lb-operator-clusterrole + name: listener-operator-clusterrole rules: - apiGroups: - "" diff --git a/deploy/manifests/serviceaccount.yaml b/deploy/manifests/serviceaccount.yaml index 449784b6..5cb7fa4a 100644 --- a/deploy/manifests/serviceaccount.yaml +++ b/deploy/manifests/serviceaccount.yaml @@ -2,26 +2,26 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: lb-operator-serviceaccount + name: listener-operator-serviceaccount labels: - app.kubernetes.io/name: lb-operator - app.kubernetes.io/instance: lb-operator + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator app.kubernetes.io/version: "0.1.0-nightly" --- apiVersion: rbac.authorization.k8s.io/v1 # This cluster role binding allows anyone in the "manager" group to read secrets in any namespace. kind: ClusterRoleBinding metadata: - name: lb-operator-clusterrolebinding + name: listener-operator-clusterrolebinding labels: - app.kubernetes.io/name: lb-operator - app.kubernetes.io/instance: lb-operator + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator app.kubernetes.io/version: "0.1.0-nightly" subjects: - kind: ServiceAccount - name: lb-operator-serviceaccount + name: listener-operator-serviceaccount namespace: default roleRef: kind: ClusterRole - name: lb-operator-clusterrole + name: listener-operator-clusterrole apiGroup: rbac.authorization.k8s.io diff --git a/docker/Dockerfile b/docker/Dockerfile index 9541181c..80434596 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -9,13 +9,13 @@ FROM registry.access.redhat.com/ubi8/ubi-minimal AS operator ARG VERSION ARG RELEASE="1" -LABEL name="Stackable Operator for Stackable Load Balancer Operator" \ +LABEL name="Stackable Operator for Stackable Listener Operator" \ maintainer="info@stackable.de" \ vendor="Stackable GmbH" \ version="${VERSION}" \ release="${RELEASE}" \ - summary="Deploy and manage Stackable Load Balancer Operator clusters." \ - description="Deploy and manage Stackable Load Balancer Operator clusters." + summary="Deploy and manage Stackable Listener Operator clusters." \ + description="Deploy and manage Stackable Listener Operator clusters." # Update image RUN microdnf install -y yum \ @@ -25,11 +25,11 @@ RUN microdnf install -y yum \ COPY LICENSE /licenses/LICENSE -COPY --from=builder /app/stackable-lb-operator / +COPY --from=builder /app/stackable-listener-operator / RUN groupadd -g 1000 stackable && adduser -u 1000 -g stackable -c 'Stackable Operator' stackable USER stackable:stackable -ENTRYPOINT ["/stackable-lb-operator"] +ENTRYPOINT ["/stackable-listener-operator"] CMD ["run"] diff --git a/scripts/generate-manifests.sh b/scripts/generate-manifests.sh index e0078e66..8edcae8e 100755 --- a/scripts/generate-manifests.sh +++ b/scripts/generate-manifests.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# This script reads a Helm chart from deploy/helm/lb-operator and +# This script reads a Helm chart from deploy/helm/listener-operator and # generates manifest files into deploy/manifestss set -e @@ -7,15 +7,15 @@ tmp=$(mktemp -d ./manifests-XXXXX) helm template --output-dir "$tmp" \ --include-crds \ - --name-template lb-operator \ - deploy/helm/lb-operator + --name-template listener-operator \ + deploy/helm/listener-operator -for file in "$tmp"/lb-operator/*/*; do +for file in "$tmp"/listener-operator/*/*; do yq eval -i 'del(.. | select(has("app.kubernetes.io/managed-by")) | ."app.kubernetes.io/managed-by")' /dev/stdin < "$file" yq eval -i 'del(.. | select(has("helm.sh/chart")) | ."helm.sh/chart")' /dev/stdin < "$file" sed -i '/# Source: .*/d' "$file" done -cp -r "$tmp"/lb-operator/*/* deploy/manifests/ +cp -r "$tmp"/listener-operator/*/* deploy/manifests/ rm -rf "$tmp" From 6474a6fde89d8cdd0fd72d485718d227eeb913f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 15:54:27 +0200 Subject: [PATCH 45/99] Finish rebranding --- README.md | 15 ++-- Tiltfile | 10 +-- default.nix | 13 ++- deploy/helm/listener-operator/crds/crds.yaml | 36 ++++----- .../templates/csidriver.yaml | 2 +- .../templates/daemonset.yaml | 6 +- .../templates/lb-classes.yaml | 14 ---- .../templates/listener-classes.yaml | 14 ++++ .../listener-operator/templates/roles.yaml | 12 +-- .../templates/storageclass.yaml | 4 +- deploy/helm/listener-operator/values.yaml | 6 +- deploy/manifests/crds.yaml | 36 ++++----- deploy/manifests/csidriver.yaml | 2 +- deploy/manifests/daemonset.yaml | 8 +- deploy/manifests/lb-classes.yaml | 14 ---- deploy/manifests/listener-classes.yaml | 14 ++++ deploy/manifests/roles.yaml | 12 +-- deploy/manifests/storageclass.yaml | 4 +- docs/antora.yml | 4 +- .../ROOT/examples/lbclass-public-gke.yaml | 7 -- .../ROOT/examples/lbclass-public-onprem.yaml | 7 -- ...e.yaml => listenerclass-internal-gke.yaml} | 4 +- .../examples/listenerclass-public-gke.yaml | 7 ++ .../examples/listenerclass-public-onprem.yaml | 7 ++ docs/modules/ROOT/examples/usage-pod.yaml | 10 +-- docs/modules/ROOT/nav.adoc | 4 +- docs/modules/ROOT/pages/building.adoc | 6 +- docs/modules/ROOT/pages/index.adoc | 4 +- docs/modules/ROOT/pages/installation.adoc | 6 +- docs/modules/ROOT/pages/listener.adoc | 32 ++++++++ docs/modules/ROOT/pages/listenerclass.adoc | 26 ++++++ docs/modules/ROOT/pages/loadbalancer.adoc | 32 -------- .../modules/ROOT/pages/loadbalancerclass.adoc | 27 ------- docs/modules/ROOT/pages/usage.adoc | 14 ++-- docs/modules/ROOT/pages/volume.adoc | 20 ++--- examples/nginx-lb.yaml | 10 +-- examples/nginx-nodeport.yaml | 10 +-- examples/nginx-preprovisioned-lb.yaml | 16 ++-- rust/listener-operator/src/crd.rs | 28 +++---- .../src/csi_server/controller.rs | 53 ++++++------ .../src/csi_server/identity.rs | 8 +- rust/listener-operator/src/csi_server/mod.rs | 14 ++-- rust/listener-operator/src/csi_server/node.rs | 81 ++++++++++--------- ...b_controller.rs => listener_controller.rs} | 74 +++++++++-------- rust/listener-operator/src/main.rs | 28 ++++--- .../smoke-nodeport/00-create-lbclass.yaml | 7 -- .../00-create-listenerclass.yaml | 7 ++ .../01-create-nginx-statefulset.yaml | 10 +-- .../kuttl/smoke-nodeport/02-assert.yaml | 4 +- 49 files changed, 393 insertions(+), 396 deletions(-) delete mode 100644 deploy/helm/listener-operator/templates/lb-classes.yaml create mode 100644 deploy/helm/listener-operator/templates/listener-classes.yaml delete mode 100644 deploy/manifests/lb-classes.yaml create mode 100644 deploy/manifests/listener-classes.yaml delete mode 100644 docs/modules/ROOT/examples/lbclass-public-gke.yaml delete mode 100644 docs/modules/ROOT/examples/lbclass-public-onprem.yaml rename docs/modules/ROOT/examples/{lbclass-internal-gke.yaml => listenerclass-internal-gke.yaml} (67%) create mode 100644 docs/modules/ROOT/examples/listenerclass-public-gke.yaml create mode 100644 docs/modules/ROOT/examples/listenerclass-public-onprem.yaml create mode 100644 docs/modules/ROOT/pages/listener.adoc create mode 100644 docs/modules/ROOT/pages/listenerclass.adoc delete mode 100644 docs/modules/ROOT/pages/loadbalancer.adoc delete mode 100644 docs/modules/ROOT/pages/loadbalancerclass.adoc rename rust/listener-operator/src/{lb_controller.rs => listener_controller.rs} (78%) delete mode 100644 tests/templates/kuttl/smoke-nodeport/00-create-lbclass.yaml create mode 100644 tests/templates/kuttl/smoke-nodeport/00-create-listenerclass.yaml diff --git a/README.md b/README.md index c95559fe..6e4bcc4c 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,29 @@ -# Stackable Load Balancer Operator +# Stackable Listener Operator A CSI provider intended to provide an abstract way to expose a single Pod to the outside network, while hiding details about the cluster from the application developer. -This is intended to be used by services that perform their own clustering and replica discovery, -and require external clients to connect to the correct replica. For example, this would be suitable -for HDFS DataNodes and Kafka listener connections, but not so much for HDFS NameNodes, or Kafka bootstrap -addresses. - ## Usage ### Running `nix run -f. tilt up` -### LoadBalancerClass +### ListenerClass -`LoadBalancerClass` objects are used by cluster administrators to define a policy for how incoming connections +`ListenerClass` objects are used by cluster administrators to define a policy for how incoming connections should be handled. For example, a small on-prem cluster might prefer to use `NodePort` services (because they don't require BGP peering or ARP spoofing, at the cost of making each instance "sticky" to its initial K8s Node), while a managed cloud cluster might prefer `LoadBalancer`. ### Pods -Pods are exposed by mounting a `PersistentVolume` with the `storageClassName` of `lb.stackable.tech` into them. +Pods are exposed by mounting a `PersistentVolume` with the `storageClassName` of `listeners.stackable.tech` into them. This can either be created as a `volumeClaimTemplate` of a `StatefulSet` (ensuring that each network identity will be persistent for each replica identity, even across pod replacements) or an `ephemeral` pod `Volume` (in which case the network identity will be recreated from scratch for every Pod). -The `LoadBalancerClass` is specified using the `lb.stackable.tech/lb-class` annotation on the `PersistentVolumeClaim`. +The `ListenerClass` is specified using the `listeners.stackable.tech/listener-class` annotation on the `PersistentVolumeClaim`. The mounted volume will contain the file `address` (containing the external address of the `Pod`), as well as `ports/{port-name}` (containing the port number that the port is accessible on `address` from, which may or may not diff --git a/Tiltfile b/Tiltfile index d9bc371b..85c36c2f 100644 --- a/Tiltfile +++ b/Tiltfile @@ -1,8 +1,8 @@ default_registry("docker.stackable.tech/sandbox") custom_build( - 'docker.stackable.tech/sandbox/lb-operator', - 'nix run -f . crate2nix generate && nix-build . -A docker --argstr dockerName "${EXPECTED_REGISTRY}/lb-operator" && ./result/load-image | docker load', + 'docker.stackable.tech/sandbox/listener-operator', + 'nix run -f . crate2nix generate && nix-build . -A docker --argstr dockerName "${EXPECTED_REGISTRY}/listener-operator" && ./result/load-image | docker load', deps=['rust', 'Cargo.toml', 'Cargo.lock', 'default.nix', "nix", 'build.rs', 'vendor'], # ignore=['result*', 'Cargo.nix', 'target', *.yaml], outputs_image_ref_to='result/ref', @@ -16,10 +16,10 @@ if os.path.exists('result'): # Exclude stale CRDs from Helm chart, and apply the rest helm_crds, helm_non_crds = filter_yaml( helm( - 'deploy/helm/lb-operator', - name='lb-operator', + 'deploy/helm/listener-operator', + name='listener-operator', set=[ - 'image.repository=docker.stackable.tech/sandbox/lb-operator', + 'image.repository=docker.stackable.tech/sandbox/listener-operator', ], ), api_version = "^apiextensions\\.k8s\\.io/.*$", diff --git a/default.nix b/default.nix index e9bec3ce..b67a88e4 100644 --- a/default.nix +++ b/default.nix @@ -10,19 +10,16 @@ tonic-reflection = attrs: { buildInputs = [ pkgs.rustfmt ]; }; - stackable-lb-operator = attrs: { - buildInputs = [ pkgs.rustfmt ]; - }; }; } -, dockerName ? "docker.stackable.tech/sandbox/lb-operator" +, dockerName ? "docker.stackable.tech/sandbox/listener-operator" , dockerTag ? null }: rec { build = cargo.rootCrate.build; - crds = pkgs.runCommand "lb-operator-crds.yaml" {} + crds = pkgs.runCommand "listener-operator-crds.yaml" {} '' - ${build}/bin/stackable-lb-operator crd > $out + ${build}/bin/stackable-listener-operator crd > $out ''; dockerImage = pkgs.dockerTools.streamLayeredImage { @@ -30,10 +27,10 @@ rec { tag = dockerTag; contents = [ pkgs.bashInteractive pkgs.coreutils pkgs.util-linuxMinimal ]; config = { - Cmd = [ (build+"/bin/stackable-lb-operator") "run" ]; + Cmd = [ (build+"/bin/stackable-listener-operator") "run" ]; }; }; - docker = pkgs.linkFarm "lb-operator-docker" [ + docker = pkgs.linkFarm "listener-operator-docker" [ { name = "load-image"; path = dockerImage; diff --git a/deploy/helm/listener-operator/crds/crds.yaml b/deploy/helm/listener-operator/crds/crds.yaml index 8977373d..5f98fbc7 100644 --- a/deploy/helm/listener-operator/crds/crds.yaml +++ b/deploy/helm/listener-operator/crds/crds.yaml @@ -2,25 +2,24 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: loadbalancerclasses.lb.stackable.tech + name: listenerclasses.listeners.stackable.tech annotations: helm.sh/resource-policy: keep spec: - group: lb.stackable.tech + group: listeners.stackable.tech names: categories: [] - kind: LoadBalancerClass - plural: loadbalancerclasses - shortNames: - - lbclass - singular: loadbalancerclass + kind: ListenerClass + plural: listenerclasses + shortNames: [] + singular: listenerclass scope: Cluster versions: - additionalPrinterColumns: [] name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for LoadBalancerClassSpec via `CustomResource`" + description: "Auto-generated derived type for ListenerClassSpec via `CustomResource`" properties: spec: description: "Defines a policy for how [`LoadBalancer`]s should be exposed." @@ -42,7 +41,7 @@ spec: type: object required: - spec - title: LoadBalancerClass + title: ListenerClass type: object served: true storage: true @@ -51,25 +50,24 @@ spec: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: loadbalancers.lb.stackable.tech + name: listeners.listeners.stackable.tech annotations: helm.sh/resource-policy: keep spec: - group: lb.stackable.tech + group: listeners.stackable.tech names: categories: [] - kind: LoadBalancer - plural: loadbalancers - shortNames: - - lb - singular: loadbalancer + kind: Listener + plural: listeners + shortNames: [] + singular: listener scope: Namespaced versions: - additionalPrinterColumns: [] name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for LoadBalancerSpec via `CustomResource`" + description: "Auto-generated derived type for ListenerSpec via `CustomResource`" properties: spec: description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" @@ -134,7 +132,7 @@ spec: additionalProperties: format: int32 type: integer - description: "Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by lb-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does not require [`Node`]-local access." + description: "Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by listener-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does not require [`Node`]-local access." nullable: true type: object serviceName: @@ -144,7 +142,7 @@ spec: type: object required: - spec - title: LoadBalancer + title: Listener type: object served: true storage: true diff --git a/deploy/helm/listener-operator/templates/csidriver.yaml b/deploy/helm/listener-operator/templates/csidriver.yaml index d327cad3..c819bc84 100644 --- a/deploy/helm/listener-operator/templates/csidriver.yaml +++ b/deploy/helm/listener-operator/templates/csidriver.yaml @@ -2,7 +2,7 @@ apiVersion: storage.k8s.io/v1 kind: CSIDriver metadata: - name: lb.stackable.tech + name: listeners.stackable.tech spec: attachRequired: false podInfoOnMount: true diff --git a/deploy/helm/listener-operator/templates/daemonset.yaml b/deploy/helm/listener-operator/templates/daemonset.yaml index e6cdb3bd..3dbf3fa7 100644 --- a/deploy/helm/listener-operator/templates/daemonset.yaml +++ b/deploy/helm/listener-operator/templates/daemonset.yaml @@ -60,7 +60,7 @@ spec: image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0 args: - --csi-address=/csi/csi.sock - - --kubelet-registration-path=/var/lib/kubelet/plugins/lb.stackable.tech/csi.sock + - --kubelet-registration-path=/var/lib/kubelet/plugins/listeners.stackable.tech/csi.sock volumeMounts: - name: registration-sock mountPath: /registration @@ -69,10 +69,10 @@ spec: volumes: - name: registration-sock hostPath: - path: /var/lib/kubelet/plugins_registry/lb.stackable.tech-reg.sock + path: /var/lib/kubelet/plugins_registry/listeners.stackable.tech-reg.sock - name: csi hostPath: - path: /var/lib/kubelet/plugins/lb.stackable.tech/ + path: /var/lib/kubelet/plugins/listeners.stackable.tech/ - name: mountpoint hostPath: path: /var/lib/kubelet/pods/ diff --git a/deploy/helm/listener-operator/templates/lb-classes.yaml b/deploy/helm/listener-operator/templates/lb-classes.yaml deleted file mode 100644 index 85c4e0fb..00000000 --- a/deploy/helm/listener-operator/templates/lb-classes.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancerClass -metadata: - name: nodeport -spec: - serviceType: NodePort ---- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancerClass -metadata: - name: lb-external -spec: - serviceType: LoadBalancer diff --git a/deploy/helm/listener-operator/templates/listener-classes.yaml b/deploy/helm/listener-operator/templates/listener-classes.yaml new file mode 100644 index 00000000..0c404940 --- /dev/null +++ b/deploy/helm/listener-operator/templates/listener-classes.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: listeners.stackable.tech/v1alpha1 +kind: ListenerClass +metadata: + name: nodeport +spec: + serviceType: NodePort +--- +apiVersion: listeners.stackable.tech/v1alpha1 +kind: ListenerClass +metadata: + name: lb-external +spec: + serviceType: LoadBalancer diff --git a/deploy/helm/listener-operator/templates/roles.yaml b/deploy/helm/listener-operator/templates/roles.yaml index bb284dca..40c4ef76 100644 --- a/deploy/helm/listener-operator/templates/roles.yaml +++ b/deploy/helm/listener-operator/templates/roles.yaml @@ -59,19 +59,19 @@ rules: verbs: - create - apiGroups: - - lb.stackable.tech + - listeners.stackable.tech resources: - - loadbalancerclasses - - loadbalancers + - listenerclasses + - listeners verbs: - get - list - watch - apiGroups: - - lb.stackable.tech + - listeners.stackable.tech resources: - - loadbalancers - - loadbalancers/status + - listeners + - listeners/status verbs: - patch - create diff --git a/deploy/helm/listener-operator/templates/storageclass.yaml b/deploy/helm/listener-operator/templates/storageclass.yaml index 58074654..59f2c5d5 100644 --- a/deploy/helm/listener-operator/templates/storageclass.yaml +++ b/deploy/helm/listener-operator/templates/storageclass.yaml @@ -2,6 +2,6 @@ apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: - name: lb.stackable.tech -provisioner: lb.stackable.tech + name: listeners.stackable.tech +provisioner: listeners.stackable.tech volumeBindingMode: WaitForFirstConsumer diff --git a/deploy/helm/listener-operator/values.yaml b/deploy/helm/listener-operator/values.yaml index 85c422ba..3448a385 100644 --- a/deploy/helm/listener-operator/values.yaml +++ b/deploy/helm/listener-operator/values.yaml @@ -1,7 +1,7 @@ -# Default values for lb-operator. +# Default values for listener-operator. --- image: - repository: docker.stackable.tech/stackable/lb-operator + repository: docker.stackable.tech/stackable/listener-operator pullPolicy: IfNotPresent imagePullSecrets: [] @@ -23,7 +23,7 @@ podSecurityContext: {} # fsGroup: 2000 securityContext: - # lb-operator requires root permissions + # listener-operator requires root permissions runAsUser: 0 privileged: true # capabilities: diff --git a/deploy/manifests/crds.yaml b/deploy/manifests/crds.yaml index 46306ad7..6c4d1471 100644 --- a/deploy/manifests/crds.yaml +++ b/deploy/manifests/crds.yaml @@ -3,25 +3,24 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: loadbalancerclasses.lb.stackable.tech + name: listenerclasses.listeners.stackable.tech annotations: helm.sh/resource-policy: keep spec: - group: lb.stackable.tech + group: listeners.stackable.tech names: categories: [] - kind: LoadBalancerClass - plural: loadbalancerclasses - shortNames: - - lbclass - singular: loadbalancerclass + kind: ListenerClass + plural: listenerclasses + shortNames: [] + singular: listenerclass scope: Cluster versions: - additionalPrinterColumns: [] name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for LoadBalancerClassSpec via `CustomResource`" + description: "Auto-generated derived type for ListenerClassSpec via `CustomResource`" properties: spec: description: "Defines a policy for how [`LoadBalancer`]s should be exposed." @@ -43,7 +42,7 @@ spec: type: object required: - spec - title: LoadBalancerClass + title: ListenerClass type: object served: true storage: true @@ -52,25 +51,24 @@ spec: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: loadbalancers.lb.stackable.tech + name: listeners.listeners.stackable.tech annotations: helm.sh/resource-policy: keep spec: - group: lb.stackable.tech + group: listeners.stackable.tech names: categories: [] - kind: LoadBalancer - plural: loadbalancers - shortNames: - - lb - singular: loadbalancer + kind: Listener + plural: listeners + shortNames: [] + singular: listener scope: Namespaced versions: - additionalPrinterColumns: [] name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for LoadBalancerSpec via `CustomResource`" + description: "Auto-generated derived type for ListenerSpec via `CustomResource`" properties: spec: description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" @@ -135,7 +133,7 @@ spec: additionalProperties: format: int32 type: integer - description: "Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by lb-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does not require [`Node`]-local access." + description: "Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by listener-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does not require [`Node`]-local access." nullable: true type: object serviceName: @@ -145,7 +143,7 @@ spec: type: object required: - spec - title: LoadBalancer + title: Listener type: object served: true storage: true diff --git a/deploy/manifests/csidriver.yaml b/deploy/manifests/csidriver.yaml index d327cad3..c819bc84 100644 --- a/deploy/manifests/csidriver.yaml +++ b/deploy/manifests/csidriver.yaml @@ -2,7 +2,7 @@ apiVersion: storage.k8s.io/v1 kind: CSIDriver metadata: - name: lb.stackable.tech + name: listeners.stackable.tech spec: attachRequired: false podInfoOnMount: true diff --git a/deploy/manifests/daemonset.yaml b/deploy/manifests/daemonset.yaml index 5b4bfce7..402b072c 100644 --- a/deploy/manifests/daemonset.yaml +++ b/deploy/manifests/daemonset.yaml @@ -25,7 +25,7 @@ spec: securityContext: privileged: true runAsUser: 0 - image: "docker.stackable.tech/stackable/lb-operator:0.1.0-nightly" + image: "docker.stackable.tech/stackable/listener-operator:0.1.0-nightly" imagePullPolicy: IfNotPresent resources: {} env: @@ -55,7 +55,7 @@ spec: image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0 args: - --csi-address=/csi/csi.sock - - --kubelet-registration-path=/var/lib/kubelet/plugins/lb.stackable.tech/csi.sock + - --kubelet-registration-path=/var/lib/kubelet/plugins/listeners.stackable.tech/csi.sock volumeMounts: - name: registration-sock mountPath: /registration @@ -64,10 +64,10 @@ spec: volumes: - name: registration-sock hostPath: - path: /var/lib/kubelet/plugins_registry/lb.stackable.tech-reg.sock + path: /var/lib/kubelet/plugins_registry/listeners.stackable.tech-reg.sock - name: csi hostPath: - path: /var/lib/kubelet/plugins/lb.stackable.tech/ + path: /var/lib/kubelet/plugins/listeners.stackable.tech/ - name: mountpoint hostPath: path: /var/lib/kubelet/pods/ diff --git a/deploy/manifests/lb-classes.yaml b/deploy/manifests/lb-classes.yaml deleted file mode 100644 index 85c4e0fb..00000000 --- a/deploy/manifests/lb-classes.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancerClass -metadata: - name: nodeport -spec: - serviceType: NodePort ---- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancerClass -metadata: - name: lb-external -spec: - serviceType: LoadBalancer diff --git a/deploy/manifests/listener-classes.yaml b/deploy/manifests/listener-classes.yaml new file mode 100644 index 00000000..0c404940 --- /dev/null +++ b/deploy/manifests/listener-classes.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: listeners.stackable.tech/v1alpha1 +kind: ListenerClass +metadata: + name: nodeport +spec: + serviceType: NodePort +--- +apiVersion: listeners.stackable.tech/v1alpha1 +kind: ListenerClass +metadata: + name: lb-external +spec: + serviceType: LoadBalancer diff --git a/deploy/manifests/roles.yaml b/deploy/manifests/roles.yaml index f7e390a4..95830fee 100644 --- a/deploy/manifests/roles.yaml +++ b/deploy/manifests/roles.yaml @@ -59,19 +59,19 @@ rules: verbs: - create - apiGroups: - - lb.stackable.tech + - listeners.stackable.tech resources: - - loadbalancerclasses - - loadbalancers + - listenerclasses + - listeners verbs: - get - list - watch - apiGroups: - - lb.stackable.tech + - listeners.stackable.tech resources: - - loadbalancers - - loadbalancers/status + - listeners + - listeners/status verbs: - patch - create diff --git a/deploy/manifests/storageclass.yaml b/deploy/manifests/storageclass.yaml index 58074654..59f2c5d5 100644 --- a/deploy/manifests/storageclass.yaml +++ b/deploy/manifests/storageclass.yaml @@ -2,6 +2,6 @@ apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: - name: lb.stackable.tech -provisioner: lb.stackable.tech + name: listeners.stackable.tech +provisioner: listeners.stackable.tech volumeBindingMode: WaitForFirstConsumer diff --git a/docs/antora.yml b/docs/antora.yml index 55024b97..8307319c 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,7 +1,7 @@ --- -name: lb-operator +name: listener-operator version: "nightly" -title: Stackable LB Operator +title: Stackable Listener Operator nav: - modules/ROOT/nav.adoc prerelease: true diff --git a/docs/modules/ROOT/examples/lbclass-public-gke.yaml b/docs/modules/ROOT/examples/lbclass-public-gke.yaml deleted file mode 100644 index 66ad418d..00000000 --- a/docs/modules/ROOT/examples/lbclass-public-gke.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancerClass -metadata: - name: public -spec: - serviceType: LoadBalancer diff --git a/docs/modules/ROOT/examples/lbclass-public-onprem.yaml b/docs/modules/ROOT/examples/lbclass-public-onprem.yaml deleted file mode 100644 index ad238c75..00000000 --- a/docs/modules/ROOT/examples/lbclass-public-onprem.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancerClass -metadata: - name: public -spec: - serviceType: NodePort diff --git a/docs/modules/ROOT/examples/lbclass-internal-gke.yaml b/docs/modules/ROOT/examples/listenerclass-internal-gke.yaml similarity index 67% rename from docs/modules/ROOT/examples/lbclass-internal-gke.yaml rename to docs/modules/ROOT/examples/listenerclass-internal-gke.yaml index 4e796542..04fafba8 100644 --- a/docs/modules/ROOT/examples/lbclass-internal-gke.yaml +++ b/docs/modules/ROOT/examples/listenerclass-internal-gke.yaml @@ -1,6 +1,6 @@ --- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancerClass +apiVersion: listeners.stackable.tech/v1alpha1 +kind: ListenerClass metadata: name: internal spec: diff --git a/docs/modules/ROOT/examples/listenerclass-public-gke.yaml b/docs/modules/ROOT/examples/listenerclass-public-gke.yaml new file mode 100644 index 00000000..7709281b --- /dev/null +++ b/docs/modules/ROOT/examples/listenerclass-public-gke.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: listeners.stackable.tech/v1alpha1 +kind: ListenerClass +metadata: + name: public +spec: + serviceType: LoadBalancer diff --git a/docs/modules/ROOT/examples/listenerclass-public-onprem.yaml b/docs/modules/ROOT/examples/listenerclass-public-onprem.yaml new file mode 100644 index 00000000..ed27bace --- /dev/null +++ b/docs/modules/ROOT/examples/listenerclass-public-onprem.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: listeners.stackable.tech/v1alpha1 +kind: ListenerClass +metadata: + name: public +spec: + serviceType: NodePort diff --git a/docs/modules/ROOT/examples/usage-pod.yaml b/docs/modules/ROOT/examples/usage-pod.yaml index 1237f94b..80ab4668 100644 --- a/docs/modules/ROOT/examples/usage-pod.yaml +++ b/docs/modules/ROOT/examples/usage-pod.yaml @@ -5,14 +5,14 @@ metadata: name: example-public-pod spec: volumes: - - name: lb + - name: listener ephemeral: # <1> volumeClaimTemplate: metadata: annotations: - lb.stackable.tech/lb-class: public # <2> + listeners.stackable.tech/listener-class: public # <2> spec: - storageClassName: lb.stackable.tech + storageClassName: listeners.stackable.tech accessModes: - ReadWriteMany resources: @@ -22,5 +22,5 @@ spec: - name: nginx image: nginx volumeMounts: - - name: lb - mountPath: /lb # <3> + - name: listener + mountPath: /listener # <3> diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 58dbb7e2..964b201e 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -3,7 +3,7 @@ * xref:configuration.adoc[] * xref:usage.adoc[] * Concepts -** xref:loadbalancer.adoc[] -** xref:loadbalancerclass.adoc[] +** xref:listener.adoc[] +** xref:listener.adoc[] ** xref:volume.adoc[] diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index 1dd95c05..2c7e372e 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -25,14 +25,14 @@ $ git submodule update --recursive --init # Update the Chart metadata and CRD definitions $ make compile-chart # Create a unique image ID -$ REPO=lb-operator +$ REPO=listener-operator $ TAG="$(uuidgen)" # Build the image $ docker build . -f docker/Dockerfile -t "$REPO:$TAG" # Load the image onto the Kind nodes $ kind load docker-image "$REPO:$TAG" # Deploy -$ helm upgrade lb-operator deploy/helm/lb-operator \ +$ helm upgrade listener-operator deploy/helm/listener-operator \ --install \ --set-string "image.repository=$REPO,image.tag=$TAG" ---- @@ -58,7 +58,7 @@ $ nix build -f . docker $ kind load image-archive <(./result/load-image) # Deploy $ kubectl apply -f result/crds.yaml -f provisioner.yaml -$ kubectl rollout restart ds/lb-provisioner +$ kubectl rollout restart ds/listener-provisioner ---- You may need to add `extra-experimental-features = nix-command` to `/etc/nix/nix.conf`, or add `--experimental-features nix-command` to the Nix commands. diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 866a3c00..d44b0d32 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -1,3 +1,3 @@ -= Stackable LB Operator += Stackable Listener Operator -This is an operator for Kubernetes that provisions load balancers and injects connection parameters into Pods. +This is an operator for Kubernetes that provisions network listeners according to cluster policy, and injects connection parameters into Pods. diff --git a/docs/modules/ROOT/pages/installation.adoc b/docs/modules/ROOT/pages/installation.adoc index 6f434deb..35a19313 100644 --- a/docs/modules/ROOT/pages/installation.adoc +++ b/docs/modules/ROOT/pages/installation.adoc @@ -1,6 +1,6 @@ = Installation -There are two ways to run the Stackable LB Operator: +There are two ways to run the Stackable Listener Operator: 1. Helm managed Docker container deployment on Kubernetes @@ -15,11 +15,11 @@ Helm allows you to download and deploy Stackable operators on Kubernetes and is $ helm repo add stackable https://repo.stackable.tech/repository/helm-stable/ ---- -Then install the Stackable LB Operator +Then install the Stackable Listener Operator [source,console] ---- -$ helm install lb-operator stackable/lb-operator +$ helm install listener-operator stackable/listener-operator ---- Helm will deploy the operator in Kubernetes containers and apply the CRDs. You're now ready to expose services! diff --git a/docs/modules/ROOT/pages/listener.adoc b/docs/modules/ROOT/pages/listener.adoc new file mode 100644 index 00000000..00576913 --- /dev/null +++ b/docs/modules/ROOT/pages/listener.adoc @@ -0,0 +1,32 @@ += `Listener` + +A `Listener` object exposes a set of `Pod`s according to the rules of a xref:listenerclass.adoc[], but it also adds a couple of other +features that are useful for the Stackable platform at large. + +== `ListenerClass` + +The exact rules of pod exposure are dictated by the specified xref:listenerclass.adoc[], which allow a single `Listener` definition to be reused in different clusters, regardless of the Kubernetes distribution or cloud provider. + +== Address API + +A `Listener` writes back all addresses that it can be reached on to `Listener.status.ingress_addresses`, which can then be used to generate discovery information. Contrary to Kubernetes' `Service`, this is done regardless of the type of service, and transparently also contains information about remapped ports. + +== Address volume projection + +`Listener` objects can be mounted into a `Pod` as a `PersistentVolumeClaim`, which contains information about how the `Pod` should request that external clients refer to it. + +For example, if the volume is mounted to `/stackable/listener`, the primary address can be read from `/stackable/listener/default-address/address`, and the public `http` port number can be read from `/stackable/listener/default-address/ports/http`. + +== Per-replica LBs + +A `Listener` PVC can also specify a xref:listenerclass.adoc[] rather than a `Listener`, in which case a `Listener` object is created +automatically. These PVCs can automatically be created for each replica using either `StatefulSet` 's `volumeClaimTemplates` (for long-lived LBs that will +be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` (for temporary LBs that are deleted when their corresponding `Pod` is deleted). + +== Sticky scheduling + +When mounting a `Listener` PVC, it will be made "sticky" to that node if the xref:listenerclass.adoc[] uses a strategy that depends on the node +that the workload is running on. + +Keep in mind that this will only work correctly when using long-lived PVCs (such as via `StatefulSet` 's `volumeClaimTemplates`). Ephemeral PVCs +will be "reset" for every pod that is created, even if they refer to a long-lived `Listener` object. diff --git a/docs/modules/ROOT/pages/listenerclass.adoc b/docs/modules/ROOT/pages/listenerclass.adoc new file mode 100644 index 00000000..260065f3 --- /dev/null +++ b/docs/modules/ROOT/pages/listenerclass.adoc @@ -0,0 +1,26 @@ += `ListenerClass` + +A `ListenerClass` defines a category of listeners. For example, this could be "VPC-internal service", "internet-accessible service", or "K8s-internal service". +The `ListenerClass` then defines how this intent is realized in a given cluster. + +For example, a Google Kubernetes Engine (GKE) cluster might want to expose all internet-facing services using a managed load balancer, since GKE nodes are +relatively short-lived and don't have stable addresses: + +[source,yaml] +---- +include::example$listenerclass-public-gke.yaml[] +---- + +On the other hand, an on-premise cluster might not have dedicated load balancer infrastructure at all, but instead use "pet" Nodes which may be expected to live for years. This might lead administrators of such systems to prefer exposing node ports directly instead: + +[source,yaml] +---- +include::example$listenerclass-public-onprem.yaml[] +---- + +Finally, it can be desirable to add additional annotations to a `Service`. For example, a user might want to only expose some services inside a given cloud vendor VPC. How exactly this is accomplished depends on the cloud provider in question, but for GKE this requires the annotation `networking.gke.io/load-balancer-type`: + +[source,yaml] +---- +include::example$listenerclass-internal-gke.yaml[] +---- diff --git a/docs/modules/ROOT/pages/loadbalancer.adoc b/docs/modules/ROOT/pages/loadbalancer.adoc deleted file mode 100644 index c0f13df3..00000000 --- a/docs/modules/ROOT/pages/loadbalancer.adoc +++ /dev/null @@ -1,32 +0,0 @@ -= `LoadBalancer` - -A `LoadBalancer` object exposes a set of `Pod`s according to the rules of a xref:loadbalancerclass.adoc[], but it also adds a couple of other -features that are useful for the Stackable platform at large. - -== `LoadBalancerClass` - -The exact rules of pod exposure are dictated by the specified xref:loadbalancerclass.adoc[], which allow a single `LoadBalancer` definition to be reused in different clusters, regardless of the Kubernetes distribution or cloud provider. - -== Address API - -A `LoadBalancer` writes back all addresses that it can be reached on to `LoadBalancer.status.ingress_addresses`, which can then be used to generate discovery information. Contrary to Kubernetes' `Service`, this is done regardless of the type of service, and transparently also contains information about remapped ports. - -== Address volume projection - -`LoadBalancer` objects can be mounted into a `Pod` as a `PersistentVolumeClaim`, which contains information about how the `Pod` should request that external clients refer to it. - -For example, if the volume is mounted to `/stackable/lb`, the primary address can be read from `/stackable/lb/default-address/address`, and the public `http` port number can be read from `/stackable/lb/default-address/ports/http`. - -== Per-replica LBs - -A `LoadBalancer` PVC can also specify a xref:loadbalancerclass.adoc[] rather than a `LoadBalancer`, in which case a `LoadBalancer` object is created -automatically. These PVCs can automatically be created for each replica using either `StatefulSet` 's `volumeClaimTemplates` (for long-lived LBs that will -be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` (for temporary LBs that are deleted when their corresponding `Pod` is deleted). - -== Sticky scheduling - -When mounting a `LoadBalancer` PVC, it will be made "sticky" to that node if the xref:loadbalancerclass.adoc[] uses a strategy that depends on the node -that the workload is running on. - -Keep in mind that this will only work correctly when using long-lived PVCs (such as via `StatefulSet` 's `volumeClaimTemplates`). Ephemeral PVCs -will be "reset" for every pod that is created, even if they refer to a long-lived `LoadBalancer` object. diff --git a/docs/modules/ROOT/pages/loadbalancerclass.adoc b/docs/modules/ROOT/pages/loadbalancerclass.adoc deleted file mode 100644 index adbb9dc7..00000000 --- a/docs/modules/ROOT/pages/loadbalancerclass.adoc +++ /dev/null @@ -1,27 +0,0 @@ -= `LoadBalancerClass` - -A `LoadBalancerClass` defines a category of load balancers. For example, this could be "VPC-internal service", "internet-accessible service", or "K8s-internal service". -The `LoadBalancerClass` then defines how this intent is realized in a given cluster. - -For example, a Google Kubernetes Engine (GKE) cluster might want to expose all internet-facing services using a xref:loadbalancer.adoc[], since GKE nodes are -relatively short-lived and don't have stable addresses: - -[source,yaml] ----- -include::example$lbclass-public-gke.yaml[] ----- - -On the other hand, an on-premise cluster might not have dedicated load balancer infrastructure at all, but has "pet" Nodes with lifetimes on the orders -of years. This might lead administrators of such systems to prefer exposing node ports directly instead: - -[source,yaml] ----- -include::example$lbclass-public-onprem.yaml[] ----- - -Finally, it can be desirable to add additional annotations to a `Service`. For example, a user might want to only expose some services inside a given cloud vendor VPC. How exactly this is accomplished depends on the cloud provider in question, but for GKE this requires the annotation `networking.gke.io/load-balancer-type`: - -[source,yaml] ----- -include::example$lbclass-internal-gke.yaml[] ----- diff --git a/docs/modules/ROOT/pages/usage.adoc b/docs/modules/ROOT/pages/usage.adoc index 23fc2736..f9ac6cbe 100644 --- a/docs/modules/ROOT/pages/usage.adoc +++ b/docs/modules/ROOT/pages/usage.adoc @@ -1,6 +1,6 @@ = Usage -The operator creates a xref:loadbalancer.adoc[] for each mounted CSI volume with `driver: lb.stackable.tech`. +The operator creates a xref:listener.adoc[] for each mounted CSI volume with `driver: listeners.stackable.tech`. A minimal exposed `Pod` looks like this: @@ -8,20 +8,20 @@ A minimal exposed `Pod` looks like this: ---- include::example$usage-pod.yaml[] ---- -<1> Defines an _ephemeral_ load balancer, meaning that it will automatically be deleted when the `Pod` is. -<2> Defines that we want to expose this pod by automatically creating a service according to the xref:loadbalancerclass.adoc[] `public`. -<3> Mounts metadata about the `LoadBalancer` (such as the port mapping and IP address) into `/lb`. The volume *must* be mounted, even if this data is never used by the `Pod` itself. +<1> Defines an _ephemeral_ listener, meaning that it will automatically be deleted when the `Pod` is. +<2> Defines that we want to expose this pod by automatically creating a service according to the xref:listenerclass.adoc[] `public`. +<3> Mounts metadata about the `Listener` (such as the port mapping and IP address) into `/listener`. The volume *must* be mounted, even if this data is never used by the `Pod` itself. -The exact xref:loadbalancerclass.adoc[] is going to depend on the Kubernetes environment, but should often look like this for public clouds: +The exact xref:listenerclass.adoc[] is going to depend on the Kubernetes environment, but should often look like this for public clouds: [source,yaml] ---- -include::example$lbclass-public-gke.yaml[] +include::example$listenerclass-public-gke.yaml[] ---- Or like this for on-premise environments: [source,yaml] ---- -include::example$lbclass-public-onprem.yaml[] +include::example$listenerclass-public-onprem.yaml[] ---- diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index 88f11f47..ad3aa4a1 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -6,22 +6,22 @@ The LB Operator acts as a CSI `PersistentVolume`, which helps it to stabilize ne == Stable addresses -Some xref:loadbalancerclass.adoc[] strategies, such as `NodePort`, tie the public address to the Kubernetes node that the `Pod` is running on. When this address must be configured statically in clients +Some xref:listenerclass.adoc[] strategies, such as `NodePort`, tie the public address to the Kubernetes node that the `Pod` is running on. When this address must be configured statically in clients (such as for HDFS NameNodes), then Kubernetes' default "floating" scheduling either requires all clients to be reconfigured every time something moves, or for all clients to proxy their traffic through a single static node, which then becomes a single point of failure (along with the node that the workload is running on). -Mounting load balancers into Pods as `PersistentVolume` allows lb-operator to pin these workloads to one node. Note that this only happens for xref:loadbalancerclass.adoc[] es that actually benefit +Mounting listeners into Pods as `PersistentVolume` allows the Listener Operator to pin these workloads to one node. Note that this only happens for xref:listenerclass.adoc[] es that actually benefit from pinning. == Pod metadata injection -Some services (such as Kafka) need to know their external address, so that they can advertise it to their own replica discovery mechanism. xref:loadbalancer.adoc[] volumes contain a file tree that exposes +Some services (such as Kafka) need to know their external address, so that they can advertise it to their own replica discovery mechanism. xref:listener.adoc[] volumes contain a file tree that exposes this information: [source] ---- - `default-address/`- A symlink to `addresses/\{primary address\}` -- `addresses/` - Contains information about all addresses associated with this xref:loadbalancer.adoc[] +- `addresses/` - Contains information about all addresses associated with this xref:listener.adoc[] - `\{address\}/` - A folder is created for each address - `address` - Contains the Pod's address (IP address or hostname) - `ports/` - Contains port numbers for each named port @@ -44,15 +44,15 @@ The `volumeClaimTemplates` allow volumes to be provisioned for each `StatefulSet All configuration must be specified as `annotations` on the `PersistentVolumeClaim`. The following attributes are currently supported: -=== `lb.stackable.tech/lb-name` +=== `listeners.stackable.tech/listener-name` -*Required*: If `lb.stackable.tech/lb-class` is not specified +*Required*: If `listeners.stackable.tech/listener-class` is not specified -Provisions metadata about an existing xref:loadbalancer.adoc[] that was created manually. +Provisions metadata about an existing xref:listener.adoc[] that was created manually. -=== `lb.stackable.tech/lb-class` +=== `listeners.stackable.tech/listener-class` -*Required*: If `lb.stackable.tech/lb-name` is not specified +*Required*: If `listeners.stackable.tech/listener-name` is not specified -Provisions a new xref:loadbalancer.adoc[] using the specified xref:loadbalancerclass.adoc[]. The created xref:loadbalancer.adoc[] will expose +Provisions a new xref:listener.adoc[] using the specified xref:listenerclass.adoc[]. The created xref:listener.adoc[] will expose all of the `Pod` 's ports. diff --git a/examples/nginx-lb.yaml b/examples/nginx-lb.yaml index c5e7fa34..73d3f3e8 100644 --- a/examples/nginx-lb.yaml +++ b/examples/nginx-lb.yaml @@ -20,8 +20,8 @@ spec: - name: http containerPort: 9999 volumeMounts: - - name: lb - mountPath: /usr/share/nginx/html/lb + - name: listener + mountPath: /usr/share/nginx/html/listener - name: config mountPath: /etc/nginx/templates volumes: @@ -30,13 +30,13 @@ spec: name: exposed-nginx-lb-config volumeClaimTemplates: - metadata: - name: lb + name: listener annotations: - lb.stackable.tech/lb-class: lb-external + listeners.stackable.tech/listener-class: lb-external spec: accessModes: - ReadWriteMany - storageClassName: lb.stackable.tech + storageClassName: listeners.stackable.tech resources: requests: storage: 1 diff --git a/examples/nginx-nodeport.yaml b/examples/nginx-nodeport.yaml index 070d78d7..e6e19fd3 100644 --- a/examples/nginx-nodeport.yaml +++ b/examples/nginx-nodeport.yaml @@ -20,17 +20,17 @@ spec: - name: http containerPort: 80 volumeMounts: - - name: lb - mountPath: /usr/share/nginx/html/lb + - name: listener + mountPath: /usr/share/nginx/html/listener volumeClaimTemplates: - metadata: - name: lb + name: listener annotations: - lb.stackable.tech/lb-class: nodeport + listeners.stackable.tech/listener-class: nodeport spec: accessModes: - ReadWriteMany - storageClassName: lb.stackable.tech + storageClassName: listeners.stackable.tech resources: requests: storage: 1 diff --git a/examples/nginx-preprovisioned-lb.yaml b/examples/nginx-preprovisioned-lb.yaml index e4f675a4..43b34b9f 100644 --- a/examples/nginx-preprovisioned-lb.yaml +++ b/examples/nginx-preprovisioned-lb.yaml @@ -20,25 +20,25 @@ spec: - name: http containerPort: 80 volumeMounts: - - name: lb - mountPath: /usr/share/nginx/html/lb + - name: listener + mountPath: /usr/share/nginx/html/listener volumeClaimTemplates: - metadata: - name: lb + name: listener annotations: - lb.stackable.tech/lb-name: exposed-nginx-preprovisioned-lb + listeners.stackable.tech/listener-name: exposed-nginx-preprovisioned-lb spec: accessModes: - ReadWriteMany - storageClassName: lb.stackable.tech + storageClassName: listeners.stackable.tech resources: requests: storage: 1 --- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancer +apiVersion: listeners.stackable.tech/v1alpha1 +kind: Listener metadata: - name: exposed-nginx-preprovisioned-lb + name: exposed-nginx-preprovisioned-listener spec: className: lb-external ports: diff --git a/rust/listener-operator/src/crd.rs b/rust/listener-operator/src/crd.rs index b6ede1b1..8e141fc7 100644 --- a/rust/listener-operator/src/crd.rs +++ b/rust/listener-operator/src/crd.rs @@ -10,10 +10,9 @@ use stackable_operator::k8s_openapi::api::core::v1::{Node, Pod, Service}; /// Defines a policy for how [`LoadBalancer`]s should be exposed. #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)] #[kube( - group = "lb.stackable.tech", + group = "listeners.stackable.tech", version = "v1alpha1", - kind = "LoadBalancerClass", - shortname = "lbclass", + kind = "ListenerClass", crates( kube_core = "stackable_operator::kube::core", k8s_openapi = "stackable_operator::k8s_openapi", @@ -21,7 +20,7 @@ use stackable_operator::k8s_openapi::api::core::v1::{Node, Pod, Service}; ) )] #[serde(rename_all = "camelCase")] -pub struct LoadBalancerClassSpec { +pub struct ListenerClassSpec { pub service_type: ServiceType, /// Annotations that should be added to the [`Service`] object. #[serde(default)] @@ -44,12 +43,11 @@ pub enum ServiceType { /// 2. It has a consistent API for reading back the exposed address(es) of the service #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default)] #[kube( - group = "lb.stackable.tech", + group = "listeners.stackable.tech", version = "v1alpha1", - kind = "LoadBalancer", - shortname = "lb", + kind = "Listener", namespaced, - status = "LoadBalancerStatus", + status = "ListenerStatus", crates( kube_core = "stackable_operator::kube::core", k8s_openapi = "stackable_operator::k8s_openapi", @@ -57,18 +55,18 @@ pub enum ServiceType { ) )] #[serde(rename_all = "camelCase")] -pub struct LoadBalancerSpec { +pub struct ListenerSpec { /// The name of the [`LoadBalancerClass`]. pub class_name: Option, /// Labels that the [`Pod`]s must share in order to be exposed. pub pod_selector: Option>, /// Ports that should be exposed. - pub ports: Option>, + pub ports: Option>, } #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] -pub struct LoadBalancerPort { +pub struct ListenerPort { /// The name of the port. /// /// The name of each port *must* be unique within a single [`LoadBalancer`]. @@ -82,14 +80,14 @@ pub struct LoadBalancerPort { /// Informs users about how to reach the [`LoadBalancer`]. #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] -pub struct LoadBalancerStatus { +pub struct ListenerStatus { /// The backing Kubernetes [`Service`]. pub service_name: Option, /// All addresses that the [`LoadBalancer`] is currently reachable from. - pub ingress_addresses: Option>, + pub ingress_addresses: Option>, /// Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on. /// - /// This is only intended for internal use by lb-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does + /// This is only intended for internal use by listener-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does /// not require [`Node`]-local access. pub node_ports: Option>, } @@ -97,7 +95,7 @@ pub struct LoadBalancerStatus { /// One address that a [`LoadBalancer`] is accessible from. #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] -pub struct LoadBalancerIngress { +pub struct ListenerIngress { /// The hostname or IP address to the [`LoadBalancer`]. pub address: String, /// Port mapping table. diff --git a/rust/listener-operator/src/csi_server/controller.rs b/rust/listener-operator/src/csi_server/controller.rs index d8c88648..f887703e 100644 --- a/rust/listener-operator/src/csi_server/controller.rs +++ b/rust/listener-operator/src/csi_server/controller.rs @@ -6,15 +6,11 @@ use stackable_operator::{ }; use tonic::{Request, Response, Status}; -use crate::{ - crd::{LoadBalancer, LoadBalancerClass, ServiceType}, - grpc::csi, - utils::error_full_message, -}; +use crate::{crd::ServiceType, grpc::csi, utils::error_full_message}; -use super::{tonic_unimplemented, LbSelector, LbVolumeContext}; +use super::{tonic_unimplemented, ListenerSelector, ListenerVolumeContext}; -pub struct LbOperatorController { +pub struct ListenerOperatorController { pub client: stackable_operator::client::Client, } @@ -38,8 +34,10 @@ enum CreateVolumeError { }, #[snafu(display("failed to decode volume context"))] DecodeVolumeContext { source: serde::de::value::Error }, - #[snafu(display("{lb} does not specify a load balancer class"))] - NoLoadBalancerClass { lb: ObjectRef }, + #[snafu(display("{listener} does not specify a listener class"))] + NoListenerClass { + listener: ObjectRef, + }, } impl From for Status { @@ -49,14 +47,14 @@ impl From for Status { match err { CreateVolumeError::DecodeRequestParams { .. } => Status::invalid_argument(full_msg), CreateVolumeError::DecodeVolumeContext { .. } => Status::invalid_argument(full_msg), - CreateVolumeError::NoLoadBalancerClass { .. } => Status::invalid_argument(full_msg), + CreateVolumeError::NoListenerClass { .. } => Status::invalid_argument(full_msg), CreateVolumeError::GetObject { .. } => Status::unavailable(full_msg), } } } #[tonic::async_trait] -impl csi::v1::controller_server::Controller for LbOperatorController { +impl csi::v1::controller_server::Controller for ListenerOperatorController { async fn controller_get_capabilities( &self, _request: Request, @@ -95,33 +93,36 @@ impl csi::v1::controller_server::Controller for LbOperatorController { .erase(), })?; let raw_volume_context = pvc.metadata.annotations.unwrap_or_default(); - let LbVolumeContext { lb_selector } = - LbVolumeContext::deserialize(raw_volume_context.clone().into_deserializer()) + let ListenerVolumeContext { listener_selector } = + ListenerVolumeContext::deserialize(raw_volume_context.clone().into_deserializer()) .context(create_volume_error::DecodeVolumeContextSnafu)?; - let lb_class_name = match lb_selector { - LbSelector::Lb(lb_name) => { - let lb = self + let listener_class_name = match listener_selector { + ListenerSelector::Listener(listener_name) => { + let listener = self .client - .get::(&lb_name, Some(&ns)) + .get::(&listener_name, Some(&ns)) .await .with_context(|_| GetObjectSnafu { - obj: ObjectRef::::new(&lb_name).within(&ns).erase(), + obj: ObjectRef::::new(&listener_name) + .within(&ns) + .erase(), })?; - lb.spec + listener + .spec .class_name .clone() - .with_context(|| NoLoadBalancerClassSnafu { - lb: ObjectRef::from_obj(&lb), + .with_context(|| NoListenerClassSnafu { + listener: ObjectRef::from_obj(&listener), })? } - LbSelector::LbClass(lb_class) => lb_class, + ListenerSelector::ListenerClass(listener_class) => listener_class, }; - let lb_class = self + let listener_class = self .client - .get::(&lb_class_name, None) + .get::(&listener_class_name, None) .await .with_context(|_| GetObjectSnafu { - obj: ObjectRef::::new(&lb_class_name) + obj: ObjectRef::::new(&listener_class_name) .within(&ns) .erase(), })?; @@ -131,7 +132,7 @@ impl csi::v1::controller_server::Controller for LbOperatorController { volume_id: request.name, volume_context: raw_volume_context.into_iter().collect(), content_source: None, - accessible_topology: match lb_class.spec.service_type { + accessible_topology: match listener_class.spec.service_type { // Pick the top node (as selected by the CSI client) and "stick" to that // Since we want clients to have a stable address to connect to ServiceType::NodePort => request diff --git a/rust/listener-operator/src/csi_server/identity.rs b/rust/listener-operator/src/csi_server/identity.rs index c6281701..595cfeea 100644 --- a/rust/listener-operator/src/csi_server/identity.rs +++ b/rust/listener-operator/src/csi_server/identity.rs @@ -3,18 +3,18 @@ use std::collections::HashMap; use clap::crate_version; use tonic::{Request, Response, Status}; -use crate::grpc::csi; +use crate::{grpc::csi, OPERATOR_KEY}; -pub struct LbOperatorIdentity; +pub struct ListenerOperatorIdentity; #[tonic::async_trait] -impl csi::v1::identity_server::Identity for LbOperatorIdentity { +impl csi::v1::identity_server::Identity for ListenerOperatorIdentity { async fn get_plugin_info( &self, _request: Request, ) -> Result, Status> { Ok(Response::new(csi::v1::GetPluginInfoResponse { - name: "lb.stackable.tech".to_string(), + name: OPERATOR_KEY.to_string(), vendor_version: crate_version!().to_string(), manifest: HashMap::new(), })) diff --git a/rust/listener-operator/src/csi_server/mod.rs b/rust/listener-operator/src/csi_server/mod.rs index f8bf62de..952670ac 100644 --- a/rust/listener-operator/src/csi_server/mod.rs +++ b/rust/listener-operator/src/csi_server/mod.rs @@ -5,17 +5,17 @@ pub mod identity; pub mod node; #[derive(Deserialize)] -enum LbSelector { - #[serde(rename = "lb.stackable.tech/lb-class")] - LbClass(String), - #[serde(rename = "lb.stackable.tech/lb-name")] - Lb(String), +enum ListenerSelector { + #[serde(rename = "listeners.stackable.tech/listener-class")] + ListenerClass(String), + #[serde(rename = "listeners.stackable.tech/listener-name")] + Listener(String), } #[derive(Deserialize)] -struct LbVolumeContext { +struct ListenerVolumeContext { #[serde(flatten)] - lb_selector: LbSelector, + listener_selector: ListenerSelector, } fn tonic_unimplemented() -> Result { diff --git a/rust/listener-operator/src/csi_server/node.rs b/rust/listener-operator/src/csi_server/node.rs index 69df0cbc..55f4a341 100644 --- a/rust/listener-operator/src/csi_server/node.rs +++ b/rust/listener-operator/src/csi_server/node.rs @@ -17,28 +17,28 @@ use stackable_operator::{ use tonic::{Request, Response, Status}; use crate::{ - crd::{LoadBalancer, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec}, + crd::{Listener, ListenerIngress, ListenerPort, ListenerSpec}, grpc::csi::{self, v1::Topology}, utils::{error_full_message, node_primary_address}, }; -use super::{tonic_unimplemented, LbSelector, LbVolumeContext}; +use super::{tonic_unimplemented, ListenerSelector, ListenerVolumeContext}; const FIELD_MANAGER_SCOPE: &str = "volume"; -pub struct LbOperatorNode { +pub struct ListenerOperatorNode { pub client: stackable_operator::client::Client, pub node_name: String, } #[derive(Deserialize)] -struct LbNodeVolumeContext { +struct ListenerNodeVolumeContext { #[serde(rename = "csi.storage.k8s.io/pod.namespace")] pod_namespace: String, #[serde(rename = "csi.storage.k8s.io/pod.name")] pod_name: String, #[serde(flatten)] - common: LbVolumeContext, + common: ListenerVolumeContext, } #[derive(Snafu, Debug)] @@ -54,13 +54,13 @@ enum PublishVolumeError { #[snafu(display("{pod} has not been scheduled to a node yet"))] PodHasNoNode { pod: ObjectRef }, #[snafu(display("failed to build LoadBalancer's owner reference"))] - BuildLbOwnerRef { + BuildListenerOwnerRef { source: stackable_operator::error::Error, }, - #[snafu(display("failed to apply {lb}"))] - ApplyLb { + #[snafu(display("failed to apply {listener}"))] + ApplyListener { source: stackable_operator::error::Error, - lb: ObjectRef, + listener: ObjectRef, }, #[snafu(display("failed to prepare pod dir at {target_path:?}"))] PreparePodDir { @@ -77,8 +77,8 @@ impl From for Status { PublishVolumeError::DecodeVolumeContext { .. } => Status::invalid_argument(full_msg), PublishVolumeError::GetObject { .. } => Status::unavailable(full_msg), PublishVolumeError::PodHasNoNode { .. } => Status::unavailable(full_msg), - PublishVolumeError::BuildLbOwnerRef { .. } => Status::unavailable(full_msg), - PublishVolumeError::ApplyLb { .. } => Status::unavailable(full_msg), + PublishVolumeError::BuildListenerOwnerRef { .. } => Status::unavailable(full_msg), + PublishVolumeError::ApplyListener { .. } => Status::unavailable(full_msg), PublishVolumeError::PreparePodDir { .. } => Status::internal(full_msg), } } @@ -105,7 +105,7 @@ impl From for Status { } #[tonic::async_trait] -impl csi::v1::node_server::Node for LbOperatorNode { +impl csi::v1::node_server::Node for ListenerOperatorNode { async fn node_get_info( &self, _request: Request, @@ -115,7 +115,7 @@ impl csi::v1::node_server::Node for LbOperatorNode { max_volumes_per_node: i64::MAX, accessible_topology: Some(Topology { segments: [( - "lb.stackable.tech/hostname".to_string(), + "listeners.stackable.tech/hostname".to_string(), self.node_name.clone(), )] .into(), @@ -154,22 +154,22 @@ impl csi::v1::node_server::Node for LbOperatorNode { } let request = request.into_inner(); - let LbNodeVolumeContext { + let ListenerNodeVolumeContext { pod_namespace: ns, pod_name, - common: LbVolumeContext { lb_selector }, - } = LbNodeVolumeContext::deserialize(request.volume_context.into_deserializer()) + common: ListenerVolumeContext { listener_selector }, + } = ListenerNodeVolumeContext::deserialize(request.volume_context.into_deserializer()) .context(DecodeVolumeContextSnafu)?; let pv_name = &request.volume_id; let pv = get_obj::(&self.client, pv_name, None).await?; let pod = get_obj::(&self.client, &pod_name, Some(&ns)).await?; - let lb = match lb_selector { - LbSelector::Lb(lb_name) => { - get_obj::(&self.client, &lb_name, Some(&ns)).await? + let listener = match listener_selector { + ListenerSelector::Listener(listener_name) => { + get_obj::(&self.client, &listener_name, Some(&ns)).await? } - LbSelector::LbClass(lb_class_name) => { - let lb = LoadBalancer { + ListenerSelector::ListenerClass(listener_class_name) => { + let listener = Listener { metadata: ObjectMeta { namespace: Some(ns.clone()), name: pv @@ -179,18 +179,18 @@ impl csi::v1::node_server::Node for LbOperatorNode { owner_references: Some(vec![OwnerReferenceBuilder::new() .initialize_from_resource(&pv) .build() - .context(BuildLbOwnerRefSnafu)?]), + .context(BuildListenerOwnerRefSnafu)?]), ..Default::default() }, - spec: LoadBalancerSpec { - class_name: Some(lb_class_name), + spec: ListenerSpec { + class_name: Some(listener_class_name), ports: Some( pod.spec .iter() .flat_map(|ps| &ps.containers) .flat_map(|ctr| &ctr.ports) .flatten() - .map(|port| LoadBalancerPort { + .map(|port| ListenerPort { name: port .name .clone() @@ -205,10 +205,10 @@ impl csi::v1::node_server::Node for LbOperatorNode { status: None, }; self.client - .apply_patch(FIELD_MANAGER_SCOPE, &lb, &lb) + .apply_patch(FIELD_MANAGER_SCOPE, &listener, &listener) .await - .with_context(|_| ApplyLbSnafu { - lb: ObjectRef::from_obj(&lb), + .with_context(|_| ApplyListenerSnafu { + listener: ObjectRef::from_obj(&listener), })? } }; @@ -217,7 +217,7 @@ impl csi::v1::node_server::Node for LbOperatorNode { // connect to the pod in question. // We also can't rely on `ingress_addresses` being set yet, since the pod won't have an IP address yet // (and so can't be found in `Endpoints`) - let lb_addrs = if let Some(node_ports) = lb + let listener_addrs = if let Some(node_ports) = listener .status .as_ref() .and_then(|status| status.node_ports.clone()) @@ -231,22 +231,23 @@ impl csi::v1::node_server::Node for LbOperatorNode { })?; let node = get_obj::(&self.client, node_name, None).await?; node_primary_address(&node) - .map(|address| LoadBalancerIngress { + .map(|address| ListenerIngress { address: address.to_string(), ports: node_ports, }) .into_iter() .collect() } else { - lb.status + listener + .status .as_ref() - .and_then(|lbs| lbs.ingress_addresses.as_ref()) + .and_then(|s| s.ingress_addresses.as_ref()) .cloned() .unwrap_or_default() }; let target_path = PathBuf::from(request.target_path); - pod_dir::write_lb_info_to_pod_dir(&target_path, &lb_addrs) + pod_dir::write_listener_info_to_pod_dir(&target_path, &listener_addrs) .await .context(PreparePodDirSnafu { target_path })?; @@ -301,27 +302,27 @@ impl csi::v1::node_server::Node for LbOperatorNode { mod pod_dir { use std::path::Path; - use crate::crd::LoadBalancerIngress; + use crate::crd::ListenerIngress; use snafu::{OptionExt, ResultExt, Snafu}; #[derive(Snafu, Debug)] pub enum Error { #[snafu(display("failed to write content"), context(false))] WriteContent { source: std::io::Error }, - #[snafu(display("load balancer has no address yet"))] - NoDefaultLb, + #[snafu(display("listener has no address yet"))] + NoDefaultAddress, #[snafu(display("default address folder is outside of the volume root"))] DefaultAddrIsOutsideRoot { source: std::path::StripPrefixError }, } - pub async fn write_lb_info_to_pod_dir( + pub async fn write_listener_info_to_pod_dir( target_path: &Path, - lb_addrs: &[LoadBalancerIngress], + listener_addrs: &[ListenerIngress], ) -> Result<(), Error> { let addrs_path = target_path.join("addresses"); tokio::fs::create_dir_all(&addrs_path).await?; let mut default_addr_dir = None; - for addr in lb_addrs { + for addr in listener_addrs { let addr_dir = addrs_path.join(&addr.address); let ports_dir = addr_dir.join("ports"); tokio::fs::create_dir_all(&ports_dir).await?; @@ -333,7 +334,7 @@ mod pod_dir { } tokio::fs::symlink( default_addr_dir - .context(NoDefaultLbSnafu)? + .context(NoDefaultAddressSnafu)? .strip_prefix(&target_path) .context(DefaultAddrIsOutsideRootSnafu)?, target_path.join("default-address"), diff --git a/rust/listener-operator/src/lb_controller.rs b/rust/listener-operator/src/listener_controller.rs similarity index 78% rename from rust/listener-operator/src/lb_controller.rs rename to rust/listener-operator/src/listener_controller.rs index 7be6c70d..96dc611b 100644 --- a/rust/listener-operator/src/lb_controller.rs +++ b/rust/listener-operator/src/listener_controller.rs @@ -1,7 +1,7 @@ use crate::{ crd::{ - LoadBalancer, LoadBalancerClass, LoadBalancerIngress, LoadBalancerPort, LoadBalancerSpec, - LoadBalancerStatus, ServiceType, + Listener, ListenerClass, ListenerIngress, ListenerPort, ListenerSpec, ListenerStatus, + ServiceType, }, utils::node_primary_address, }; @@ -19,28 +19,29 @@ use stackable_operator::{ use std::{collections::BTreeMap, sync::Arc, time::Duration}; use strum::IntoStaticStr; -const FIELD_MANAGER_SCOPE: &str = "loadbalancer"; +const FIELD_MANAGER_SCOPE: &str = "listener"; pub async fn run(client: stackable_operator::client::Client) { let controller = - controller::Controller::new(client.get_all_api::(), ListParams::default()); - let lb_store = controller.store(); + controller::Controller::new(client.get_all_api::(), ListParams::default()); + let listener_store = controller.store(); controller .owns(client.get_all_api::(), ListParams::default()) .watches( client.get_all_api::(), ListParams::default(), move |endpoints| { - lb_store + listener_store .state() .into_iter() - .filter(move |lb| { - lb.status + .filter(move |listener| { + listener + .status .as_ref() - .and_then(|lbs| lbs.service_name.as_deref()) + .and_then(|s| s.service_name.as_deref()) == endpoints.metadata.name.as_deref() }) - .map(|lb| ObjectRef::from_obj(&*lb)) + .map(|l| ObjectRef::from_obj(&*l)) }, ) .shutdown_on_signal() @@ -52,7 +53,7 @@ pub async fn run(client: stackable_operator::client::Client) { }), ) .map(|res| { - report_controller_reconciled(&client, "loadbalancers.lb.stackable.tech", &res); + report_controller_reconciled(&client, "listener.listeners.stackable.tech", &res); }) .collect::<()>() .await; @@ -107,23 +108,30 @@ impl ReconcilerError for Error { } } -pub async fn reconcile(lb: Arc, ctx: Arc) -> Result { - let ns = lb.metadata.namespace.clone().context(NoNsSnafu)?; - let lb_class_name = lb.spec.class_name.as_deref().context(NoLbClassSnafu)?; - let lb_class = ctx +pub async fn reconcile( + listener: Arc, + ctx: Arc, +) -> Result { + let ns = listener.metadata.namespace.clone().context(NoNsSnafu)?; + let listener_class_name = listener + .spec + .class_name + .as_deref() + .context(NoLbClassSnafu)?; + let listener_class = ctx .client - .get::(lb_class_name, None) + .get::(listener_class_name, None) .await .with_context(|_| GetObjectSnafu { - obj: ObjectRef::::new(lb_class_name).erase(), + obj: ObjectRef::::new(listener_class_name).erase(), })?; - let pod_ports = lb + let pod_ports = listener .spec .ports .iter() .flatten() .map( - |LoadBalancerPort { + |ListenerPort { name, port, protocol, @@ -141,25 +149,25 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result>(); - let svc_name = lb.metadata.name.clone().context(NoNameSnafu)?; + let svc_name = listener.metadata.name.clone().context(NoNameSnafu)?; let svc = Service { metadata: ObjectMeta { namespace: Some(ns.clone()), name: Some(svc_name.clone()), owner_references: Some(vec![OwnerReferenceBuilder::new() - .initialize_from_resource(&*lb) + .initialize_from_resource(&*listener) .build() .context(BuildLbOwnerRefSnafu)?]), ..Default::default() }, spec: Some(ServiceSpec { - type_: Some(match lb_class.spec.service_type { + type_: Some(match listener_class.spec.service_type { ServiceType::NodePort => "NodePort".to_string(), ServiceType::LoadBalancer => "LoadBalancer".to_string(), }), ports: Some(pod_ports.into_values().collect()), external_traffic_policy: Some("Local".to_string()), - selector: lb.spec.pod_selector.clone(), + selector: listener.spec.pod_selector.clone(), publish_not_ready_addresses: Some(true), ..Default::default() }), @@ -175,7 +183,7 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result; let ports: BTreeMap; - match lb_class.spec.service_type { + match listener_class.spec.service_type { ServiceType::NodePort => { let endpoints = ctx .client @@ -235,31 +243,31 @@ pub async fn reconcile(lb: Arc, ctx: Arc) -> Result anyhow::Result<()> { stackable_operator::cli::Command::Crd => { println!( "{}{}", - serde_yaml::to_string(&LoadBalancerClass::crd()).unwrap(), - serde_yaml::to_string(&LoadBalancer::crd()).unwrap() + serde_yaml::to_string(&ListenerClass::crd()).unwrap(), + serde_yaml::to_string(&Listener::crd()).unwrap() ); } stackable_operator::cli::Command::Run(LbOperatorRun { @@ -56,13 +59,12 @@ async fn main() -> anyhow::Result<()> { tracing_target, }) => { stackable_operator::logging::initialize_logging( - "LB_OPERATOR_LOG", - "lb-operator", + "LISTENER_OPERATOR_LOG", + "listener-operator", tracing_target, ); let client = - stackable_operator::client::create_client(Some("lb.stackable.tech".to_string())) - .await?; + stackable_operator::client::create_client(Some(OPERATOR_KEY.to_string())).await?; if csi_endpoint .symlink_metadata() .map_or(false, |meta| meta.file_type().is_socket()) @@ -77,11 +79,11 @@ async fn main() -> anyhow::Result<()> { .register_encoded_file_descriptor_set(grpc::FILE_DESCRIPTOR_SET_BYTES) .build()?, ) - .add_service(IdentityServer::new(LbOperatorIdentity)) - .add_service(ControllerServer::new(LbOperatorController { + .add_service(IdentityServer::new(ListenerOperatorIdentity)) + .add_service(ControllerServer::new(ListenerOperatorController { client: client.clone(), })) - .add_service(NodeServer::new(LbOperatorNode { + .add_service(NodeServer::new(ListenerOperatorNode { client: client.clone(), node_name, })) @@ -90,7 +92,7 @@ async fn main() -> anyhow::Result<()> { .map_ok(TonicUnixStream), sigterm.recv().map(|_| ()), ); - let controller = lb_controller::run(client); + let controller = listener_controller::run(client); pin_mut!(csi_server, controller); futures::future::select(csi_server, controller).await; } diff --git a/tests/templates/kuttl/smoke-nodeport/00-create-lbclass.yaml b/tests/templates/kuttl/smoke-nodeport/00-create-lbclass.yaml deleted file mode 100644 index 5a3e3d8c..00000000 --- a/tests/templates/kuttl/smoke-nodeport/00-create-lbclass.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: lb.stackable.tech/v1alpha1 -kind: LoadBalancerClass -metadata: - name: lb-operator-test-smoke-nodeport -spec: - serviceType: NodePort diff --git a/tests/templates/kuttl/smoke-nodeport/00-create-listenerclass.yaml b/tests/templates/kuttl/smoke-nodeport/00-create-listenerclass.yaml new file mode 100644 index 00000000..d501f211 --- /dev/null +++ b/tests/templates/kuttl/smoke-nodeport/00-create-listenerclass.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: listeners.stackable.tech/v1alpha1 +kind: ListenerClass +metadata: + name: listener-operator-test-smoke-nodeport +spec: + serviceType: NodePort diff --git a/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml b/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml index 3bda7a97..a346fcc2 100644 --- a/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml +++ b/tests/templates/kuttl/smoke-nodeport/01-create-nginx-statefulset.yaml @@ -21,8 +21,8 @@ spec: - name: http containerPort: 80 volumeMounts: - - name: lb - mountPath: /lb + - name: listener + mountPath: /listener - name: metadata mountPath: /usr/share/nginx/html/ volumes: @@ -34,13 +34,13 @@ spec: fieldPath: metadata.name volumeClaimTemplates: - metadata: - name: lb + name: listener annotations: - lb.stackable.tech/lb-class: lb-operator-test-smoke-nodeport + listeners.stackable.tech/listener-class: listener-operator-test-smoke-nodeport spec: accessModes: - ReadWriteMany - storageClassName: lb.stackable.tech + storageClassName: listeners.stackable.tech resources: requests: storage: 1 diff --git a/tests/templates/kuttl/smoke-nodeport/02-assert.yaml b/tests/templates/kuttl/smoke-nodeport/02-assert.yaml index 2be11fe3..2887667c 100644 --- a/tests/templates/kuttl/smoke-nodeport/02-assert.yaml +++ b/tests/templates/kuttl/smoke-nodeport/02-assert.yaml @@ -2,5 +2,5 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert commands: - - script: curl $(kubectl -n $NAMESPACE get loadbalancer/lb-nginx-0 -o jsonpath='http://{.status.ingressAddresses[0].address}:{.status.ingressAddresses[0].ports.http}/pod-name') | grep nginx-0 - - script: curl $(kubectl -n $NAMESPACE get loadbalancer/lb-nginx-1 -o jsonpath='http://{.status.ingressAddresses[0].address}:{.status.ingressAddresses[0].ports.http}/pod-name') | grep nginx-1 + - script: curl $(kubectl -n $NAMESPACE get listener/listener-nginx-0 -o jsonpath='http://{.status.ingressAddresses[0].address}:{.status.ingressAddresses[0].ports.http}/pod-name') | grep nginx-0 + - script: curl $(kubectl -n $NAMESPACE get listener/listener-nginx-1 -o jsonpath='http://{.status.ingressAddresses[0].address}:{.status.ingressAddresses[0].ports.http}/pod-name') | grep nginx-1 From 5cef2b35e26df479cbf15b3d9ea24716d30424eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 15:55:57 +0200 Subject: [PATCH 46/99] Emphasize using our storage class rather than the direct driver --- docs/modules/ROOT/pages/usage.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/usage.adoc b/docs/modules/ROOT/pages/usage.adoc index f9ac6cbe..d9dd623c 100644 --- a/docs/modules/ROOT/pages/usage.adoc +++ b/docs/modules/ROOT/pages/usage.adoc @@ -1,6 +1,6 @@ = Usage -The operator creates a xref:listener.adoc[] for each mounted CSI volume with `driver: listeners.stackable.tech`. +The operator creates a xref:listener.adoc[] for each mounted CSI volume with `storageClassName: listeners.stackable.tech`. A minimal exposed `Pod` looks like this: From 4aca95a2f8f182c32800c29b5ee1f84d815a7c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 16:06:05 +0200 Subject: [PATCH 47/99] Print startup message --- Cargo.lock | 159 ++++++++++++++++++++++++++++- rust/listener-operator/Cargo.toml | 1 + rust/listener-operator/build.rs | 8 ++ rust/listener-operator/src/main.rs | 15 ++- 4 files changed, 180 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10734035..2fd6c65e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,6 +167,17 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "built" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f346b6890a0dfa7266974910e7df2d5088120dd54721b9b0e5aae1ae5e05715" +dependencies = [ + "cargo-lock", + "chrono", + "git2", +] + [[package]] name = "bumpalo" version = "3.10.0" @@ -185,11 +196,26 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +[[package]] +name = "cargo-lock" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c408da54db4c50d4693f7e649c299bc9de9c23ead86249e5368830bb32a734b" +dependencies = [ + "semver", + "serde", + "toml", + "url", +] + [[package]] name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -207,6 +233,7 @@ dependencies = [ "num-integer", "num-traits", "serde", + "time", "winapi", ] @@ -616,7 +643,20 @@ checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "git2" +version = "0.13.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "url", ] [[package]] @@ -771,6 +811,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "1.9.1" @@ -828,6 +879,15 @@ dependencies = [ "regex", ] +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.59" @@ -991,6 +1051,30 @@ version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +[[package]] +name = "libgit2-sys" +version = "0.12.26+1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + +[[package]] +name = "libz-sys" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1066,7 +1150,7 @@ checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] @@ -1633,6 +1717,9 @@ name = "semver" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +dependencies = [ + "serde", +] [[package]] name = "serde" @@ -1769,6 +1856,7 @@ name = "stackable-listener-operator" version = "0.1.0-nightly" dependencies = [ "anyhow", + "built", "clap", "futures", "h2", @@ -1960,6 +2048,32 @@ dependencies = [ "threadpool", ] +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + [[package]] name = "tokio" version = "1.20.1" @@ -2064,6 +2178,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + [[package]] name = "tonic" version = "0.7.2" @@ -2279,18 +2402,44 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + [[package]] name = "unicode-ident" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +[[package]] +name = "unicode-normalization" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-xid" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +[[package]] +name = "url" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22fe195a4f217c25b25cb5058ced57059824a678474874038dc88d211bf508d3" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "valuable" version = "0.1.0" @@ -2319,6 +2468,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/rust/listener-operator/Cargo.toml b/rust/listener-operator/Cargo.toml index 5f7ee0fc..6bfce36c 100644 --- a/rust/listener-operator/Cargo.toml +++ b/rust/listener-operator/Cargo.toml @@ -31,4 +31,5 @@ snafu = "0.7.1" strum = "0.24.1" [build-dependencies] +built = { version = "0.5.1", features = ["chrono", "git2"] } tonic-build = "0.7.2" diff --git a/rust/listener-operator/build.rs b/rust/listener-operator/build.rs index 155e936c..5c3870d1 100644 --- a/rust/listener-operator/build.rs +++ b/rust/listener-operator/build.rs @@ -8,4 +8,12 @@ fn main() { .file_descriptor_set_path(out_dir.join("file_descriptor_set.bin")) .compile(&["csi.proto"], &["vendor/csi"]) .unwrap(); + built::write_built_file_with_opts( + // built's env module depends on a whole bunch of variables that crate2nix doesn't provide + // so we grab the specific env variables that we care about out ourselves instead. + built::Options::default().set_env(false), + "Cargo.toml".as_ref(), + &out_dir.join("built.rs"), + ) + .unwrap(); } diff --git a/rust/listener-operator/src/main.rs b/rust/listener-operator/src/main.rs index b4a54d61..af58adb0 100644 --- a/rust/listener-operator/src/main.rs +++ b/rust/listener-operator/src/main.rs @@ -1,6 +1,6 @@ use std::{os::unix::prelude::FileTypeExt, path::PathBuf}; -use clap::Parser; +use clap::{crate_description, crate_version, Parser}; use csi_server::{ controller::ListenerOperatorController, identity::ListenerOperatorIdentity, node::ListenerOperatorNode, @@ -42,6 +42,11 @@ struct LbOperatorRun { tracing_target: TracingTarget, } +mod built_info { + include!(concat!(env!("OUT_DIR"), "/built.rs")); + pub const TARGET: Option<&str> = option_env!("TARGET"); +} + #[tokio::main] async fn main() -> anyhow::Result<()> { let opts = Opts::parse(); @@ -63,6 +68,14 @@ async fn main() -> anyhow::Result<()> { "listener-operator", tracing_target, ); + stackable_operator::utils::print_startup_string( + crate_description!(), + crate_version!(), + built_info::GIT_VERSION, + built_info::TARGET.unwrap_or("unknown target"), + built_info::BUILT_TIME_UTC, + built_info::RUSTC_VERSION, + ); let client = stackable_operator::client::create_client(Some(OPERATOR_KEY.to_string())).await?; if csi_endpoint From 7bfac371a46910a96d1c2ffe29700f06c7872ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 16:13:37 +0200 Subject: [PATCH 48/99] More rebranding --- deploy/helm/listener-operator/crds/crds.yaml | 18 +++++++------- deploy/manifests/crds.yaml | 18 +++++++------- rust/listener-operator/src/crd.rs | 24 +++++++++---------- rust/listener-operator/src/csi_server/node.rs | 2 +- .../src/listener_controller.rs | 18 +++++++------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/deploy/helm/listener-operator/crds/crds.yaml b/deploy/helm/listener-operator/crds/crds.yaml index 5f98fbc7..9b6ba10d 100644 --- a/deploy/helm/listener-operator/crds/crds.yaml +++ b/deploy/helm/listener-operator/crds/crds.yaml @@ -22,7 +22,7 @@ spec: description: "Auto-generated derived type for ListenerClassSpec via `CustomResource`" properties: spec: - description: "Defines a policy for how [`LoadBalancer`]s should be exposed." + description: "Defines a policy for how [`Listener`]s should be exposed." properties: serviceAnnotations: additionalProperties: @@ -70,10 +70,10 @@ spec: description: "Auto-generated derived type for ListenerSpec via `CustomResource`" properties: spec: - description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" + description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" properties: className: - description: "The name of the [`LoadBalancerClass`]." + description: "The name of the [`ListenerClass`]." nullable: true type: string podSelector: @@ -87,7 +87,7 @@ spec: items: properties: name: - description: "The name of the port.\n\nThe name of each port *must* be unique within a single [`LoadBalancer`]." + description: "The name of the port.\n\nThe name of each port *must* be unique within a single [`Listener`]." type: string port: description: The port number. @@ -105,16 +105,16 @@ spec: type: array type: object status: - description: "Informs users about how to reach the [`LoadBalancer`]." + description: "Informs users about how to reach the [`Listener`]." nullable: true properties: ingressAddresses: - description: "All addresses that the [`LoadBalancer`] is currently reachable from." + description: "All addresses that the [`Listener`] is currently reachable from." items: - description: "One address that a [`LoadBalancer`] is accessible from." + description: "One address that a [`Listener`] is accessible from." properties: address: - description: "The hostname or IP address to the [`LoadBalancer`]." + description: "The hostname or IP address to the [`Listener`]." type: string ports: additionalProperties: @@ -132,7 +132,7 @@ spec: additionalProperties: format: int32 type: integer - description: "Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by listener-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does not require [`Node`]-local access." + description: "Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does not require [`Node`]-local access." nullable: true type: object serviceName: diff --git a/deploy/manifests/crds.yaml b/deploy/manifests/crds.yaml index 6c4d1471..57b2b1c0 100644 --- a/deploy/manifests/crds.yaml +++ b/deploy/manifests/crds.yaml @@ -23,7 +23,7 @@ spec: description: "Auto-generated derived type for ListenerClassSpec via `CustomResource`" properties: spec: - description: "Defines a policy for how [`LoadBalancer`]s should be exposed." + description: "Defines a policy for how [`Listener`]s should be exposed." properties: serviceAnnotations: additionalProperties: @@ -71,10 +71,10 @@ spec: description: "Auto-generated derived type for ListenerSpec via `CustomResource`" properties: spec: - description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" + description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" properties: className: - description: "The name of the [`LoadBalancerClass`]." + description: "The name of the [`ListenerClass`]." nullable: true type: string podSelector: @@ -88,7 +88,7 @@ spec: items: properties: name: - description: "The name of the port.\n\nThe name of each port *must* be unique within a single [`LoadBalancer`]." + description: "The name of the port.\n\nThe name of each port *must* be unique within a single [`Listener`]." type: string port: description: The port number. @@ -106,16 +106,16 @@ spec: type: array type: object status: - description: "Informs users about how to reach the [`LoadBalancer`]." + description: "Informs users about how to reach the [`Listener`]." nullable: true properties: ingressAddresses: - description: "All addresses that the [`LoadBalancer`] is currently reachable from." + description: "All addresses that the [`Listener`] is currently reachable from." items: - description: "One address that a [`LoadBalancer`] is accessible from." + description: "One address that a [`Listener`] is accessible from." properties: address: - description: "The hostname or IP address to the [`LoadBalancer`]." + description: "The hostname or IP address to the [`Listener`]." type: string ports: additionalProperties: @@ -133,7 +133,7 @@ spec: additionalProperties: format: int32 type: integer - description: "Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by listener-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does not require [`Node`]-local access." + description: "Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does not require [`Node`]-local access." nullable: true type: object serviceName: diff --git a/rust/listener-operator/src/crd.rs b/rust/listener-operator/src/crd.rs index 8e141fc7..e8e8b970 100644 --- a/rust/listener-operator/src/crd.rs +++ b/rust/listener-operator/src/crd.rs @@ -4,10 +4,10 @@ use serde::{Deserialize, Serialize}; use stackable_operator::kube::CustomResource; use stackable_operator::schemars::{self, JsonSchema}; -#[cfg(rustdoc)] +#[cfg(doc)] use stackable_operator::k8s_openapi::api::core::v1::{Node, Pod, Service}; -/// Defines a policy for how [`LoadBalancer`]s should be exposed. +/// Defines a policy for how [`Listener`]s should be exposed. #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)] #[kube( group = "listeners.stackable.tech", @@ -38,8 +38,8 @@ pub enum ServiceType { /// Exposes a set of pods to the outside world. /// -/// Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`LoadBalancer`] changes two things: -/// 1. It uses a cluster-level policy object ([`LoadBalancerClass`]) to define how exactly the exposure works +/// Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: +/// 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works /// 2. It has a consistent API for reading back the exposed address(es) of the service #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default)] #[kube( @@ -56,7 +56,7 @@ pub enum ServiceType { )] #[serde(rename_all = "camelCase")] pub struct ListenerSpec { - /// The name of the [`LoadBalancerClass`]. + /// The name of the [`ListenerClass`]. pub class_name: Option, /// Labels that the [`Pod`]s must share in order to be exposed. pub pod_selector: Option>, @@ -69,7 +69,7 @@ pub struct ListenerSpec { pub struct ListenerPort { /// The name of the port. /// - /// The name of each port *must* be unique within a single [`LoadBalancer`]. + /// The name of each port *must* be unique within a single [`Listener`]. pub name: String, /// The port number. pub port: i32, @@ -77,26 +77,26 @@ pub struct ListenerPort { pub protocol: Option, } -/// Informs users about how to reach the [`LoadBalancer`]. +/// Informs users about how to reach the [`Listener`]. #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct ListenerStatus { /// The backing Kubernetes [`Service`]. pub service_name: Option, - /// All addresses that the [`LoadBalancer`] is currently reachable from. + /// All addresses that the [`Listener`] is currently reachable from. pub ingress_addresses: Option>, - /// Port mappings for accessing the [`LoadBalancer`] on each [`Node`] that the [`Pod`]s are currently running on. + /// Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on. /// - /// This is only intended for internal use by listener-operator itself. This will be left unset if using a [`LoadBalancerClass`] that does + /// This is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does /// not require [`Node`]-local access. pub node_ports: Option>, } -/// One address that a [`LoadBalancer`] is accessible from. +/// One address that a [`Listener`] is accessible from. #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct ListenerIngress { - /// The hostname or IP address to the [`LoadBalancer`]. + /// The hostname or IP address to the [`Listener`]. pub address: String, /// Port mapping table. pub ports: BTreeMap, diff --git a/rust/listener-operator/src/csi_server/node.rs b/rust/listener-operator/src/csi_server/node.rs index 55f4a341..172afefe 100644 --- a/rust/listener-operator/src/csi_server/node.rs +++ b/rust/listener-operator/src/csi_server/node.rs @@ -53,7 +53,7 @@ enum PublishVolumeError { }, #[snafu(display("{pod} has not been scheduled to a node yet"))] PodHasNoNode { pod: ObjectRef }, - #[snafu(display("failed to build LoadBalancer's owner reference"))] + #[snafu(display("failed to build Listener's owner reference"))] BuildListenerOwnerRef { source: stackable_operator::error::Error, }, diff --git a/rust/listener-operator/src/listener_controller.rs b/rust/listener-operator/src/listener_controller.rs index 96dc611b..ddae09a6 100644 --- a/rust/listener-operator/src/listener_controller.rs +++ b/rust/listener-operator/src/listener_controller.rs @@ -69,15 +69,15 @@ pub enum Error { NoNs, #[snafu(display("object has no name"))] NoName, - #[snafu(display("object has no LoadBalancerClass (.spec.class_name)"))] - NoLbClass, + #[snafu(display("object has no ListenerClass (.spec.class_name)"))] + NoListenerClass, #[snafu(display("failed to get {obj}"))] GetObject { source: stackable_operator::error::Error, obj: ObjectRef, }, - #[snafu(display("failed to build owner reference to LoadBalancer"))] - BuildLbOwnerRef { + #[snafu(display("failed to build owner reference to Listener"))] + BuildListenerOwnerRef { source: stackable_operator::error::Error, }, #[snafu(display("failed to apply {svc}"))] @@ -85,7 +85,7 @@ pub enum Error { source: stackable_operator::error::Error, svc: ObjectRef, }, - #[snafu(display("failed to apply status for LoadBalancer"))] + #[snafu(display("failed to apply status for Listener"))] ApplyStatus { source: stackable_operator::error::Error, }, @@ -99,9 +99,9 @@ impl ReconcilerError for Error { match self { Self::NoNs => None, Self::NoName => None, - Self::NoLbClass => None, + Self::NoListenerClass => None, Self::GetObject { source: _, obj } => Some(obj.clone()), - Self::BuildLbOwnerRef { .. } => None, + Self::BuildListenerOwnerRef { .. } => None, Self::ApplyService { source: _, svc } => Some(svc.clone().erase()), Self::ApplyStatus { source: _ } => None, } @@ -117,7 +117,7 @@ pub async fn reconcile( .spec .class_name .as_deref() - .context(NoLbClassSnafu)?; + .context(NoListenerClassSnafu)?; let listener_class = ctx .client .get::(listener_class_name, None) @@ -157,7 +157,7 @@ pub async fn reconcile( owner_references: Some(vec![OwnerReferenceBuilder::new() .initialize_from_resource(&*listener) .build() - .context(BuildLbOwnerRefSnafu)?]), + .context(BuildListenerOwnerRefSnafu)?]), ..Default::default() }, spec: Some(ServiceSpec { From 19871510ce5f77e3281801b5390faff9cf3b1172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 8 Sep 2022 16:17:09 +0200 Subject: [PATCH 49/99] Rename crate directory for consistency --- .gitmodules | 2 +- Cargo.toml | 2 +- rust/{listener-operator => operator-binary}/Cargo.toml | 0 rust/{listener-operator => operator-binary}/build.rs | 0 rust/{listener-operator => operator-binary}/src/crd.rs | 0 .../src/csi_server/controller.rs | 0 .../src/csi_server/identity.rs | 0 .../src/csi_server/mod.rs | 0 .../src/csi_server/node.rs | 0 rust/{listener-operator => operator-binary}/src/grpc.rs | 0 rust/{listener-operator => operator-binary}/src/lib.rs | 0 .../src/listener_controller.rs | 0 rust/{listener-operator => operator-binary}/src/main.rs | 0 rust/{listener-operator => operator-binary}/src/utils.rs | 0 rust/{listener-operator => operator-binary}/vendor/csi | 0 15 files changed, 2 insertions(+), 2 deletions(-) rename rust/{listener-operator => operator-binary}/Cargo.toml (100%) rename rust/{listener-operator => operator-binary}/build.rs (100%) rename rust/{listener-operator => operator-binary}/src/crd.rs (100%) rename rust/{listener-operator => operator-binary}/src/csi_server/controller.rs (100%) rename rust/{listener-operator => operator-binary}/src/csi_server/identity.rs (100%) rename rust/{listener-operator => operator-binary}/src/csi_server/mod.rs (100%) rename rust/{listener-operator => operator-binary}/src/csi_server/node.rs (100%) rename rust/{listener-operator => operator-binary}/src/grpc.rs (100%) rename rust/{listener-operator => operator-binary}/src/lib.rs (100%) rename rust/{listener-operator => operator-binary}/src/listener_controller.rs (100%) rename rust/{listener-operator => operator-binary}/src/main.rs (100%) rename rust/{listener-operator => operator-binary}/src/utils.rs (100%) rename rust/{listener-operator => operator-binary}/vendor/csi (100%) diff --git a/.gitmodules b/.gitmodules index 793e4fd1..a2274990 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "rust/lb-operator/vendor/csi"] - path = rust/listener-operator/vendor/csi + path = rust/operator-binary/vendor/csi url = https://github.com/container-storage-interface/spec diff --git a/Cargo.toml b/Cargo.toml index 5b4466fe..302ec2d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["rust/listener-operator"] +members = ["rust/operator-binary"] [patch.crates-io] # Workaround for https://github.com/hyperium/tonic/issues/243 diff --git a/rust/listener-operator/Cargo.toml b/rust/operator-binary/Cargo.toml similarity index 100% rename from rust/listener-operator/Cargo.toml rename to rust/operator-binary/Cargo.toml diff --git a/rust/listener-operator/build.rs b/rust/operator-binary/build.rs similarity index 100% rename from rust/listener-operator/build.rs rename to rust/operator-binary/build.rs diff --git a/rust/listener-operator/src/crd.rs b/rust/operator-binary/src/crd.rs similarity index 100% rename from rust/listener-operator/src/crd.rs rename to rust/operator-binary/src/crd.rs diff --git a/rust/listener-operator/src/csi_server/controller.rs b/rust/operator-binary/src/csi_server/controller.rs similarity index 100% rename from rust/listener-operator/src/csi_server/controller.rs rename to rust/operator-binary/src/csi_server/controller.rs diff --git a/rust/listener-operator/src/csi_server/identity.rs b/rust/operator-binary/src/csi_server/identity.rs similarity index 100% rename from rust/listener-operator/src/csi_server/identity.rs rename to rust/operator-binary/src/csi_server/identity.rs diff --git a/rust/listener-operator/src/csi_server/mod.rs b/rust/operator-binary/src/csi_server/mod.rs similarity index 100% rename from rust/listener-operator/src/csi_server/mod.rs rename to rust/operator-binary/src/csi_server/mod.rs diff --git a/rust/listener-operator/src/csi_server/node.rs b/rust/operator-binary/src/csi_server/node.rs similarity index 100% rename from rust/listener-operator/src/csi_server/node.rs rename to rust/operator-binary/src/csi_server/node.rs diff --git a/rust/listener-operator/src/grpc.rs b/rust/operator-binary/src/grpc.rs similarity index 100% rename from rust/listener-operator/src/grpc.rs rename to rust/operator-binary/src/grpc.rs diff --git a/rust/listener-operator/src/lib.rs b/rust/operator-binary/src/lib.rs similarity index 100% rename from rust/listener-operator/src/lib.rs rename to rust/operator-binary/src/lib.rs diff --git a/rust/listener-operator/src/listener_controller.rs b/rust/operator-binary/src/listener_controller.rs similarity index 100% rename from rust/listener-operator/src/listener_controller.rs rename to rust/operator-binary/src/listener_controller.rs diff --git a/rust/listener-operator/src/main.rs b/rust/operator-binary/src/main.rs similarity index 100% rename from rust/listener-operator/src/main.rs rename to rust/operator-binary/src/main.rs diff --git a/rust/listener-operator/src/utils.rs b/rust/operator-binary/src/utils.rs similarity index 100% rename from rust/listener-operator/src/utils.rs rename to rust/operator-binary/src/utils.rs diff --git a/rust/listener-operator/vendor/csi b/rust/operator-binary/vendor/csi similarity index 100% rename from rust/listener-operator/vendor/csi rename to rust/operator-binary/vendor/csi From a60a12e428634e02638b251c129baec3dac7ef83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 10:31:49 +0200 Subject: [PATCH 50/99] Update docs/modules/ROOT/pages/building.adoc Co-authored-by: Malte Sander --- docs/modules/ROOT/pages/building.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index 2c7e372e..813cd096 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -4,8 +4,8 @@ This operator is written in Rust. It is developed against the latest stable Rust release, and we currently don't support any older versions. -The LB Operator is a https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface (CSI)] provider plugin -for the local Kubelet, which means that it should only be executed inside a Kubernetes `Pod`. Currently, the following ways are supported to build the LB Operator: +The Listener Operator is a https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface (CSI)] provider plugin +for the local Kubelet, which means that it should only be executed inside a Kubernetes `Pod`. Currently, the following ways are supported to build the Listener Operator: * `docker build` * https://nixos.org/[Nix] From c9c8ef3bd99461a4d6ac4f1efcd7149597e40160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 10:31:58 +0200 Subject: [PATCH 51/99] Update docs/modules/ROOT/pages/building.adoc Co-authored-by: Malte Sander --- docs/modules/ROOT/pages/building.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index 813cd096..2dcd17e9 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -72,7 +72,7 @@ $ nix run -f . tilt up == K3d -The LB Operator, as with most CSI providers, requires the Kubernetes node's root folder to be mounted as `rshared`. K3d does not do this by default, +The Listener Operator, as with most CSI providers, requires the Kubernetes node's root folder to be mounted as `rshared`. K3d does not do this by default, but can be prodded into doing this by running `mount --make-rshared /` in each node container. To do this for each running K3d node, run the following script: From b4131f460e868290ade417c73cce0a140590f1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 10:37:20 +0200 Subject: [PATCH 52/99] More rebranding bits and pieces --- docs/modules/ROOT/pages/listener.adoc | 6 +++--- rust/operator-binary/src/main.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/modules/ROOT/pages/listener.adoc b/docs/modules/ROOT/pages/listener.adoc index 00576913..f1bae800 100644 --- a/docs/modules/ROOT/pages/listener.adoc +++ b/docs/modules/ROOT/pages/listener.adoc @@ -17,11 +17,11 @@ A `Listener` writes back all addresses that it can be reached on to `Listener.st For example, if the volume is mounted to `/stackable/listener`, the primary address can be read from `/stackable/listener/default-address/address`, and the public `http` port number can be read from `/stackable/listener/default-address/ports/http`. -== Per-replica LBs +== Per-replica listeners A `Listener` PVC can also specify a xref:listenerclass.adoc[] rather than a `Listener`, in which case a `Listener` object is created -automatically. These PVCs can automatically be created for each replica using either `StatefulSet` 's `volumeClaimTemplates` (for long-lived LBs that will -be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` (for temporary LBs that are deleted when their corresponding `Pod` is deleted). +automatically. These PVCs can automatically be created for each replica using either `StatefulSet` 's `volumeClaimTemplates` (for long-lived listeners that will +be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` (for temporary listeners that are deleted when their corresponding `Pod` is deleted). == Sticky scheduling diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index af58adb0..a525fa20 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -29,11 +29,11 @@ const OPERATOR_KEY: &str = "listeners.stackable.tech"; #[clap(author, version)] struct Opts { #[clap(subcommand)] - cmd: stackable_operator::cli::Command, + cmd: stackable_operator::cli::Command, } #[derive(clap::Parser)] -struct LbOperatorRun { +struct ListenerOperatorRun { #[clap(long, env)] csi_endpoint: PathBuf, #[clap(long, env)] @@ -58,7 +58,7 @@ async fn main() -> anyhow::Result<()> { serde_yaml::to_string(&Listener::crd()).unwrap() ); } - stackable_operator::cli::Command::Run(LbOperatorRun { + stackable_operator::cli::Command::Run(ListenerOperatorRun { csi_endpoint, node_name, tracing_target, From d2b148c7264d6525a37eaa8ef3babe7025c40a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 10:39:22 +0200 Subject: [PATCH 53/99] Document `--node-name` --- docs/modules/ROOT/pages/commandline_args.adoc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/modules/ROOT/pages/commandline_args.adoc b/docs/modules/ROOT/pages/commandline_args.adoc index e8828831..64917581 100644 --- a/docs/modules/ROOT/pages/commandline_args.adoc +++ b/docs/modules/ROOT/pages/commandline_args.adoc @@ -9,3 +9,12 @@ The path to the https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface] Unix Domain Socket that the operator should listen on. +=== --node-name + +*Required*: true + +*Multiple values*: false + +*Environment variable*: `NODE_NAME` + +The name of the Kubernetes `Node` that this `Pod` is running on. From 1e0db1a5113239ff9cfd5049f2a0c7fc14d3c07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 10:47:16 +0200 Subject: [PATCH 54/99] Fix duplicate link to listener.adoc in nav --- docs/modules/ROOT/nav.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 964b201e..c51c0241 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -4,6 +4,6 @@ * xref:usage.adoc[] * Concepts ** xref:listener.adoc[] -** xref:listener.adoc[] +** xref:listenerclass.adoc[] ** xref:volume.adoc[] From 654e79a610d42394eccb061082f3c950c78beb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 12:44:19 +0200 Subject: [PATCH 55/99] Fix the Nix build instructions --- default.nix | 8 ++++++++ docs/modules/ROOT/pages/building.adoc | 22 ++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/default.nix b/default.nix index b67a88e4..dd0f58e1 100644 --- a/default.nix +++ b/default.nix @@ -39,6 +39,14 @@ rec { name = "ref"; path = pkgs.writeText "${dockerImage.name}-image-tag" "${dockerImage.imageName}:${dockerImage.imageTag}"; } + { + name = "image-repo"; + path = pkgs.writeText "${dockerImage.name}-name" dockerImage.imageName; + } + { + name = "image-tag"; + path = pkgs.writeText "${dockerImage.name}-name" dockerImage.imageTag; + } { name = "crds.yaml"; path = crds; diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index 2dcd17e9..dd8cd506 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -39,31 +39,33 @@ $ helm upgrade listener-operator deploy/helm/listener-operator \ == Nix -To build and deploy to the active Kind cluster, run: +To build and deploy to the active Kind cluster, run the following bash script: [source,console] ---- $ echo Building with Nix # Ensure that all submodules are up-to-date $ git submodule update --recursive --init -# Ensure that the Cargo.lock is up-to-date -# This is not required if you use a tool that invokes Cargo regularly anyway, such as Rust-Analyzer -$ cargo generate-lockfile # Use crate2nix (https://github.com/kolloch/crate2nix) to convert Cargo.lock into a Nix derivation -$ nix run -f . crate2nix generate +$ nix run -f . crate2nix generate # Build the Docker images +# A custom Docker repository can be specified by appending `--argstr dockerName my-custom-repository` $ nix build -f . docker # Load the images onto the Kind nodes -# Nix does not use the Docker daemon, instead it builds individual layers, as well as a script (`result/load-image`) that combines them into a Docker image archive -$ kind load image-archive <(./result/load-image) +# Nix does not use the Docker daemon, instead it builds individual layers, as well as +# a script (`result/load-image`) that combines them into a Docker image archive. +# `load-image` can also be piped into `docker load` to prepare for pushing to a registry. +$ ./result/load-image | kind load image-archive /dev/stdin # Deploy -$ kubectl apply -f result/crds.yaml -f provisioner.yaml -$ kubectl rollout restart ds/listener-provisioner +$ kubectl apply -f result/crds.yaml +$ helm upgrade listener-operator deploy/helm/listener-operator \ + --install \ + --set-string "image.repository=$(cat result/image-repo),image.tag=$(cat result/image-tag)" ---- You may need to add `extra-experimental-features = nix-command` to `/etc/nix/nix.conf`, or add `--experimental-features nix-command` to the Nix commands. -You can also use https://tilt.dev/[Tilt] to automatically recompile and redeploy when files are changed: +You can also use https://tilt.dev/[Tilt] to automatically rebuild and redeploy when files are changed: [source,console] ---- From a6e928633025421417fb596778952fcd093d4351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 13:35:37 +0200 Subject: [PATCH 56/99] Added a note about buffering the image --- docs/modules/ROOT/pages/building.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index dd8cd506..ffd03f9f 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -55,6 +55,8 @@ $ nix build -f . docker # Nix does not use the Docker daemon, instead it builds individual layers, as well as # a script (`result/load-image`) that combines them into a Docker image archive. # `load-image` can also be piped into `docker load` to prepare for pushing to a registry. +# Some people have reported issues with piping, for those it may be helpful to buffer the image through a file +# by running `./result/load-image > image.tar && kind load image-archive image.tar`. $ ./result/load-image | kind load image-archive /dev/stdin # Deploy $ kubectl apply -f result/crds.yaml From 73af0e3c130bb586a1fab32dd8e796c53b48045e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 17:06:38 +0200 Subject: [PATCH 57/99] Rename submodule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index a2274990..aabdd5b8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "rust/lb-operator/vendor/csi"] +[submodule "rust/operator-binary/vendor/csi"] path = rust/operator-binary/vendor/csi url = https://github.com/container-storage-interface/spec From e4ee4b06f1189cda03090ed74132bf26baa00ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 9 Sep 2022 17:07:20 +0200 Subject: [PATCH 58/99] Update docs/modules/ROOT/pages/volume.adoc Co-authored-by: Malte Sander --- docs/modules/ROOT/pages/volume.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index ad3aa4a1..4e946f63 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -2,7 +2,7 @@ TODO: Expand severely. -The LB Operator acts as a CSI `PersistentVolume`, which helps it to stabilize network addresses, inject pod metadata and expose individual pods. +The Listener Operator acts as a CSI `PersistentVolume`, which helps it to stabilize network addresses, inject pod metadata and expose individual pods. == Stable addresses From 1b0e70b382e2d7ec0653e82f7ee7cb1df65b4d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 12 Sep 2022 11:44:37 +0200 Subject: [PATCH 59/99] Added note about needing to buffer with more than one kind node --- .gitignore | 1 + docs/modules/ROOT/pages/building.adoc | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 65ef2553..e89cb372 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ target/ Cargo.nix crate-hashes.json result +image.tar \ No newline at end of file diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index ffd03f9f..315aac6a 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -55,9 +55,9 @@ $ nix build -f . docker # Nix does not use the Docker daemon, instead it builds individual layers, as well as # a script (`result/load-image`) that combines them into a Docker image archive. # `load-image` can also be piped into `docker load` to prepare for pushing to a registry. -# Some people have reported issues with piping, for those it may be helpful to buffer the image through a file -# by running `./result/load-image > image.tar && kind load image-archive image.tar`. -$ ./result/load-image | kind load image-archive /dev/stdin +$ ./result/load-image > image.tar && kind load image-archive image.tar +# On single-node kind clusters it is slightly more efficient to run +# `./result/load-image | kind load image-archive /dev/stdin` instead. # Deploy $ kubectl apply -f result/crds.yaml $ helm upgrade listener-operator deploy/helm/listener-operator \ From 8d1b259da1cbc4d3a8be70334fc7b1aa318d5911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 12 Sep 2022 11:52:54 +0200 Subject: [PATCH 60/99] Also ignore image.tar from docker builds --- .dockerignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.dockerignore b/.dockerignore index 38ad1963..5d0eb2f1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,5 +5,7 @@ target/ .idea/ *.iws +image.tar + # We do NOT want to ignore .git because we use the `built` crate to gather the current git commit hash at built time # This means we need the .git directory in our Docker image, it will be thrown away and won't be included in the final image From 495f736ee479a44eb84dd8072f60ead09d705dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 12 Sep 2022 12:11:26 +0200 Subject: [PATCH 61/99] Docker workflow: Use the Docker image to also build the CRD --- docs/modules/ROOT/pages/building.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index 315aac6a..92ca7133 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -22,8 +22,6 @@ To build and deploy to the active Kind cluster, run: $ echo Building with Docker # Ensure that all submodules are up-to-date $ git submodule update --recursive --init -# Update the Chart metadata and CRD definitions -$ make compile-chart # Create a unique image ID $ REPO=listener-operator $ TAG="$(uuidgen)" @@ -31,6 +29,8 @@ $ TAG="$(uuidgen)" $ docker build . -f docker/Dockerfile -t "$REPO:$TAG" # Load the image onto the Kind nodes $ kind load docker-image "$REPO:$TAG" +# Deploy latest CRD +$ docker run --rm "$REPO:$TAG" crd | kubectl apply -f- # Deploy $ helm upgrade listener-operator deploy/helm/listener-operator \ --install \ From b33e2f826f629f6565107f4f123f7ec9cafbfddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 12 Sep 2022 12:14:17 +0200 Subject: [PATCH 62/99] Apply suggestions from code review Co-authored-by: Felix Hennig --- docs/modules/ROOT/pages/volume.adoc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index 4e946f63..c02f5a2f 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -1,6 +1,5 @@ = Volume -TODO: Expand severely. The Listener Operator acts as a CSI `PersistentVolume`, which helps it to stabilize network addresses, inject pod metadata and expose individual pods. @@ -20,12 +19,12 @@ this information: [source] ---- -- `default-address/`- A symlink to `addresses/\{primary address\}` +- `default-address/`- A symlink to `addresses/{primary address}` - `addresses/` - Contains information about all addresses associated with this xref:listener.adoc[] - - `\{address\}/` - A folder is created for each address + - `{address}/` - A folder is created for each address - `address` - Contains the Pod's address (IP address or hostname) - `ports/` - Contains port numbers for each named port - - `\{port name\}` - Contains the public port number for this named port + - `{port name}` - Contains the public port number for this named port ---- == Individual pod exposure From 1b2509253db549b39e7406ce8945188923b0f301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 12 Sep 2022 16:17:09 +0200 Subject: [PATCH 63/99] Fix repo/tag derivation names to line up with the file names --- default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index dd0f58e1..9c339d21 100644 --- a/default.nix +++ b/default.nix @@ -41,11 +41,11 @@ rec { } { name = "image-repo"; - path = pkgs.writeText "${dockerImage.name}-name" dockerImage.imageName; + path = pkgs.writeText "${dockerImage.name}-repo" dockerImage.imageName; } { name = "image-tag"; - path = pkgs.writeText "${dockerImage.name}-name" dockerImage.imageTag; + path = pkgs.writeText "${dockerImage.name}-tag" dockerImage.imageTag; } { name = "crds.yaml"; From 2be895a4f820095fa869bf86647465dd4bfcd4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 12 Sep 2022 16:19:15 +0200 Subject: [PATCH 64/99] Update build docs slightly based on feedback from @siegfriedweber --- docs/modules/ROOT/pages/building.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index 92ca7133..ed300e0e 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -39,7 +39,7 @@ $ helm upgrade listener-operator deploy/helm/listener-operator \ == Nix -To build and deploy to the active Kind cluster, run the following bash script: +To build and deploy to the active Kind cluster, run the following Bash commands: [source,console] ---- @@ -49,7 +49,7 @@ $ git submodule update --recursive --init # Use crate2nix (https://github.com/kolloch/crate2nix) to convert Cargo.lock into a Nix derivation $ nix run -f . crate2nix generate # Build the Docker images -# A custom Docker repository can be specified by appending `--argstr dockerName my-custom-repository` +# A custom Docker repository can be specified by appending `--argstr dockerName my-custom-registry/listener-operator` $ nix build -f . docker # Load the images onto the Kind nodes # Nix does not use the Docker daemon, instead it builds individual layers, as well as From fa45a84b77c48755b27f49d6adc4b217e013de10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 12:58:26 +0200 Subject: [PATCH 65/99] Update docs/modules/ROOT/pages/building.adoc Co-authored-by: Siegfried Weber --- docs/modules/ROOT/pages/building.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index ed300e0e..ff233051 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -10,8 +10,8 @@ for the local Kubelet, which means that it should only be executed inside a Kube * `docker build` * https://nixos.org/[Nix] -The `docker build`command is currently the primary deployment target, and the official images are built -using it. However, Nix has much faster incremental build and deploy times, making it ideal for local development. +The `docker build` command is currently the primary deployment target, and the official images are built +using it. However, Nix has much faster incremental build and deployment times, making it ideal for local development. == Docker From ee1b2a5ad821102c82c95693228763213d5c06e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 12:59:06 +0200 Subject: [PATCH 66/99] Update docs/modules/ROOT/examples/usage-pod.yaml Co-authored-by: Siegfried Weber --- docs/modules/ROOT/examples/usage-pod.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/modules/ROOT/examples/usage-pod.yaml b/docs/modules/ROOT/examples/usage-pod.yaml index 80ab4668..9e316110 100644 --- a/docs/modules/ROOT/examples/usage-pod.yaml +++ b/docs/modules/ROOT/examples/usage-pod.yaml @@ -21,6 +21,9 @@ spec: containers: - name: nginx image: nginx + ports: + - name: http + containerPort: 80 volumeMounts: - name: listener mountPath: /listener # <3> From b394795b550fcc5dc3df08f7ac85b808be1e060b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 12:59:30 +0200 Subject: [PATCH 67/99] Update docs/modules/ROOT/pages/index.adoc Co-authored-by: Siegfried Weber --- docs/modules/ROOT/pages/index.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index d44b0d32..f8568992 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -1,3 +1,3 @@ = Stackable Listener Operator -This is an operator for Kubernetes that provisions network listeners according to cluster policy, and injects connection parameters into Pods. +This is an operator for Kubernetes that provisions network listeners according to the cluster policy, and injects connection parameters into Pods. From 21c4d535c5c9a788d105d1a287c88e57a7e0658e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 13:00:20 +0200 Subject: [PATCH 68/99] Update docs/modules/ROOT/pages/listener.adoc Co-authored-by: Siegfried Weber --- docs/modules/ROOT/pages/listener.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/listener.adoc b/docs/modules/ROOT/pages/listener.adoc index f1bae800..73a66940 100644 --- a/docs/modules/ROOT/pages/listener.adoc +++ b/docs/modules/ROOT/pages/listener.adoc @@ -1,6 +1,6 @@ = `Listener` -A `Listener` object exposes a set of `Pod`s according to the rules of a xref:listenerclass.adoc[], but it also adds a couple of other +A `Listener` object exposes a set of ``Pod``s according to the rules of a xref:listenerclass.adoc[], but it also adds a couple of other features that are useful for the Stackable platform at large. == `ListenerClass` From 2124deff8e430c4a99b6796b347026002c8aa8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 13:01:01 +0200 Subject: [PATCH 69/99] Update docs/modules/ROOT/pages/listener.adoc Co-authored-by: Siegfried Weber --- docs/modules/ROOT/pages/listener.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/listener.adoc b/docs/modules/ROOT/pages/listener.adoc index 73a66940..1391b234 100644 --- a/docs/modules/ROOT/pages/listener.adoc +++ b/docs/modules/ROOT/pages/listener.adoc @@ -20,8 +20,8 @@ For example, if the volume is mounted to `/stackable/listener`, the primary addr == Per-replica listeners A `Listener` PVC can also specify a xref:listenerclass.adoc[] rather than a `Listener`, in which case a `Listener` object is created -automatically. These PVCs can automatically be created for each replica using either `StatefulSet` 's `volumeClaimTemplates` (for long-lived listeners that will -be kept across replica restarts and upgrades) or `Pod` 's `volumes[].ephemeral` (for temporary listeners that are deleted when their corresponding `Pod` is deleted). +automatically. These PVCs can automatically be created for each replica using either ``StatefulSet``'s `volumeClaimTemplates` (for long-lived listeners that will +be kept across replica restarts and upgrades) or ``Pod``'s `volumes[].ephemeral` (for temporary listeners that are deleted when their corresponding `Pod` is deleted). == Sticky scheduling From 7f03ef1044df59b209a5872d94f176bf1e7ea0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 14:47:10 +0200 Subject: [PATCH 70/99] Update docs/modules/ROOT/pages/listener.adoc Co-authored-by: Siegfried Weber --- docs/modules/ROOT/pages/listener.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/listener.adoc b/docs/modules/ROOT/pages/listener.adoc index 1391b234..2ef6aedd 100644 --- a/docs/modules/ROOT/pages/listener.adoc +++ b/docs/modules/ROOT/pages/listener.adoc @@ -28,5 +28,5 @@ be kept across replica restarts and upgrades) or ``Pod``'s `volumes[].ephemeral` When mounting a `Listener` PVC, it will be made "sticky" to that node if the xref:listenerclass.adoc[] uses a strategy that depends on the node that the workload is running on. -Keep in mind that this will only work correctly when using long-lived PVCs (such as via `StatefulSet` 's `volumeClaimTemplates`). Ephemeral PVCs +Keep in mind that this will only work correctly when using long-lived PVCs (such as via ``StatefulSet``'s `volumeClaimTemplates`). Ephemeral PVCs will be "reset" for every pod that is created, even if they refer to a long-lived `Listener` object. From 3e9b30390781b2e82eaf6591bf5c7d6c3ad7e13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 14:48:25 +0200 Subject: [PATCH 71/99] Apply suggestions from code review Co-authored-by: Siegfried Weber --- docs/modules/ROOT/pages/volume.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index c02f5a2f..c9d4a772 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -54,4 +54,4 @@ Provisions metadata about an existing xref:listener.adoc[] that was created manu *Required*: If `listeners.stackable.tech/listener-name` is not specified Provisions a new xref:listener.adoc[] using the specified xref:listenerclass.adoc[]. The created xref:listener.adoc[] will expose -all of the `Pod` 's ports. +all of the ``Pod``'s ports. From 8dd61570eabe27ac5b2158c0e902e76e4eecddf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 15:22:47 +0200 Subject: [PATCH 72/99] Update docs/modules/ROOT/pages/volume.adoc Co-authored-by: Siegfried Weber --- docs/modules/ROOT/pages/volume.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index c9d4a772..6265ea2e 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -9,7 +9,7 @@ Some xref:listenerclass.adoc[] strategies, such as `NodePort`, tie the public ad (such as for HDFS NameNodes), then Kubernetes' default "floating" scheduling either requires all clients to be reconfigured every time something moves, or for all clients to proxy their traffic through a single static node, which then becomes a single point of failure (along with the node that the workload is running on). -Mounting listeners into Pods as `PersistentVolume` allows the Listener Operator to pin these workloads to one node. Note that this only happens for xref:listenerclass.adoc[] es that actually benefit +Mounting listeners into Pods as `PersistentVolume` allows the Listener Operator to pin these workloads to one node. Note that this only happens for xref:listenerclass.adoc[]es that actually benefit from pinning. == Pod metadata injection From b0729b7b39f61d9b0179c87f8abbcc63a4ed75c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 15:27:27 +0200 Subject: [PATCH 73/99] Update docs/modules/ROOT/pages/volume.adoc Co-authored-by: Siegfried Weber --- docs/modules/ROOT/pages/volume.adoc | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index 6265ea2e..3ed72133 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -17,15 +17,16 @@ from pinning. Some services (such as Kafka) need to know their external address, so that they can advertise it to their own replica discovery mechanism. xref:listener.adoc[] volumes contain a file tree that exposes this information: -[source] ----- -- `default-address/`- A symlink to `addresses/{primary address}` -- `addresses/` - Contains information about all addresses associated with this xref:listener.adoc[] - - `{address}/` - A folder is created for each address - - `address` - Contains the Pod's address (IP address or hostname) - - `ports/` - Contains port numbers for each named port - - `{port name}` - Contains the public port number for this named port ----- +[square] +* `default-address/`- A symlink to `addresses/{primary address}` +* `addresses/` - Contains information about all addresses associated with this xref:listener.adoc[] +[square] +** `{address}/` - A folder is created for each address +[square] +*** `address` - Contains the Pod's address (IP address or hostname) +*** `ports/` - Contains port numbers for each named port +[square] +**** `{port name}` - Contains the public port number for this named port == Individual pod exposure From c03482ec63f75c3bec42282a11ccac354a0ebc6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 19 Sep 2022 15:31:12 +0200 Subject: [PATCH 74/99] Fix doc escaping --- docs/modules/ROOT/pages/volume.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/volume.adoc b/docs/modules/ROOT/pages/volume.adoc index 3ed72133..13d74c5a 100644 --- a/docs/modules/ROOT/pages/volume.adoc +++ b/docs/modules/ROOT/pages/volume.adoc @@ -21,7 +21,7 @@ this information: * `default-address/`- A symlink to `addresses/{primary address}` * `addresses/` - Contains information about all addresses associated with this xref:listener.adoc[] [square] -** `{address}/` - A folder is created for each address +** `\{address\}/` - A folder is created for each address [square] *** `address` - Contains the Pod's address (IP address or hostname) *** `ports/` - Contains port numbers for each named port From 7d7f9fc4acc20663333d1a403979c7c0de932bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 10:45:08 +0200 Subject: [PATCH 75/99] Rename preprovisioned example listener back to -lb --- examples/nginx-preprovisioned-lb.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nginx-preprovisioned-lb.yaml b/examples/nginx-preprovisioned-lb.yaml index 43b34b9f..49530273 100644 --- a/examples/nginx-preprovisioned-lb.yaml +++ b/examples/nginx-preprovisioned-lb.yaml @@ -38,7 +38,7 @@ spec: apiVersion: listeners.stackable.tech/v1alpha1 kind: Listener metadata: - name: exposed-nginx-preprovisioned-listener + name: exposed-nginx-preprovisioned-lb spec: className: lb-external ports: From 063712d8afe92d3260dcf69ceba630f87fb39bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 10:45:43 +0200 Subject: [PATCH 76/99] Move CRDs into operator-rs --- Cargo.lock | 306 ++++++++++-------- Cargo.toml | 3 +- rust/operator-binary/Cargo.toml | 3 +- rust/operator-binary/src/crd.rs | 102 ------ .../src/csi_server/controller.rs | 15 +- rust/operator-binary/src/csi_server/node.rs | 8 +- rust/operator-binary/src/lib.rs | 1 - .../src/listener_controller.rs | 12 +- rust/operator-binary/src/main.rs | 16 +- 9 files changed, 197 insertions(+), 269 deletions(-) delete mode 100644 rust/operator-binary/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 2fd6c65e..7067455c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,13 +15,22 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -33,9 +42,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.59" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "async-stream" @@ -88,9 +97,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.5.13" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9496f0c1d1afb7a2af4338bbe1d969cddfead41d87a9fb3aaa6d0bbc7af648" +checksum = "c9e3356844c4d6a6d6467b8da2cffb4a2820be256f50a3a386c9d152bab31043" dependencies = [ "async-trait", "axum-core", @@ -117,9 +126,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4f44a0e6200e9d11a1cdc989e4b358f6e3d354fbf48478f345a17f4e43f8635" +checksum = "d9f0c0a60006f2a293d82d571f635042a72edf927539b7685bd62d361963839b" dependencies = [ "async-trait", "bytes", @@ -127,6 +136,8 @@ dependencies = [ "http", "http-body", "mime", + "tower-layer", + "tower-service", ] [[package]] @@ -180,9 +191,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byteorder" @@ -225,23 +236,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "serde", "time", + "wasm-bindgen", "winapi", ] [[package]] name = "clap" -version = "3.2.16" +version = "3.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" +checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" dependencies = [ "atty", "bitflags", @@ -256,9 +269,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.15" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck", "proc-macro-error", @@ -422,9 +435,9 @@ checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "encoding" @@ -538,19 +551,18 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "futures" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -563,9 +575,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -573,15 +585,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -590,15 +602,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ "proc-macro2", "quote", @@ -607,21 +619,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-channel", "futures-core", @@ -728,9 +740,9 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -805,6 +817,20 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "once_cell", + "wasm-bindgen", + "winapi", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -813,11 +839,10 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -849,9 +874,9 @@ checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "d8bf247779e67a9082a4790b45e71ac7cfd1321331a5c856a74a9faebdab78d0" dependencies = [ "either", ] @@ -890,9 +915,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -974,11 +999,11 @@ dependencies = [ "secrecy", "serde", "serde_json", - "serde_yaml", + "serde_yaml 0.8.26", "thiserror", "tokio", "tokio-native-tls", - "tokio-util 0.7.3", + "tokio-util 0.7.4", "tower", "tower-http", "tracing", @@ -1035,7 +1060,7 @@ dependencies = [ "smallvec", "thiserror", "tokio", - "tokio-util 0.7.3", + "tokio-util 0.7.4", "tracing", ] @@ -1047,9 +1072,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.127" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "libgit2-sys" @@ -1092,9 +1117,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" dependencies = [ "autocfg", "scopeguard", @@ -1118,12 +1143,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "matchit" version = "0.5.0" @@ -1209,9 +1228,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "openssl" @@ -1323,9 +1342,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.2.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" [[package]] name = "parking_lot" @@ -1361,9 +1380,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" @@ -1377,18 +1396,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", @@ -1421,9 +1440,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "prettyplease" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697ae720ee02011f439e0701db107ffe2916d83f718342d65d7f8bf7b8a5fee9" +checksum = "a49e86d2c26a24059894a3afa13fd17d063419b05dfb83f06d9c3566060c3f5a" dependencies = [ "proc-macro2", "syn", @@ -1473,7 +1492,7 @@ dependencies = [ "semver", "serde", "serde_json", - "serde_yaml", + "serde_yaml 0.8.26", "thiserror", "xml-rs", ] @@ -1565,9 +1584,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -1691,9 +1710,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -1714,18 +1733,18 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.142" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] @@ -1742,9 +1761,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.142" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -1764,9 +1783,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "indexmap", "itoa 1.0.3", @@ -1786,6 +1805,19 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "serde_yaml" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8613d593412a0deb7bbd8de9d908efff5a0cb9ccd8f62c641e7b2ed2f57291d1" +dependencies = [ + "indexmap", + "itoa 1.0.3", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -1843,9 +1875,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -1866,7 +1898,6 @@ dependencies = [ "prost-types", "serde", "serde_json", - "serde_yaml", "snafu", "socket2", "stackable-operator", @@ -1880,10 +1911,9 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.24.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.24.0#8667365352e384e298caa8ebe9f99b2381c190ed" +version = "0.25.0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feature/listener-operator#ac294e0d230141e4ca1d858e137d94d093df671c" dependencies = [ - "backoff", "chrono", "clap", "const_format", @@ -1902,7 +1932,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "serde_yaml", + "serde_yaml 0.9.13", "stackable-operator-derive", "strum", "thiserror", @@ -1914,8 +1944,8 @@ dependencies = [ [[package]] name = "stackable-operator-derive" -version = "0.24.0" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.24.0#8667365352e384e298caa8ebe9f99b2381c190ed" +version = "0.25.0" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feature/listener-operator#ac294e0d230141e4ca1d858e137d94d093df671c" dependencies = [ "darling", "proc-macro2", @@ -1940,9 +1970,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4faebde00e8ff94316c01800f9054fd2ba77d30d9e922541913051d1d978918b" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck", "proc-macro2", @@ -1953,9 +1983,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" dependencies = [ "proc-macro2", "quote", @@ -1993,24 +2023,24 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" dependencies = [ "proc-macro2", "quote", @@ -2076,9 +2106,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.20.1" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" dependencies = [ "autocfg", "bytes", @@ -2140,9 +2170,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" +checksum = "f6edf2d6bc038a43d31353570e27270603f4648d18f5ed10c0e179abe43255af" dependencies = [ "futures-core", "pin-project-lite", @@ -2165,9 +2195,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -2211,7 +2241,7 @@ dependencies = [ "prost-derive", "tokio", "tokio-stream", - "tokio-util 0.7.3", + "tokio-util 0.7.4", "tower", "tower-layer", "tower-service", @@ -2261,7 +2291,7 @@ dependencies = [ "rand", "slab", "tokio", - "tokio-util 0.7.3", + "tokio-util 0.7.4", "tower-layer", "tower-service", "tracing", @@ -2410,30 +2440,36 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68" [[package]] name = "url" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fe195a4f217c25b25cb5058ced57059824a678474874038dc88d211bf508d3" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", @@ -2482,9 +2518,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2492,9 +2528,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -2507,9 +2543,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2517,9 +2553,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -2530,19 +2566,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "which" -version = "4.2.5" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" dependencies = [ "either", - "lazy_static", "libc", + "once_cell", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 302ec2d9..6cb3fc3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ members = ["rust/operator-binary"] # Workaround for https://github.com/hyperium/tonic/issues/243 h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } -# [patch."https://github.com/stackabletech/operator-rs.git"] +[patch."https://github.com/stackabletech/operator-rs.git"] +stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feature/listener-operator" } # stackable-operator = { path = "../operator-rs" } diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 6bfce36c..199166dd 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -18,7 +18,7 @@ pin-project = "1.0.10" prost = "0.10.3" prost-types = "0.10.1" socket2 = { version = "0.4.4", features = ["all"] } -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.24.0" } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.25.0" } tokio = { version = "1.18.2", features = ["full"] } tokio-stream = { version = "0.1.8", features = ["net"] } tonic = "0.7.2" @@ -26,7 +26,6 @@ tonic-reflection = "0.4.0" anyhow = "1.0.57" serde = "1.0.137" serde_json = "1.0.81" -serde_yaml = "0.8.24" snafu = "0.7.1" strum = "0.24.1" diff --git a/rust/operator-binary/src/crd.rs b/rust/operator-binary/src/crd.rs index e8e8b970..8b137891 100644 --- a/rust/operator-binary/src/crd.rs +++ b/rust/operator-binary/src/crd.rs @@ -1,103 +1 @@ -use std::collections::BTreeMap; -use serde::{Deserialize, Serialize}; -use stackable_operator::kube::CustomResource; -use stackable_operator::schemars::{self, JsonSchema}; - -#[cfg(doc)] -use stackable_operator::k8s_openapi::api::core::v1::{Node, Pod, Service}; - -/// Defines a policy for how [`Listener`]s should be exposed. -#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema)] -#[kube( - group = "listeners.stackable.tech", - version = "v1alpha1", - kind = "ListenerClass", - crates( - kube_core = "stackable_operator::kube::core", - k8s_openapi = "stackable_operator::k8s_openapi", - schemars = "stackable_operator::schemars" - ) -)] -#[serde(rename_all = "camelCase")] -pub struct ListenerClassSpec { - pub service_type: ServiceType, - /// Annotations that should be added to the [`Service`] object. - #[serde(default)] - pub service_annotations: BTreeMap, -} - -/// The method used to access the services. -#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, PartialEq, Eq)] -pub enum ServiceType { - /// Reserve a port on each node. - NodePort, - /// Provision a dedicated load balancer. - LoadBalancer, -} - -/// Exposes a set of pods to the outside world. -/// -/// Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: -/// 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works -/// 2. It has a consistent API for reading back the exposed address(es) of the service -#[derive(CustomResource, Serialize, Deserialize, Clone, Debug, JsonSchema, Default)] -#[kube( - group = "listeners.stackable.tech", - version = "v1alpha1", - kind = "Listener", - namespaced, - status = "ListenerStatus", - crates( - kube_core = "stackable_operator::kube::core", - k8s_openapi = "stackable_operator::k8s_openapi", - schemars = "stackable_operator::schemars" - ) -)] -#[serde(rename_all = "camelCase")] -pub struct ListenerSpec { - /// The name of the [`ListenerClass`]. - pub class_name: Option, - /// Labels that the [`Pod`]s must share in order to be exposed. - pub pod_selector: Option>, - /// Ports that should be exposed. - pub ports: Option>, -} - -#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct ListenerPort { - /// The name of the port. - /// - /// The name of each port *must* be unique within a single [`Listener`]. - pub name: String, - /// The port number. - pub port: i32, - /// The layer-4 protocol (`TCP` or `UDP`). - pub protocol: Option, -} - -/// Informs users about how to reach the [`Listener`]. -#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct ListenerStatus { - /// The backing Kubernetes [`Service`]. - pub service_name: Option, - /// All addresses that the [`Listener`] is currently reachable from. - pub ingress_addresses: Option>, - /// Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on. - /// - /// This is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does - /// not require [`Node`]-local access. - pub node_ports: Option>, -} - -/// One address that a [`Listener`] is accessible from. -#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct ListenerIngress { - /// The hostname or IP address to the [`Listener`]. - pub address: String, - /// Port mapping table. - pub ports: BTreeMap, -} diff --git a/rust/operator-binary/src/csi_server/controller.rs b/rust/operator-binary/src/csi_server/controller.rs index f887703e..eddce75f 100644 --- a/rust/operator-binary/src/csi_server/controller.rs +++ b/rust/operator-binary/src/csi_server/controller.rs @@ -1,12 +1,13 @@ use serde::{de::IntoDeserializer, Deserialize}; use snafu::{OptionExt, ResultExt, Snafu}; use stackable_operator::{ + commons::listener::{Listener, ListenerClass, ServiceType}, k8s_openapi::api::core::v1::PersistentVolumeClaim, kube::{core::DynamicObject, runtime::reflector::ObjectRef}, }; use tonic::{Request, Response, Status}; -use crate::{crd::ServiceType, grpc::csi, utils::error_full_message}; +use crate::{grpc::csi, utils::error_full_message}; use super::{tonic_unimplemented, ListenerSelector, ListenerVolumeContext}; @@ -35,9 +36,7 @@ enum CreateVolumeError { #[snafu(display("failed to decode volume context"))] DecodeVolumeContext { source: serde::de::value::Error }, #[snafu(display("{listener} does not specify a listener class"))] - NoListenerClass { - listener: ObjectRef, - }, + NoListenerClass { listener: ObjectRef }, } impl From for Status { @@ -100,10 +99,10 @@ impl csi::v1::controller_server::Controller for ListenerOperatorController { ListenerSelector::Listener(listener_name) => { let listener = self .client - .get::(&listener_name, Some(&ns)) + .get::(&listener_name, Some(&ns)) .await .with_context(|_| GetObjectSnafu { - obj: ObjectRef::::new(&listener_name) + obj: ObjectRef::::new(&listener_name) .within(&ns) .erase(), })?; @@ -119,10 +118,10 @@ impl csi::v1::controller_server::Controller for ListenerOperatorController { }; let listener_class = self .client - .get::(&listener_class_name, None) + .get::(&listener_class_name, None) .await .with_context(|_| GetObjectSnafu { - obj: ObjectRef::::new(&listener_class_name) + obj: ObjectRef::::new(&listener_class_name) .within(&ns) .erase(), })?; diff --git a/rust/operator-binary/src/csi_server/node.rs b/rust/operator-binary/src/csi_server/node.rs index 172afefe..4fb9aec3 100644 --- a/rust/operator-binary/src/csi_server/node.rs +++ b/rust/operator-binary/src/csi_server/node.rs @@ -7,6 +7,7 @@ use serde::{ use snafu::{OptionExt, ResultExt, Snafu}; use stackable_operator::{ builder::OwnerReferenceBuilder, + commons::listener::{Listener, ListenerIngress, ListenerPort, ListenerSpec}, k8s_openapi::api::core::v1::{Node, PersistentVolume, Pod}, kube::{ core::{DynamicObject, ObjectMeta}, @@ -17,7 +18,6 @@ use stackable_operator::{ use tonic::{Request, Response, Status}; use crate::{ - crd::{Listener, ListenerIngress, ListenerPort, ListenerSpec}, grpc::csi::{self, v1::Topology}, utils::{error_full_message, node_primary_address}, }; @@ -60,7 +60,7 @@ enum PublishVolumeError { #[snafu(display("failed to apply {listener}"))] ApplyListener { source: stackable_operator::error::Error, - listener: ObjectRef, + listener: ObjectRef, }, #[snafu(display("failed to prepare pod dir at {target_path:?}"))] PreparePodDir { @@ -166,7 +166,7 @@ impl csi::v1::node_server::Node for ListenerOperatorNode { let listener = match listener_selector { ListenerSelector::Listener(listener_name) => { - get_obj::(&self.client, &listener_name, Some(&ns)).await? + get_obj::(&self.client, &listener_name, Some(&ns)).await? } ListenerSelector::ListenerClass(listener_class_name) => { let listener = Listener { @@ -302,8 +302,8 @@ impl csi::v1::node_server::Node for ListenerOperatorNode { mod pod_dir { use std::path::Path; - use crate::crd::ListenerIngress; use snafu::{OptionExt, ResultExt, Snafu}; + use stackable_operator::commons::listener::ListenerIngress; #[derive(Snafu, Debug)] pub enum Error { diff --git a/rust/operator-binary/src/lib.rs b/rust/operator-binary/src/lib.rs deleted file mode 100644 index b89e9789..00000000 --- a/rust/operator-binary/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod crd; diff --git a/rust/operator-binary/src/listener_controller.rs b/rust/operator-binary/src/listener_controller.rs index ddae09a6..103f3c39 100644 --- a/rust/operator-binary/src/listener_controller.rs +++ b/rust/operator-binary/src/listener_controller.rs @@ -1,14 +1,12 @@ -use crate::{ - crd::{ - Listener, ListenerClass, ListenerIngress, ListenerPort, ListenerSpec, ListenerStatus, - ServiceType, - }, - utils::node_primary_address, -}; +use crate::utils::node_primary_address; use futures::{future::try_join_all, StreamExt}; use snafu::{OptionExt, ResultExt, Snafu}; use stackable_operator::{ builder::OwnerReferenceBuilder, + commons::listener::{ + Listener, ListenerClass, ListenerIngress, ListenerPort, ListenerSpec, ListenerStatus, + ServiceType, + }, k8s_openapi::api::core::v1::{Endpoints, Node, Service, ServicePort, ServiceSpec}, kube::{ api::{DynamicObject, ListParams, ObjectMeta}, diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index a525fa20..3cb40a19 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -9,15 +9,16 @@ use futures::{pin_mut, FutureExt, TryStreamExt}; use grpc::csi::v1::{ controller_server::ControllerServer, identity_server::IdentityServer, node_server::NodeServer, }; -use stackable_operator::{kube::CustomResourceExt, logging::TracingTarget}; +use stackable_operator::{ + commons::listener::{Listener, ListenerClass}, + logging::TracingTarget, + CustomResourceExt, +}; use tokio::signal::unix::{signal, SignalKind}; use tokio_stream::wrappers::UnixListenerStream; use tonic::transport::Server; use utils::{uds_bind_private, TonicUnixStream}; -use crate::crd::{Listener, ListenerClass}; - -mod crd; mod csi_server; mod grpc; mod listener_controller; @@ -52,11 +53,8 @@ async fn main() -> anyhow::Result<()> { let opts = Opts::parse(); match opts.cmd { stackable_operator::cli::Command::Crd => { - println!( - "{}{}", - serde_yaml::to_string(&ListenerClass::crd()).unwrap(), - serde_yaml::to_string(&Listener::crd()).unwrap() - ); + ListenerClass::print_yaml_schema()?; + Listener::print_yaml_schema()?; } stackable_operator::cli::Command::Run(ListenerOperatorRun { csi_endpoint, From b2a09b9f17a753ded97d86796853b5b981564315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 10:58:19 +0200 Subject: [PATCH 77/99] Drop permission to access secrets --- deploy/manifests/roles.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/manifests/roles.yaml b/deploy/manifests/roles.yaml index 95830fee..a5896c90 100644 --- a/deploy/manifests/roles.yaml +++ b/deploy/manifests/roles.yaml @@ -7,7 +7,6 @@ rules: - apiGroups: - "" resources: - - secrets - events - services verbs: From 8c598b973807348a8e27596e2a3de1978ed766bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 11:00:49 +0200 Subject: [PATCH 78/99] Regenerate charts --- deploy/helm/listener-operator/crds/crds.yaml | 39 ++++++++++++-------- deploy/manifests/crds.yaml | 39 ++++++++++++-------- deploy/manifests/roles.yaml | 1 + 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/deploy/helm/listener-operator/crds/crds.yaml b/deploy/helm/listener-operator/crds/crds.yaml index 9b6ba10d..ad569a7f 100644 --- a/deploy/helm/listener-operator/crds/crds.yaml +++ b/deploy/helm/listener-operator/crds/crds.yaml @@ -19,16 +19,16 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for ListenerClassSpec via `CustomResource`" + description: Auto-generated derived type for ListenerClassSpec via `CustomResource` properties: spec: - description: "Defines a policy for how [`Listener`]s should be exposed." + description: Defines a policy for how [`Listener`]s should be exposed. properties: serviceAnnotations: additionalProperties: type: string default: {} - description: "Annotations that should be added to the [`Service`] object." + description: Annotations that should be added to the [`Service`] object. type: object serviceType: description: The method used to access the services. @@ -67,19 +67,22 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for ListenerSpec via `CustomResource`" + description: Auto-generated derived type for ListenerSpec via `CustomResource` properties: spec: - description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" + description: |- + Exposes a set of pods to the outside world. + + Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service properties: className: - description: "The name of the [`ListenerClass`]." + description: The name of the [`ListenerClass`]. nullable: true type: string podSelector: additionalProperties: type: string - description: "Labels that the [`Pod`]s must share in order to be exposed." + description: Labels that the [`Pod`]s must share in order to be exposed. nullable: true type: object ports: @@ -87,14 +90,17 @@ spec: items: properties: name: - description: "The name of the port.\n\nThe name of each port *must* be unique within a single [`Listener`]." + description: |- + The name of the port. + + The name of each port *must* be unique within a single [`Listener`]. type: string port: description: The port number. format: int32 type: integer protocol: - description: "The layer-4 protocol (`TCP` or `UDP`)." + description: The layer-4 protocol (`TCP` or `UDP`). nullable: true type: string required: @@ -105,16 +111,16 @@ spec: type: array type: object status: - description: "Informs users about how to reach the [`Listener`]." + description: Informs users about how to reach the [`Listener`]. nullable: true properties: ingressAddresses: - description: "All addresses that the [`Listener`] is currently reachable from." + description: All addresses that the [`Listener`] is currently reachable from. items: - description: "One address that a [`Listener`] is accessible from." + description: One address that a [`Listener`] is accessible from. properties: address: - description: "The hostname or IP address to the [`Listener`]." + description: The hostname or IP address to the [`Listener`]. type: string ports: additionalProperties: @@ -132,11 +138,14 @@ spec: additionalProperties: format: int32 type: integer - description: "Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does not require [`Node`]-local access." + description: |- + Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on. + + This is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does not require [`Node`]-local access. nullable: true type: object serviceName: - description: "The backing Kubernetes [`Service`]." + description: The backing Kubernetes [`Service`]. nullable: true type: string type: object diff --git a/deploy/manifests/crds.yaml b/deploy/manifests/crds.yaml index 57b2b1c0..8b305d6a 100644 --- a/deploy/manifests/crds.yaml +++ b/deploy/manifests/crds.yaml @@ -20,16 +20,16 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for ListenerClassSpec via `CustomResource`" + description: Auto-generated derived type for ListenerClassSpec via `CustomResource` properties: spec: - description: "Defines a policy for how [`Listener`]s should be exposed." + description: Defines a policy for how [`Listener`]s should be exposed. properties: serviceAnnotations: additionalProperties: type: string default: {} - description: "Annotations that should be added to the [`Service`] object." + description: Annotations that should be added to the [`Service`] object. type: object serviceType: description: The method used to access the services. @@ -68,19 +68,22 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: "Auto-generated derived type for ListenerSpec via `CustomResource`" + description: Auto-generated derived type for ListenerSpec via `CustomResource` properties: spec: - description: "Exposes a set of pods to the outside world.\n\nEssentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service" + description: |- + Exposes a set of pods to the outside world. + + Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service properties: className: - description: "The name of the [`ListenerClass`]." + description: The name of the [`ListenerClass`]. nullable: true type: string podSelector: additionalProperties: type: string - description: "Labels that the [`Pod`]s must share in order to be exposed." + description: Labels that the [`Pod`]s must share in order to be exposed. nullable: true type: object ports: @@ -88,14 +91,17 @@ spec: items: properties: name: - description: "The name of the port.\n\nThe name of each port *must* be unique within a single [`Listener`]." + description: |- + The name of the port. + + The name of each port *must* be unique within a single [`Listener`]. type: string port: description: The port number. format: int32 type: integer protocol: - description: "The layer-4 protocol (`TCP` or `UDP`)." + description: The layer-4 protocol (`TCP` or `UDP`). nullable: true type: string required: @@ -106,16 +112,16 @@ spec: type: array type: object status: - description: "Informs users about how to reach the [`Listener`]." + description: Informs users about how to reach the [`Listener`]. nullable: true properties: ingressAddresses: - description: "All addresses that the [`Listener`] is currently reachable from." + description: All addresses that the [`Listener`] is currently reachable from. items: - description: "One address that a [`Listener`] is accessible from." + description: One address that a [`Listener`] is accessible from. properties: address: - description: "The hostname or IP address to the [`Listener`]." + description: The hostname or IP address to the [`Listener`]. type: string ports: additionalProperties: @@ -133,11 +139,14 @@ spec: additionalProperties: format: int32 type: integer - description: "Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on.\n\nThis is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does not require [`Node`]-local access." + description: |- + Port mappings for accessing the [`Listener`] on each [`Node`] that the [`Pod`]s are currently running on. + + This is only intended for internal use by listener-operator itself. This will be left unset if using a [`ListenerClass`] that does not require [`Node`]-local access. nullable: true type: object serviceName: - description: "The backing Kubernetes [`Service`]." + description: The backing Kubernetes [`Service`]. nullable: true type: string type: object diff --git a/deploy/manifests/roles.yaml b/deploy/manifests/roles.yaml index a5896c90..95830fee 100644 --- a/deploy/manifests/roles.yaml +++ b/deploy/manifests/roles.yaml @@ -7,6 +7,7 @@ rules: - apiGroups: - "" resources: + - secrets - events - services verbs: From b91d438374560c0a212d5e5e6af69c14435625b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 11:15:24 +0200 Subject: [PATCH 79/99] Redid Nix build linebreaks --- docs/modules/ROOT/pages/building.adoc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/modules/ROOT/pages/building.adoc b/docs/modules/ROOT/pages/building.adoc index ff233051..f91c7c90 100644 --- a/docs/modules/ROOT/pages/building.adoc +++ b/docs/modules/ROOT/pages/building.adoc @@ -46,15 +46,19 @@ To build and deploy to the active Kind cluster, run the following Bash commands: $ echo Building with Nix # Ensure that all submodules are up-to-date $ git submodule update --recursive --init -# Use crate2nix (https://github.com/kolloch/crate2nix) to convert Cargo.lock into a Nix derivation +# Use crate2nix (https://github.com/kolloch/crate2nix) to convert +# Cargo.lock into a Nix derivation $ nix run -f . crate2nix generate # Build the Docker images -# A custom Docker repository can be specified by appending `--argstr dockerName my-custom-registry/listener-operator` +# A custom Docker repository can be specified by appending +# `--argstr dockerName my-custom-registry/listener-operator` $ nix build -f . docker # Load the images onto the Kind nodes -# Nix does not use the Docker daemon, instead it builds individual layers, as well as -# a script (`result/load-image`) that combines them into a Docker image archive. -# `load-image` can also be piped into `docker load` to prepare for pushing to a registry. +# Nix does not use the Docker daemon, instead it builds individual +# layers, as well as a script (`result/load-image`) that combines +# them into a Docker image archive. +# `load-image` can also be piped into `docker load` to prepare for +# pushing to a registry. $ ./result/load-image > image.tar && kind load image-archive image.tar # On single-node kind clusters it is slightly more efficient to run # `./result/load-image | kind load image-archive /dev/stdin` instead. From b3d3ba6ad7b60944eef5a3a67e43d02e2d5ac563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 11:16:45 +0200 Subject: [PATCH 80/99] Reformatted README to follow our conventions and link to Antora --- README.md | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 6e4bcc4c..4265c41e 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,10 @@ # Stackable Listener Operator -A CSI provider intended to provide an abstract way to expose a single Pod to the outside network, -while hiding details about the cluster from the application developer. +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/stackabletech/secret-operator/graphs/commit-activity) -## Usage +A CSI provider intended to provide an abstract way to expose a single Pod to the outside network, while hiding details about the cluster from the application developer. -### Running +It is written by [Stackable](https://www.stackable.tech) in Rust. -`nix run -f. tilt up` - -### ListenerClass - -`ListenerClass` objects are used by cluster administrators to define a policy for how incoming connections -should be handled. For example, a small on-prem cluster might prefer to use `NodePort` services (because they don't -require BGP peering or ARP spoofing, at the cost of making each instance "sticky" to its initial K8s Node), while a -managed cloud cluster might prefer `LoadBalancer`. - -### Pods - -Pods are exposed by mounting a `PersistentVolume` with the `storageClassName` of `listeners.stackable.tech` into them. -This can either be created as a `volumeClaimTemplate` of a `StatefulSet` (ensuring that each network identity will be -persistent for each replica identity, even across pod replacements) or an `ephemeral` pod `Volume` (in which case the -network identity will be recreated from scratch for every Pod). - -The `ListenerClass` is specified using the `listeners.stackable.tech/listener-class` annotation on the `PersistentVolumeClaim`. - -The mounted volume will contain the file `address` (containing the external address of the `Pod`), as well as -`ports/{port-name}` (containing the port number that the port is accessible on `address` from, which may or may not -be the same as the `containerPort`). +The documentation for this operator can be found at https://docs.stackable.tech/listener-operator/stable/index.html. +The documentation for all Stackable products can be found at https://docs.stackable.tech. From eff7c41a8ff75e545233b5ef119f12fd8380d3c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 11:37:16 +0200 Subject: [PATCH 81/99] Explicitly disable serviceName for example STSes --- examples/nginx-lb.yaml | 1 + examples/nginx-nodeport.yaml | 1 + examples/nginx-preprovisioned-lb.yaml | 1 + 3 files changed, 3 insertions(+) diff --git a/examples/nginx-lb.yaml b/examples/nginx-lb.yaml index 73d3f3e8..715ddbf4 100644 --- a/examples/nginx-lb.yaml +++ b/examples/nginx-lb.yaml @@ -5,6 +5,7 @@ metadata: name: exposed-nginx-lb spec: replicas: 1 + serviceName: "" selector: matchLabels: app: exposed-nginx-lb diff --git a/examples/nginx-nodeport.yaml b/examples/nginx-nodeport.yaml index e6e19fd3..e6b302bb 100644 --- a/examples/nginx-nodeport.yaml +++ b/examples/nginx-nodeport.yaml @@ -5,6 +5,7 @@ metadata: name: exposed-nginx-nodeport spec: replicas: 1 + serviceName: "" selector: matchLabels: app: exposed-nginx-nodeport diff --git a/examples/nginx-preprovisioned-lb.yaml b/examples/nginx-preprovisioned-lb.yaml index 49530273..7d7d9464 100644 --- a/examples/nginx-preprovisioned-lb.yaml +++ b/examples/nginx-preprovisioned-lb.yaml @@ -5,6 +5,7 @@ metadata: name: exposed-nginx-preprovisioned-lb spec: replicas: 1 + serviceName: "" selector: matchLabels: app: exposed-nginx-preprovisioned-lb From c2b55bab5d3944b45162830b78f2452811fb9c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 11:38:38 +0200 Subject: [PATCH 82/99] Remove FmtByteSlice --- rust/operator-binary/src/utils.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/rust/operator-binary/src/utils.rs b/rust/operator-binary/src/utils.rs index 140496f8..81b4a377 100644 --- a/rust/operator-binary/src/utils.rs +++ b/rust/operator-binary/src/utils.rs @@ -1,4 +1,4 @@ -use std::{fmt::LowerHex, os::unix::prelude::AsRawFd, path::Path}; +use std::{os::unix::prelude::AsRawFd, path::Path}; use pin_project::pin_project; use socket2::Socket; @@ -87,17 +87,6 @@ pub fn uds_bind_private(path: impl AsRef) -> Result(pub &'a [u8]); -impl LowerHex for FmtByteSlice<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for byte in self.0 { - f.write_fmt(format_args!("{:02x}", byte))?; - } - Ok(()) - } -} - /// Combines the messages of an error and its sources into a [`String`] of the form `"error: source 1: source 2: root error"` pub fn error_full_message(err: &dyn std::error::Error) -> String { use std::fmt::Write; @@ -130,12 +119,7 @@ pub fn node_primary_address(node: &Node) -> Option<&str> { #[cfg(test)] mod tests { - use crate::utils::{error_full_message, FmtByteSlice}; - - #[test] - fn fmt_hex_byte_slice() { - assert_eq!(format!("{:x}", FmtByteSlice(&[1, 2, 255, 128])), "0102ff80"); - } + use crate::utils::error_full_message; #[test] fn error_messages() { From a4b7cc81f75f4d10f7b5b197b215fea08d52172f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 11:43:09 +0200 Subject: [PATCH 83/99] Drop serde_json dependency --- Cargo.lock | 1 - rust/operator-binary/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7067455c..c4042253 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1897,7 +1897,6 @@ dependencies = [ "prost", "prost-types", "serde", - "serde_json", "snafu", "socket2", "stackable-operator", diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 199166dd..7f9c01de 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -25,7 +25,6 @@ tonic = "0.7.2" tonic-reflection = "0.4.0" anyhow = "1.0.57" serde = "1.0.137" -serde_json = "1.0.81" snafu = "0.7.1" strum = "0.24.1" From 7edf94b5a8846d1e028fc1715e9cb2e70483acc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 14:32:42 +0200 Subject: [PATCH 84/99] Update operator-rs --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4042253..a524f750 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1911,7 +1911,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.25.0" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feature/listener-operator#ac294e0d230141e4ca1d858e137d94d093df671c" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=main#4ec1567f9ef27bff20a43c7fab6a9aa05c4e2591" dependencies = [ "chrono", "clap", @@ -1944,7 +1944,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.25.0" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feature/listener-operator#ac294e0d230141e4ca1d858e137d94d093df671c" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=main#4ec1567f9ef27bff20a43c7fab6a9aa05c4e2591" dependencies = [ "darling", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 6cb3fc3f..3ece52d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,5 @@ members = ["rust/operator-binary"] h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } [patch."https://github.com/stackabletech/operator-rs.git"] -stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feature/listener-operator" } +stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" } # stackable-operator = { path = "../operator-rs" } From 8774de155ef3363dbc4e27d0321ef75d8f116356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 15:03:29 +0200 Subject: [PATCH 85/99] Deploy the controller separately from the node agents --- default.nix | 3 +- .../templates/controller-deployment.yaml | 70 +++++++++++++++++++ .../templates/deployment.yaml | 1 - .../{daemonset.yaml => node-daemonset.yaml} | 16 ++--- rust/operator-binary/src/main.rs | 67 ++++++++++++------ 5 files changed, 122 insertions(+), 35 deletions(-) create mode 100644 deploy/helm/listener-operator/templates/controller-deployment.yaml delete mode 100644 deploy/helm/listener-operator/templates/deployment.yaml rename deploy/helm/listener-operator/templates/{daemonset.yaml => node-daemonset.yaml} (88%) diff --git a/default.nix b/default.nix index 9c339d21..d1674f46 100644 --- a/default.nix +++ b/default.nix @@ -27,7 +27,8 @@ rec { tag = dockerTag; contents = [ pkgs.bashInteractive pkgs.coreutils pkgs.util-linuxMinimal ]; config = { - Cmd = [ (build+"/bin/stackable-listener-operator") "run" ]; + Entrypoint = [ (build+"/bin/stackable-listener-operator") ]; + Cmd = [ "run" ]; }; }; docker = pkgs.linkFarm "listener-operator-docker" [ diff --git a/deploy/helm/listener-operator/templates/controller-deployment.yaml b/deploy/helm/listener-operator/templates/controller-deployment.yaml new file mode 100644 index 00000000..772925eb --- /dev/null +++ b/deploy/helm/listener-operator/templates/controller-deployment.yaml @@ -0,0 +1,70 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-controller-deployment + labels: + {{- include "operator.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/role: controller + {{- include "operator.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + app.kubernetes.io/role: controller + {{- include "operator.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ .Release.Name }}-serviceaccount + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ include "operator.appname" . }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + args: + - run + - controller + env: + - name: CSI_ENDPOINT + value: /csi/csi.sock + volumeMounts: + - name: csi + mountPath: /csi + - name: external-provisioner + image: k8s.gcr.io/sig-storage/csi-provisioner:v3.1.0 + args: + - --csi-address=/csi/csi.sock + - --feature-gates=Topology=true + - --extra-create-metadata + volumeMounts: + - name: csi + mountPath: /csi + volumes: + - name: csi + emptyDir: {} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deploy/helm/listener-operator/templates/deployment.yaml b/deploy/helm/listener-operator/templates/deployment.yaml deleted file mode 100644 index a5c58dd7..00000000 --- a/deploy/helm/listener-operator/templates/deployment.yaml +++ /dev/null @@ -1 +0,0 @@ -# Templated Deployment disabled for this operator diff --git a/deploy/helm/listener-operator/templates/daemonset.yaml b/deploy/helm/listener-operator/templates/node-daemonset.yaml similarity index 88% rename from deploy/helm/listener-operator/templates/daemonset.yaml rename to deploy/helm/listener-operator/templates/node-daemonset.yaml index 3dbf3fa7..f5f632ae 100644 --- a/deploy/helm/listener-operator/templates/daemonset.yaml +++ b/deploy/helm/listener-operator/templates/node-daemonset.yaml @@ -2,12 +2,13 @@ apiVersion: apps/v1 kind: DaemonSet metadata: - name: {{ .Release.Name }}-daemonset + name: {{ .Release.Name }}-node-daemonset labels: {{- include "operator.labels" . | nindent 4 }} spec: selector: matchLabels: + app.kubernetes.io/role: node {{- include "operator.selectorLabels" . | nindent 6 }} template: metadata: @@ -16,6 +17,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} labels: + app.kubernetes.io/role: node {{- include "operator.selectorLabels" . | nindent 8 }} spec: {{- with .Values.imagePullSecrets }} @@ -33,6 +35,9 @@ spec: imagePullPolicy: {{ .Values.image.pullPolicy }} resources: {{- toYaml .Values.resources | nindent 12 }} + args: + - run + - node env: - name: CSI_ENDPOINT value: /csi/csi.sock @@ -47,15 +52,6 @@ spec: - name: mountpoint mountPath: /var/lib/kubelet/pods mountPropagation: Bidirectional - - name: external-provisioner - image: k8s.gcr.io/sig-storage/csi-provisioner:v3.1.0 - args: - - --csi-address=/csi/csi.sock - - --feature-gates=Topology=true - - --extra-create-metadata - volumeMounts: - - name: csi - mountPath: /csi - name: node-driver-registrar image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0 args: diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index 3cb40a19..ef1f1cb2 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -35,12 +35,22 @@ struct Opts { #[derive(clap::Parser)] struct ListenerOperatorRun { - #[clap(long, env)] - csi_endpoint: PathBuf, - #[clap(long, env)] - node_name: String, #[clap(long, env, default_value_t, arg_enum)] tracing_target: TracingTarget, + #[clap(long, env)] + csi_endpoint: PathBuf, + + #[clap(subcommand)] + mode: RunMode, +} + +#[derive(clap::Parser, strum::AsRefStr)] +enum RunMode { + Controller, + Node { + #[clap(long, env)] + node_name: String, + }, } mod built_info { @@ -57,9 +67,9 @@ async fn main() -> anyhow::Result<()> { Listener::print_yaml_schema()?; } stackable_operator::cli::Command::Run(ListenerOperatorRun { - csi_endpoint, - node_name, tracing_target, + csi_endpoint, + mode, }) => { stackable_operator::logging::initialize_logging( "LISTENER_OPERATOR_LOG", @@ -67,7 +77,7 @@ async fn main() -> anyhow::Result<()> { tracing_target, ); stackable_operator::utils::print_startup_string( - crate_description!(), + &format!("{} ({})", crate_description!(), mode.as_ref()), crate_version!(), built_info::GIT_VERSION, built_info::TARGET.unwrap_or("unknown target"), @@ -83,6 +93,8 @@ async fn main() -> anyhow::Result<()> { let _ = std::fs::remove_file(&csi_endpoint); } let mut sigterm = signal(SignalKind::terminate())?; + let csi_listener = + UnixListenerStream::new(uds_bind_private(csi_endpoint)?).map_ok(TonicUnixStream); let csi_server = Server::builder() .add_service( tonic_reflection::server::Builder::configure() @@ -90,22 +102,31 @@ async fn main() -> anyhow::Result<()> { .register_encoded_file_descriptor_set(grpc::FILE_DESCRIPTOR_SET_BYTES) .build()?, ) - .add_service(IdentityServer::new(ListenerOperatorIdentity)) - .add_service(ControllerServer::new(ListenerOperatorController { - client: client.clone(), - })) - .add_service(NodeServer::new(ListenerOperatorNode { - client: client.clone(), - node_name, - })) - .serve_with_incoming_shutdown( - UnixListenerStream::new(uds_bind_private(csi_endpoint)?) - .map_ok(TonicUnixStream), - sigterm.recv().map(|_| ()), - ); - let controller = listener_controller::run(client); - pin_mut!(csi_server, controller); - futures::future::select(csi_server, controller).await; + .add_service(IdentityServer::new(ListenerOperatorIdentity)); + + match mode { + RunMode::Controller => { + let csi_server = csi_server + .add_service(ControllerServer::new(ListenerOperatorController { + client: client.clone(), + })) + .serve_with_incoming_shutdown(csi_listener, sigterm.recv().map(|_| ())); + let controller = listener_controller::run(client).map(Ok); + pin_mut!(csi_server, controller); + futures::future::try_select(csi_server, controller) + .await + .map_err(|err| err.factor_first().0)?; + } + RunMode::Node { node_name } => { + csi_server + .add_service(NodeServer::new(ListenerOperatorNode { + client: client.clone(), + node_name, + })) + .serve_with_incoming_shutdown(csi_listener, sigterm.recv().map(|_| ())) + .await?; + } + } } } Ok(()) From 2ec3030c4a7d0a94548610e1e501b2be685ab9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Thu, 22 Sep 2022 17:03:15 +0200 Subject: [PATCH 86/99] Split out gRPC definitions to a separate crate --- .gitmodules | 4 ++-- Cargo.lock | 14 ++++++++++++-- Cargo.toml | 2 +- default.nix | 2 +- rust/csi-grpc/Cargo.toml | 15 +++++++++++++++ rust/csi-grpc/build.rs | 11 +++++++++++ .../src/grpc.rs => csi-grpc/src/lib.rs} | 6 ++---- rust/{operator-binary => csi-grpc}/vendor/csi | 0 rust/operator-binary/Cargo.toml | 3 +-- rust/operator-binary/build.rs | 6 ------ rust/operator-binary/src/crd.rs | 1 - rust/operator-binary/src/csi_server/controller.rs | 3 ++- rust/operator-binary/src/csi_server/identity.rs | 3 ++- rust/operator-binary/src/csi_server/node.rs | 6 ++---- rust/operator-binary/src/main.rs | 9 ++++----- 15 files changed, 55 insertions(+), 30 deletions(-) create mode 100644 rust/csi-grpc/Cargo.toml create mode 100644 rust/csi-grpc/build.rs rename rust/{operator-binary/src/grpc.rs => csi-grpc/src/lib.rs} (79%) rename rust/{operator-binary => csi-grpc}/vendor/csi (100%) delete mode 100644 rust/operator-binary/src/crd.rs diff --git a/.gitmodules b/.gitmodules index aabdd5b8..b2e03c66 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "rust/operator-binary/vendor/csi"] - path = rust/operator-binary/vendor/csi +[submodule "rust/csi-grpc/vendor/csi"] + path = rust/csi-grpc/vendor/csi url = https://github.com/container-storage-interface/spec diff --git a/Cargo.lock b/Cargo.lock index a524f750..05c2f117 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -354,6 +354,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "csi-grpc" +version = "0.1.0" +dependencies = [ + "built", + "prost", + "prost-types", + "tonic", + "tonic-build", +] + [[package]] name = "darling" version = "0.14.1" @@ -1890,12 +1901,12 @@ dependencies = [ "anyhow", "built", "clap", + "csi-grpc", "futures", "h2", "libc", "pin-project", "prost", - "prost-types", "serde", "snafu", "socket2", @@ -1904,7 +1915,6 @@ dependencies = [ "tokio", "tokio-stream", "tonic", - "tonic-build", "tonic-reflection", ] diff --git a/Cargo.toml b/Cargo.toml index 3ece52d8..f2d62b4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["rust/operator-binary"] +members = ["rust/operator-binary", "rust/csi-grpc"] [patch.crates-io] # Workaround for https://github.com/hyperium/tonic/issues/243 diff --git a/default.nix b/default.nix index d1674f46..c4ef02a0 100644 --- a/default.nix +++ b/default.nix @@ -16,7 +16,7 @@ , dockerTag ? null }: rec { - build = cargo.rootCrate.build; + build = cargo.workspaceMembers.stackable-listener-operator.build; crds = pkgs.runCommand "listener-operator-crds.yaml" {} '' ${build}/bin/stackable-listener-operator crd > $out diff --git a/rust/csi-grpc/Cargo.toml b/rust/csi-grpc/Cargo.toml new file mode 100644 index 00000000..192f0dd7 --- /dev/null +++ b/rust/csi-grpc/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "csi-grpc" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +prost = "0.10.3" +prost-types = "0.10.1" +tonic = "0.7.2" + +[build-dependencies] +built = { version = "0.5.1", features = ["chrono", "git2"] } +tonic-build = "0.7.2" \ No newline at end of file diff --git a/rust/csi-grpc/build.rs b/rust/csi-grpc/build.rs new file mode 100644 index 00000000..155e936c --- /dev/null +++ b/rust/csi-grpc/build.rs @@ -0,0 +1,11 @@ +//! Compile Rust code from gRPC definition files stored in the vendor/csi directory. + +use std::path::PathBuf; + +fn main() { + let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR is required")); + tonic_build::configure() + .file_descriptor_set_path(out_dir.join("file_descriptor_set.bin")) + .compile(&["csi.proto"], &["vendor/csi"]) + .unwrap(); +} diff --git a/rust/operator-binary/src/grpc.rs b/rust/csi-grpc/src/lib.rs similarity index 79% rename from rust/operator-binary/src/grpc.rs rename to rust/csi-grpc/src/lib.rs index 7a59f196..d6adb506 100644 --- a/rust/operator-binary/src/grpc.rs +++ b/rust/csi-grpc/src/lib.rs @@ -5,8 +5,6 @@ pub static FILE_DESCRIPTOR_SET_BYTES: &[u8] = // Trivial warnings that come from prost-generated code #[allow(clippy::derive_partial_eq_without_eq)] -pub mod csi { - pub mod v1 { - tonic::include_proto!("csi.v1"); - } +pub mod v1 { + tonic::include_proto!("csi.v1"); } diff --git a/rust/operator-binary/vendor/csi b/rust/csi-grpc/vendor/csi similarity index 100% rename from rust/operator-binary/vendor/csi rename to rust/csi-grpc/vendor/csi diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 7f9c01de..b27af4e5 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -16,7 +16,6 @@ futures = "0.3.21" libc = "0.2.125" pin-project = "1.0.10" prost = "0.10.3" -prost-types = "0.10.1" socket2 = { version = "0.4.4", features = ["all"] } stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.25.0" } tokio = { version = "1.18.2", features = ["full"] } @@ -27,7 +26,7 @@ anyhow = "1.0.57" serde = "1.0.137" snafu = "0.7.1" strum = "0.24.1" +csi-grpc = { path = "../csi-grpc" } [build-dependencies] built = { version = "0.5.1", features = ["chrono", "git2"] } -tonic-build = "0.7.2" diff --git a/rust/operator-binary/build.rs b/rust/operator-binary/build.rs index 5c3870d1..ed36fcf0 100644 --- a/rust/operator-binary/build.rs +++ b/rust/operator-binary/build.rs @@ -1,13 +1,7 @@ -//! Compile Rust code from gRPC definition files stored in the vendor/csi directory. - use std::path::PathBuf; fn main() { let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR is required")); - tonic_build::configure() - .file_descriptor_set_path(out_dir.join("file_descriptor_set.bin")) - .compile(&["csi.proto"], &["vendor/csi"]) - .unwrap(); built::write_built_file_with_opts( // built's env module depends on a whole bunch of variables that crate2nix doesn't provide // so we grab the specific env variables that we care about out ourselves instead. diff --git a/rust/operator-binary/src/crd.rs b/rust/operator-binary/src/crd.rs deleted file mode 100644 index 8b137891..00000000 --- a/rust/operator-binary/src/crd.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rust/operator-binary/src/csi_server/controller.rs b/rust/operator-binary/src/csi_server/controller.rs index eddce75f..1b03dfe9 100644 --- a/rust/operator-binary/src/csi_server/controller.rs +++ b/rust/operator-binary/src/csi_server/controller.rs @@ -1,3 +1,4 @@ +use csi_grpc as csi; use serde::{de::IntoDeserializer, Deserialize}; use snafu::{OptionExt, ResultExt, Snafu}; use stackable_operator::{ @@ -7,7 +8,7 @@ use stackable_operator::{ }; use tonic::{Request, Response, Status}; -use crate::{grpc::csi, utils::error_full_message}; +use crate::utils::error_full_message; use super::{tonic_unimplemented, ListenerSelector, ListenerVolumeContext}; diff --git a/rust/operator-binary/src/csi_server/identity.rs b/rust/operator-binary/src/csi_server/identity.rs index 595cfeea..6d9ba72e 100644 --- a/rust/operator-binary/src/csi_server/identity.rs +++ b/rust/operator-binary/src/csi_server/identity.rs @@ -1,9 +1,10 @@ use std::collections::HashMap; use clap::crate_version; +use csi_grpc as csi; use tonic::{Request, Response, Status}; -use crate::{grpc::csi, OPERATOR_KEY}; +use crate::OPERATOR_KEY; pub struct ListenerOperatorIdentity; diff --git a/rust/operator-binary/src/csi_server/node.rs b/rust/operator-binary/src/csi_server/node.rs index 4fb9aec3..7db1dec5 100644 --- a/rust/operator-binary/src/csi_server/node.rs +++ b/rust/operator-binary/src/csi_server/node.rs @@ -1,5 +1,6 @@ use std::{fmt::Debug, path::PathBuf}; +use csi_grpc::{self as csi, v1::Topology}; use serde::{ de::{DeserializeOwned, IntoDeserializer}, Deserialize, @@ -17,10 +18,7 @@ use stackable_operator::{ }; use tonic::{Request, Response, Status}; -use crate::{ - grpc::csi::{self, v1::Topology}, - utils::{error_full_message, node_primary_address}, -}; +use crate::utils::{error_full_message, node_primary_address}; use super::{tonic_unimplemented, ListenerSelector, ListenerVolumeContext}; diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index ef1f1cb2..eaf1633f 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -1,14 +1,14 @@ use std::{os::unix::prelude::FileTypeExt, path::PathBuf}; use clap::{crate_description, crate_version, Parser}; +use csi_grpc::v1::{ + controller_server::ControllerServer, identity_server::IdentityServer, node_server::NodeServer, +}; use csi_server::{ controller::ListenerOperatorController, identity::ListenerOperatorIdentity, node::ListenerOperatorNode, }; use futures::{pin_mut, FutureExt, TryStreamExt}; -use grpc::csi::v1::{ - controller_server::ControllerServer, identity_server::IdentityServer, node_server::NodeServer, -}; use stackable_operator::{ commons::listener::{Listener, ListenerClass}, logging::TracingTarget, @@ -20,7 +20,6 @@ use tonic::transport::Server; use utils::{uds_bind_private, TonicUnixStream}; mod csi_server; -mod grpc; mod listener_controller; mod utils; @@ -99,7 +98,7 @@ async fn main() -> anyhow::Result<()> { .add_service( tonic_reflection::server::Builder::configure() .include_reflection_service(true) - .register_encoded_file_descriptor_set(grpc::FILE_DESCRIPTOR_SET_BYTES) + .register_encoded_file_descriptor_set(csi_grpc::FILE_DESCRIPTOR_SET_BYTES) .build()?, ) .add_service(IdentityServer::new(ListenerOperatorIdentity)); From f1bf0c4d551b393f96c9f967d684eaa587f7ad58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 23 Sep 2022 13:13:20 +0200 Subject: [PATCH 87/99] Use released operator-rs 0.25.1 --- Cargo.lock | 8 ++++---- Cargo.toml | 4 ++-- rust/operator-binary/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05c2f117..e4765625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1920,8 +1920,8 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.25.0" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=main#4ec1567f9ef27bff20a43c7fab6a9aa05c4e2591" +version = "0.25.1" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.25.1#7e85e965623557def1e89a9be30df2b2a7220632" dependencies = [ "chrono", "clap", @@ -1953,8 +1953,8 @@ dependencies = [ [[package]] name = "stackable-operator-derive" -version = "0.25.0" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=main#4ec1567f9ef27bff20a43c7fab6a9aa05c4e2591" +version = "0.25.1" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.25.1#7e85e965623557def1e89a9be30df2b2a7220632" dependencies = [ "darling", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index f2d62b4c..d1b4fda7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,6 @@ members = ["rust/operator-binary", "rust/csi-grpc"] # Workaround for https://github.com/hyperium/tonic/issues/243 h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } -[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 = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" } # stackable-operator = { path = "../operator-rs" } diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index b27af4e5..0c5dee9b 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -17,7 +17,7 @@ libc = "0.2.125" pin-project = "1.0.10" prost = "0.10.3" socket2 = { version = "0.4.4", features = ["all"] } -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.25.0" } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.25.1" } tokio = { version = "1.18.2", features = ["full"] } tokio-stream = { version = "0.1.8", features = ["net"] } tonic = "0.7.2" From 240992aca3b2e81f9c14339779be64d93e43471e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 23 Sep 2022 13:13:29 +0200 Subject: [PATCH 88/99] Fix clippy warning --- rust/operator-binary/src/listener_controller.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/operator-binary/src/listener_controller.rs b/rust/operator-binary/src/listener_controller.rs index 103f3c39..1b25e930 100644 --- a/rust/operator-binary/src/listener_controller.rs +++ b/rust/operator-binary/src/listener_controller.rs @@ -262,7 +262,7 @@ pub async fn reconcile( }) .collect(), ), - node_ports: (listener_class.spec.service_type == ServiceType::NodePort).then(|| ports), + node_ports: (listener_class.spec.service_type == ServiceType::NodePort).then_some(ports), }; ctx.client .apply_patch_status(FIELD_MANAGER_SCOPE, &listener_status_meta, &listener_status) From 0c10c8b6f3f42649dc3e05cc6947fdb8caeeddbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 23 Sep 2022 13:30:03 +0200 Subject: [PATCH 89/99] Might as well satisfy nightly clippy too --- rust/operator-binary/src/csi_server/node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/operator-binary/src/csi_server/node.rs b/rust/operator-binary/src/csi_server/node.rs index 7db1dec5..29e1a558 100644 --- a/rust/operator-binary/src/csi_server/node.rs +++ b/rust/operator-binary/src/csi_server/node.rs @@ -333,7 +333,7 @@ mod pod_dir { tokio::fs::symlink( default_addr_dir .context(NoDefaultAddressSnafu)? - .strip_prefix(&target_path) + .strip_prefix(target_path) .context(DefaultAddrIsOutsideRootSnafu)?, target_path.join("default-address"), ) From ad2511ca17a54104d7c0fa96ad74db41a51d3793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Fri, 23 Sep 2022 17:28:18 +0200 Subject: [PATCH 90/99] Add our own label rather than reusing the pod's existing labels This avoids problems when the Pod doesn't have any labels (or those labels aren't sufficiently unique). It also encourages users to mount their listeners into their pods, even when using pre-provisioned listeners. --- Cargo.lock | 4 +-- Cargo.toml | 4 +-- rust/operator-binary/src/csi_server/node.rs | 34 +++++++++++++++++-- .../src/listener_controller.rs | 24 +++++++++++-- 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4765625..358d6dd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1921,7 +1921,7 @@ dependencies = [ [[package]] name = "stackable-operator" version = "0.25.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.25.1#7e85e965623557def1e89a9be30df2b2a7220632" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feature/listener-implied-labels#8444e699ca75980b839c9159ece8a1651ed0125f" dependencies = [ "chrono", "clap", @@ -1954,7 +1954,7 @@ dependencies = [ [[package]] name = "stackable-operator-derive" version = "0.25.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.25.1#7e85e965623557def1e89a9be30df2b2a7220632" +source = "git+https://github.com/stackabletech//operator-rs.git?branch=feature/listener-implied-labels#8444e699ca75980b839c9159ece8a1651ed0125f" dependencies = [ "darling", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index d1b4fda7..976fd87e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,6 @@ members = ["rust/operator-binary", "rust/csi-grpc"] # Workaround for https://github.com/hyperium/tonic/issues/243 h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } -# [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 = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feature/listener-implied-labels" } # stackable-operator = { path = "../operator-rs" } diff --git a/rust/operator-binary/src/csi_server/node.rs b/rust/operator-binary/src/csi_server/node.rs index 29e1a558..b728d8c4 100644 --- a/rust/operator-binary/src/csi_server/node.rs +++ b/rust/operator-binary/src/csi_server/node.rs @@ -18,7 +18,10 @@ use stackable_operator::{ }; use tonic::{Request, Response, Status}; -use crate::utils::{error_full_message, node_primary_address}; +use crate::{ + listener_controller::listener_mounted_pod_label, + utils::{error_full_message, node_primary_address}, +}; use super::{tonic_unimplemented, ListenerSelector, ListenerVolumeContext}; @@ -60,6 +63,11 @@ enum PublishVolumeError { source: stackable_operator::error::Error, listener: ObjectRef, }, + #[snafu(display("failed to add listener label to {pod}"))] + AddListenerLabelToPod { + source: stackable_operator::error::Error, + pod: ObjectRef, + }, #[snafu(display("failed to prepare pod dir at {target_path:?}"))] PreparePodDir { source: pod_dir::Error, @@ -77,6 +85,7 @@ impl From for Status { PublishVolumeError::PodHasNoNode { .. } => Status::unavailable(full_msg), PublishVolumeError::BuildListenerOwnerRef { .. } => Status::unavailable(full_msg), PublishVolumeError::ApplyListener { .. } => Status::unavailable(full_msg), + PublishVolumeError::AddListenerLabelToPod { .. } => Status::unavailable(full_msg), PublishVolumeError::PreparePodDir { .. } => Status::internal(full_msg), } } @@ -198,7 +207,8 @@ impl csi::v1::node_server::Node for ListenerOperatorNode { }) .collect(), ), - pod_selector: pod.metadata.labels.clone(), + publish_not_ready_addresses: Some(true), + ..Default::default() }, status: None, }; @@ -211,6 +221,26 @@ impl csi::v1::node_server::Node for ListenerOperatorNode { } }; + // Add listener label to pod so that traffic can be directed to it + self.client + // IMPORTANT + // Use a merge patch rather than an apply so that we don't delete labels added by other listener volumes. + // Volumes aren't hot-swappable anyway, and all labels will be removed when the pod is deleted. + .merge_patch( + &pod, + &Pod { + metadata: ObjectMeta { + labels: Some([listener_mounted_pod_label(&listener)].into()), + ..Default::default() + }, + ..Default::default() + }, + ) + .await + .with_context(|_| AddListenerLabelToPodSnafu { + pod: ObjectRef::from_obj(&pod), + })?; + // Prefer calculating a per-node address where possible, to ensure that the address at least tries to // connect to the pod in question. // We also can't rely on `ingress_addresses` being set yet, since the pod won't have an IP address yet diff --git a/rust/operator-binary/src/listener_controller.rs b/rust/operator-binary/src/listener_controller.rs index 1b25e930..0e9d5497 100644 --- a/rust/operator-binary/src/listener_controller.rs +++ b/rust/operator-binary/src/listener_controller.rs @@ -148,6 +148,8 @@ pub async fn reconcile( // Deduplicate ports by (protocol, name) .collect::>(); let svc_name = listener.metadata.name.clone().context(NoNameSnafu)?; + let mut pod_selector = listener.spec.extra_pod_selector_labels.clone(); + pod_selector.extend([listener_mounted_pod_label(&listener)]); let svc = Service { metadata: ObjectMeta { namespace: Some(ns.clone()), @@ -165,8 +167,13 @@ pub async fn reconcile( }), ports: Some(pod_ports.into_values().collect()), external_traffic_policy: Some("Local".to_string()), - selector: listener.spec.pod_selector.clone(), - publish_not_ready_addresses: Some(true), + selector: Some(pod_selector), + publish_not_ready_addresses: Some( + listener + .spec + .publish_not_ready_addresses + .unwrap_or_default(), + ), ..Default::default() }), ..Default::default() @@ -275,3 +282,16 @@ pub async fn reconcile( pub fn error_policy(_err: &Error, _ctx: Arc) -> controller::Action { controller::Action::requeue(Duration::from_secs(5)) } + +/// A label that identifies [`Pod`]s that have mounted `listener` +/// +/// Listener-Op's CSI Node driver is responsible for adding this to the relevant [`Pod`]s. +pub fn listener_mounted_pod_label(listener: &Listener) -> (String, String) { + ( + format!( + "listeners.stackable.tech/mounted-listener.{}", + listener.metadata.name.as_deref().unwrap_or_default() + ), + "true".to_string(), + ) +} From f33a6ec5b6d99c275e86d3c82d20aa685691dd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Mon, 26 Sep 2022 12:51:53 +0200 Subject: [PATCH 91/99] Preprovisioned listeners are supported now --- Tiltfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Tiltfile b/Tiltfile index 85c36c2f..65793a21 100644 --- a/Tiltfile +++ b/Tiltfile @@ -30,5 +30,4 @@ k8s_yaml(helm_non_crds) # Load examples k8s_yaml('examples/nginx-nodeport.yaml') k8s_yaml('examples/nginx-lb.yaml') -# use case currently broken... k8s_yaml('examples/nginx-preprovisioned-lb.yaml') From 3e4c595a9574d983839f8696fd880385861d108e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 27 Sep 2022 15:50:04 +0200 Subject: [PATCH 92/99] Use operator-rs 0.25.2, regenerate manifests --- Cargo.lock | 8 +-- Cargo.toml | 2 +- deploy/helm/listener-operator/crds/crds.yaml | 13 +++-- deploy/manifests/controller-deployment.yaml | 53 +++++++++++++++++++ deploy/manifests/crds.yaml | 13 +++-- deploy/manifests/deployment.yaml | 3 -- .../{daemonset.yaml => node-daemonset.yaml} | 16 +++--- rust/operator-binary/Cargo.toml | 2 +- 8 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 deploy/manifests/controller-deployment.yaml delete mode 100644 deploy/manifests/deployment.yaml rename deploy/manifests/{daemonset.yaml => node-daemonset.yaml} (86%) diff --git a/Cargo.lock b/Cargo.lock index 358d6dd0..eee05957 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1920,8 +1920,8 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.25.1" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feature/listener-implied-labels#8444e699ca75980b839c9159ece8a1651ed0125f" +version = "0.25.2" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.25.2#ef41dc96071665ce99b35e8090c8df3ef89e9616" dependencies = [ "chrono", "clap", @@ -1953,8 +1953,8 @@ dependencies = [ [[package]] name = "stackable-operator-derive" -version = "0.25.1" -source = "git+https://github.com/stackabletech//operator-rs.git?branch=feature/listener-implied-labels#8444e699ca75980b839c9159ece8a1651ed0125f" +version = "0.25.2" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.25.2#ef41dc96071665ce99b35e8090c8df3ef89e9616" dependencies = [ "darling", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 976fd87e..63156300 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,5 @@ members = ["rust/operator-binary", "rust/csi-grpc"] h2 = { git = "https://github.com/stackabletech/h2.git", branch = "feature/grpc-uds" } [patch."https://github.com/stackabletech/operator-rs.git"] -stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feature/listener-implied-labels" } +# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feature/listener-implied-labels" } # stackable-operator = { path = "../operator-rs" } diff --git a/deploy/helm/listener-operator/crds/crds.yaml b/deploy/helm/listener-operator/crds/crds.yaml index ad569a7f..d6e132e5 100644 --- a/deploy/helm/listener-operator/crds/crds.yaml +++ b/deploy/helm/listener-operator/crds/crds.yaml @@ -73,17 +73,17 @@ spec: description: |- Exposes a set of pods to the outside world. - Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service + Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service 3. The [`Pod`] must mount a [`Volume`] referring to the `Listener`, which also allows us to control stickiness properties: className: description: The name of the [`ListenerClass`]. nullable: true type: string - podSelector: + extraPodSelectorLabels: additionalProperties: type: string - description: Labels that the [`Pod`]s must share in order to be exposed. - nullable: true + default: {} + description: Extra labels that the [`Pod`]s must match in order to be exposed. They must _also_ still have a `Volume` referring to the listener. type: object ports: description: Ports that should be exposed. @@ -109,6 +109,11 @@ spec: type: object nullable: true type: array + publishNotReadyAddresses: + default: true + description: Whether incoming traffic should also be directed to `Pod`s that are not `Ready`. + nullable: true + type: boolean type: object status: description: Informs users about how to reach the [`Listener`]. diff --git a/deploy/manifests/controller-deployment.yaml b/deploy/manifests/controller-deployment.yaml new file mode 100644 index 00000000..a9f55676 --- /dev/null +++ b/deploy/manifests/controller-deployment.yaml @@ -0,0 +1,53 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: listener-operator-controller-deployment + labels: + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator + app.kubernetes.io/version: "0.1.0-nightly" +spec: + selector: + matchLabels: + app.kubernetes.io/role: controller + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator + template: + metadata: + labels: + app.kubernetes.io/role: controller + app.kubernetes.io/name: listener-operator + app.kubernetes.io/instance: listener-operator + spec: + serviceAccountName: listener-operator-serviceaccount + securityContext: {} + containers: + - name: listener-operator + securityContext: + privileged: true + runAsUser: 0 + image: "docker.stackable.tech/stackable/listener-operator:0.1.0-nightly" + imagePullPolicy: IfNotPresent + resources: {} + args: + - run + - controller + env: + - name: CSI_ENDPOINT + value: /csi/csi.sock + volumeMounts: + - name: csi + mountPath: /csi + - name: external-provisioner + image: k8s.gcr.io/sig-storage/csi-provisioner:v3.1.0 + args: + - --csi-address=/csi/csi.sock + - --feature-gates=Topology=true + - --extra-create-metadata + volumeMounts: + - name: csi + mountPath: /csi + volumes: + - name: csi + emptyDir: {} diff --git a/deploy/manifests/crds.yaml b/deploy/manifests/crds.yaml index 8b305d6a..49a0890f 100644 --- a/deploy/manifests/crds.yaml +++ b/deploy/manifests/crds.yaml @@ -74,17 +74,17 @@ spec: description: |- Exposes a set of pods to the outside world. - Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service + Essentially a Stackable extension of a Kubernetes [`Service`]. Compared to [`Service`], [`Listener`] changes two things: 1. It uses a cluster-level policy object ([`ListenerClass`]) to define how exactly the exposure works 2. It has a consistent API for reading back the exposed address(es) of the service 3. The [`Pod`] must mount a [`Volume`] referring to the `Listener`, which also allows us to control stickiness properties: className: description: The name of the [`ListenerClass`]. nullable: true type: string - podSelector: + extraPodSelectorLabels: additionalProperties: type: string - description: Labels that the [`Pod`]s must share in order to be exposed. - nullable: true + default: {} + description: Extra labels that the [`Pod`]s must match in order to be exposed. They must _also_ still have a `Volume` referring to the listener. type: object ports: description: Ports that should be exposed. @@ -110,6 +110,11 @@ spec: type: object nullable: true type: array + publishNotReadyAddresses: + default: true + description: Whether incoming traffic should also be directed to `Pod`s that are not `Ready`. + nullable: true + type: boolean type: object status: description: Informs users about how to reach the [`Listener`]. diff --git a/deploy/manifests/deployment.yaml b/deploy/manifests/deployment.yaml deleted file mode 100644 index 0892575e..00000000 --- a/deploy/manifests/deployment.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -# Templated Deployment disabled for this operator - diff --git a/deploy/manifests/daemonset.yaml b/deploy/manifests/node-daemonset.yaml similarity index 86% rename from deploy/manifests/daemonset.yaml rename to deploy/manifests/node-daemonset.yaml index 402b072c..9b08a38a 100644 --- a/deploy/manifests/daemonset.yaml +++ b/deploy/manifests/node-daemonset.yaml @@ -2,7 +2,7 @@ apiVersion: apps/v1 kind: DaemonSet metadata: - name: listener-operator-daemonset + name: listener-operator-node-daemonset labels: app.kubernetes.io/name: listener-operator app.kubernetes.io/instance: listener-operator @@ -10,11 +10,13 @@ metadata: spec: selector: matchLabels: + app.kubernetes.io/role: node app.kubernetes.io/name: listener-operator app.kubernetes.io/instance: listener-operator template: metadata: labels: + app.kubernetes.io/role: node app.kubernetes.io/name: listener-operator app.kubernetes.io/instance: listener-operator spec: @@ -28,6 +30,9 @@ spec: image: "docker.stackable.tech/stackable/listener-operator:0.1.0-nightly" imagePullPolicy: IfNotPresent resources: {} + args: + - run + - node env: - name: CSI_ENDPOINT value: /csi/csi.sock @@ -42,15 +47,6 @@ spec: - name: mountpoint mountPath: /var/lib/kubelet/pods mountPropagation: Bidirectional - - name: external-provisioner - image: k8s.gcr.io/sig-storage/csi-provisioner:v3.1.0 - args: - - --csi-address=/csi/csi.sock - - --feature-gates=Topology=true - - --extra-create-metadata - volumeMounts: - - name: csi - mountPath: /csi - name: node-driver-registrar image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0 args: diff --git a/rust/operator-binary/Cargo.toml b/rust/operator-binary/Cargo.toml index 0c5dee9b..cddd132f 100644 --- a/rust/operator-binary/Cargo.toml +++ b/rust/operator-binary/Cargo.toml @@ -17,7 +17,7 @@ libc = "0.2.125" pin-project = "1.0.10" prost = "0.10.3" socket2 = { version = "0.4.4", features = ["all"] } -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.25.1" } +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.25.2" } tokio = { version = "1.18.2", features = ["full"] } tokio-stream = { version = "0.1.8", features = ["net"] } tonic = "0.7.2" From 60b9a8e1f8b353974e3c9fafba57d782cc3e29e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 27 Sep 2022 16:00:59 +0200 Subject: [PATCH 93/99] Fix example pod indentation --- docs/modules/ROOT/examples/usage-pod.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/examples/usage-pod.yaml b/docs/modules/ROOT/examples/usage-pod.yaml index 9e316110..0c252a7a 100644 --- a/docs/modules/ROOT/examples/usage-pod.yaml +++ b/docs/modules/ROOT/examples/usage-pod.yaml @@ -22,8 +22,8 @@ spec: - name: nginx image: nginx ports: - - name: http - containerPort: 80 + - name: http + containerPort: 80 volumeMounts: - name: listener mountPath: /listener # <3> From 6c2b5b1180f4f72ebcfb44eba593d596272de64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 27 Sep 2022 16:01:32 +0200 Subject: [PATCH 94/99] Remove secrets permission properly this time --- deploy/helm/listener-operator/templates/roles.yaml | 1 - deploy/manifests/roles.yaml | 1 - 2 files changed, 2 deletions(-) diff --git a/deploy/helm/listener-operator/templates/roles.yaml b/deploy/helm/listener-operator/templates/roles.yaml index 40c4ef76..631764af 100644 --- a/deploy/helm/listener-operator/templates/roles.yaml +++ b/deploy/helm/listener-operator/templates/roles.yaml @@ -7,7 +7,6 @@ rules: - apiGroups: - "" resources: - - secrets - events - services verbs: diff --git a/deploy/manifests/roles.yaml b/deploy/manifests/roles.yaml index 95830fee..a5896c90 100644 --- a/deploy/manifests/roles.yaml +++ b/deploy/manifests/roles.yaml @@ -7,7 +7,6 @@ rules: - apiGroups: - "" resources: - - secrets - events - services verbs: From 828ac4cb90f6da8169fea0a177b08b9c12570589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 27 Sep 2022 16:02:49 +0200 Subject: [PATCH 95/99] Burninate CLI docs page --- docs/modules/ROOT/nav.adoc | 1 - docs/modules/ROOT/pages/commandline_args.adoc | 20 ------------------- docs/modules/ROOT/pages/configuration.adoc | 6 ------ 3 files changed, 27 deletions(-) delete mode 100644 docs/modules/ROOT/pages/commandline_args.adoc delete mode 100644 docs/modules/ROOT/pages/configuration.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index c51c0241..35262ec2 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -1,6 +1,5 @@ * xref:building.adoc[] * xref:installation.adoc[] -* xref:configuration.adoc[] * xref:usage.adoc[] * Concepts ** xref:listener.adoc[] diff --git a/docs/modules/ROOT/pages/commandline_args.adoc b/docs/modules/ROOT/pages/commandline_args.adoc deleted file mode 100644 index 64917581..00000000 --- a/docs/modules/ROOT/pages/commandline_args.adoc +++ /dev/null @@ -1,20 +0,0 @@ -=== --csi-endpoint - -*Required*: true - -*Multiple values*: false - -*Environment variable:* `CSI_ENDPOINT` - -The path to the https://github.com/container-storage-interface/spec/blob/master/spec.md[Container Storage Interface] Unix Domain Socket -that the operator should listen on. - -=== --node-name - -*Required*: true - -*Multiple values*: false - -*Environment variable*: `NODE_NAME` - -The name of the Kubernetes `Node` that this `Pod` is running on. diff --git a/docs/modules/ROOT/pages/configuration.adoc b/docs/modules/ROOT/pages/configuration.adoc deleted file mode 100644 index c347061a..00000000 --- a/docs/modules/ROOT/pages/configuration.adoc +++ /dev/null @@ -1,6 +0,0 @@ -= Configuration - -== Command Line Parameters -This operator accepts the following command line parameters: - -include::commandline_args.adoc[] From 41086e9fcfc1c348db1e463d8533b0cab863c4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 27 Sep 2022 16:07:39 +0200 Subject: [PATCH 96/99] Add crate metadata for csi-grpc --- Cargo.lock | 2 +- rust/csi-grpc/Cargo.toml | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eee05957..dfd7ec99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -356,7 +356,7 @@ dependencies = [ [[package]] name = "csi-grpc" -version = "0.1.0" +version = "0.1.0-nightly" dependencies = [ "built", "prost", diff --git a/rust/csi-grpc/Cargo.toml b/rust/csi-grpc/Cargo.toml index 192f0dd7..6b14c4a9 100644 --- a/rust/csi-grpc/Cargo.toml +++ b/rust/csi-grpc/Cargo.toml @@ -1,7 +1,11 @@ [package] name = "csi-grpc" -version = "0.1.0" +authors = ["Stackable GmbH "] +description = "Rust bindings for the CSI GRPC API" +license = "OSL-3.0" +version = "0.1.0-nightly" edition = "2021" +repository = "https://github.com/stackabletech/listener-operator" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 639cfd2c159a587c51484c4a471758fd2b6ccf7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 27 Sep 2022 16:09:11 +0200 Subject: [PATCH 97/99] Add docs import to listener_controller --- rust/operator-binary/src/listener_controller.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rust/operator-binary/src/listener_controller.rs b/rust/operator-binary/src/listener_controller.rs index 0e9d5497..62c7f5af 100644 --- a/rust/operator-binary/src/listener_controller.rs +++ b/rust/operator-binary/src/listener_controller.rs @@ -17,6 +17,9 @@ use stackable_operator::{ use std::{collections::BTreeMap, sync::Arc, time::Duration}; use strum::IntoStaticStr; +#[cfg(doc)] +use stackable_operator::k8s_openapi::api::core::v1::Pod; + const FIELD_MANAGER_SCOPE: &str = "listener"; pub async fn run(client: stackable_operator::client::Client) { From 22073137e3ef8f7c202f2f83e5128a23e3a7308f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Tue, 27 Sep 2022 16:29:39 +0200 Subject: [PATCH 98/99] Drop unused csi-grpc dependency on built --- Cargo.lock | 1 - rust/csi-grpc/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dfd7ec99..1cc66094 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,7 +358,6 @@ dependencies = [ name = "csi-grpc" version = "0.1.0-nightly" dependencies = [ - "built", "prost", "prost-types", "tonic", diff --git a/rust/csi-grpc/Cargo.toml b/rust/csi-grpc/Cargo.toml index 6b14c4a9..cf760c91 100644 --- a/rust/csi-grpc/Cargo.toml +++ b/rust/csi-grpc/Cargo.toml @@ -15,5 +15,4 @@ prost-types = "0.10.1" tonic = "0.7.2" [build-dependencies] -built = { version = "0.5.1", features = ["chrono", "git2"] } tonic-build = "0.7.2" \ No newline at end of file From 84032850482e3a1851d631467cf7f9c968f0389e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teo=20Klestrup=20R=C3=B6ijezon?= Date: Wed, 28 Sep 2022 14:59:52 +0200 Subject: [PATCH 99/99] Relicense csi-grpc as Apache 2.0 --- rust/csi-grpc/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/csi-grpc/Cargo.toml b/rust/csi-grpc/Cargo.toml index cf760c91..341a3507 100644 --- a/rust/csi-grpc/Cargo.toml +++ b/rust/csi-grpc/Cargo.toml @@ -2,7 +2,7 @@ name = "csi-grpc" authors = ["Stackable GmbH "] description = "Rust bindings for the CSI GRPC API" -license = "OSL-3.0" +license = "Apache-2.0" version = "0.1.0-nightly" edition = "2021" repository = "https://github.com/stackabletech/listener-operator"