diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 7db1cfc..f10545c 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -37,6 +37,6 @@ jobs: steps: - uses: actions/checkout@v7 - name: Install Helm unittest plugin - run: helm plugin install https://github.com/helm-unittest/helm-unittest.git + run: helm plugin install https://github.com/helm-unittest/helm-unittest.git --verify=false - name: Run Helm unittests run: helm unittest helm diff --git a/Cargo.lock b/Cargo.lock index 23408e0..dd54f55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -169,6 +169,29 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "aws-lc-rs" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048006790404103c488e6c5616b3e7e702a71292aadda08e8f7698a9e0d2eb53" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bfbe32ac36b3c428696ce315464181bc4029d689fd58e3f2a4e58c252242f52" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", + "pkg-config", +] + [[package]] name = "backon" version = "1.6.0" @@ -232,6 +255,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375989decec1a0fa424442bed520fa12ede43a48475ce8c7417d2c69b32b5f6b" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -241,6 +266,23 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.1", +] + [[package]] name = "chrono" version = "0.4.45" @@ -293,6 +335,15 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.5" @@ -309,16 +360,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -341,6 +382,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "darling" version = "0.24.1" @@ -453,6 +503,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -580,21 +636,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" -[[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.2.2" @@ -604,6 +645,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.34" @@ -699,8 +746,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -724,8 +773,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 6.0.0", + "rand_core 0.10.1", + "wasm-bindgen", ] [[package]] @@ -794,10 +846,11 @@ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hcloud" -version = "0.26.0" -source = "git+https://github.com/pando85/hcloud-rust?branch=v0.26.0-fix-deprecated#d749231bba9af888a768a106f3167bcc69a197ea" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a824dda64941aa56ea27a2b834467ea9b84230f8eae843f5c160b26736c6b396" dependencies = [ - "reqwest 0.12.28", + "reqwest", "serde", "serde_json", "serde_with", @@ -925,22 +978,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.21" @@ -960,11 +997,9 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2", - "system-configuration", "tokio", "tower-service", "tracing", - "windows-registry", ] [[package]] @@ -1254,6 +1289,16 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "jobserver" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + [[package]] name = "js-sys" version = "0.3.107" @@ -1432,12 +1477,6 @@ version = "0.2.191" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - [[package]] name = "litemap" version = "0.8.3" @@ -1459,6 +1498,12 @@ version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d15f86d12da44cd8d4ec3c73984537eb7f4cadcb9776a575a0a8a05ca11005c" +[[package]] +name = "lru-slab" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" + [[package]] name = "matchers" version = "0.2.0" @@ -1507,23 +1552,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d" -[[package]] -name = "native-tls" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -1566,49 +1594,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "openssl" -version = "0.10.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4de8111e94a56adca7ebfe6c365b6d42f99deb69b74b6becacd4204e2f193aa2" -dependencies = [ - "bitflags 2.13.2", - "cfg-if", - "foreign-types", - "libc", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "openssl-probe" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e036b411754132fd6b74e94b74e9a13c5cf606fa93d1885c35860d3060820b1" -[[package]] -name = "openssl-sys" -version = "0.9.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c413d6ec9ebaf5e1c829d355cb3e9f783778d700f135be0921d52fce3c60ae" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "opentelemetry" version = "0.33.1" @@ -1633,7 +1624,7 @@ dependencies = [ "bytes", "http", "opentelemetry", - "reqwest 0.13.5", + "reqwest", ] [[package]] @@ -1649,7 +1640,7 @@ dependencies = [ "opentelemetry-proto", "opentelemetry_sdk", "prost", - "reqwest 0.13.5", + "reqwest", "thiserror 2.0.21", "tokio", "tonic", @@ -1687,7 +1678,7 @@ dependencies = [ "opentelemetry", "percent-encoding", "portable-atomic", - "rand", + "rand 0.9.5", "thiserror 2.0.21", "tokio", "tokio-stream", @@ -1921,6 +1912,63 @@ dependencies = [ "cc", ] +[[package]] +name = "quinn" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4051e23e9185c255a7e33ef59cdbca87a22d359052eecd22fc6b901fb37d9d11" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.21", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e750cca55fe4f0439a15d0bb529da9651e79993e8e72c61a899a36d462befbe" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.4.3", + "lru-slab", + "rand 0.10.3", + "rand_pcg", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.21", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af66907df18639dcf4db56ca65490cabc4b27a97dbadd96f2926cca73298f016" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.61.2", +] + [[package]] name = "quote" version = "1.0.47" @@ -1949,7 +1997,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -1959,7 +2018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", ] [[package]] @@ -1971,6 +2030,21 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -2031,68 +2105,36 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.12.28" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bytes", - "encoding_rs", + "futures-channel", "futures-core", "futures-util", - "h2", "http", "http-body", "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", - "mime", "mime_guess", - "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", - "tower", - "tower-http 0.6.11", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "reqwest" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" -dependencies = [ - "base64 0.23.1", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "sync_wrapper", - "tokio", + "tokio-rustls", "tower", "tower-http 0.6.11", "tower-service", @@ -2145,6 +2187,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -2154,25 +2202,13 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5e76742e5294153d4dde1207dbec5bdd81eef6fabdc0d2118babadabfd858aa" -dependencies = [ - "bitflags 2.13.2", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - [[package]] name = "rustls" version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -2200,6 +2236,7 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ + "web-time", "zeroize", ] @@ -2209,7 +2246,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98" dependencies = [ - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "jni", "log", @@ -2236,6 +2273,7 @@ version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -2317,7 +2355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.13.2", - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -2592,40 +2630,6 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "system-configuration" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" -dependencies = [ - "bitflags 2.13.2", - "core-foundation 0.9.4", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom 0.4.3", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -2768,16 +2772,6 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.6" @@ -3097,12 +3091,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[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.5" @@ -3277,17 +3265,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" -dependencies = [ - "windows-link", - "windows-result", - "windows-strings", -] - [[package]] name = "windows-result" version = "0.4.1" @@ -3508,3 +3485,8 @@ name = "zmij" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[patch.unused]] +name = "hcloud" +version = "0.26.0" +source = "git+https://github.com/pando85/hcloud-rust?branch=v0.26.0-fix-deprecated#d749231bba9af888a768a106f3167bcc69a197ea" diff --git a/Cargo.toml b/Cargo.toml index e23c211..69fa7d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ async-trait = "0.1.89" clap = { version = "4.5.21", features = ["derive", "env"] } dotenvy = "0.15.7" futures = "0.3.31" -hcloud = "0.26.0" +hcloud = "0.27.0" http-body-util = "0.1" hyper = { version = "1.6", features = ["server", "http1"] } hyper-util = { version = "0.1", features = ["tokio"] } diff --git a/src/controller/status.rs b/src/controller/status.rs index 6739e0b..16d5543 100644 --- a/src/controller/status.rs +++ b/src/controller/status.rs @@ -25,19 +25,17 @@ pub fn build_ingress( if !public_interface { for private_net in &hcloud_lb.private_net { - if let Some(ip) = &private_net.ip { - ingress.push(LoadBalancerIngress { - ip: Some(ip.clone()), - ip_mode: Some(ip_mode.to_string()), - ..Default::default() - }); - } + ingress.push(LoadBalancerIngress { + ip: Some(private_net.ip.clone()), + ip_mode: Some(ip_mode.to_string()), + ..Default::default() + }); } return ingress; } - let ipv4 = hcloud_lb.public_net.ipv4.ip.clone().flatten(); - let ipv6 = hcloud_lb.public_net.ipv6.ip.clone().flatten(); + let ipv4 = hcloud_lb.public_net.ipv4.ip.clone(); + let ipv6 = hcloud_lb.public_net.ipv6.ip.clone(); if let Some(ipv4) = &ipv4 { ingress.push(LoadBalancerIngress { @@ -115,17 +113,21 @@ mod tests { hcloud::models::LoadBalancer { public_net: Box::new(hcloud::models::LoadBalancerPublicNet { ipv4: Box::new(hcloud::models::LoadBalancerPublicNetIpv4 { - ip: Some(Some("203.0.113.10".to_string())), - dns_ptr: Some(Some("public.example.com".to_string())), + ip: Some("203.0.113.10".to_string()), + dns_ptr: Some("public.example.com".to_string()), + blocked: false, + id: None, }), ipv6: Box::new(hcloud::models::LoadBalancerPublicNetIpv6 { - ip: Some(Some("2001:db8::10".to_string())), - dns_ptr: Some(Some("public-v6.example.com".to_string())), + ip: Some("2001:db8::10".to_string()), + dns_ptr: Some("public-v6.example.com".to_string()), + blocked: false, + id: None, }), ..Default::default() }), private_net: vec![hcloud::models::LoadBalancerPrivateNet { - ip: Some("10.10.0.5".to_string()), + ip: "10.10.0.5".to_string(), ..Default::default() }], ..Default::default() diff --git a/src/lb/api.rs b/src/lb/api.rs index 88131f4..6d182eb 100644 --- a/src/lb/api.rs +++ b/src/lb/api.rs @@ -127,11 +127,42 @@ impl HcloudLoadBalancerApi for LiveHcloudLoadBalancerApi { load_balancer_id: i64, service: LoadBalancerService, ) -> RobotLBResult<()> { + // Extract fields from the enum variant to build AddServiceRequest + let (listen_port, destination_port, protocol, proxyprotocol, health_check) = match service { + LoadBalancerService::LoadBalancerServiceTcp(tcp) => ( + tcp.listen_port, + tcp.destination_port, + hcloud::models::add_service_request::Protocol::Tcp, + tcp.proxyprotocol, + *tcp.health_check, + ), + LoadBalancerService::LoadBalancerServiceHttpProtocol(http) => ( + http.listen_port, + http.destination_port, + hcloud::models::add_service_request::Protocol::Http, + http.proxyprotocol, + *http.health_check, + ), + LoadBalancerService::LoadBalancerServiceHttpsProtocol(https) => ( + https.listen_port, + https.destination_port, + hcloud::models::add_service_request::Protocol::Https, + https.proxyprotocol, + *https.health_check, + ), + }; hcloud::apis::load_balancers_api::add_service( &self.hcloud_config, AddServiceParams { id: load_balancer_id, - load_balancer_service: service, + add_service_request: hcloud::models::AddServiceRequest { + listen_port, + destination_port, + protocol, + proxyprotocol, + health_check: Box::new(health_check), + http: None, + }, }, ) .await?; @@ -189,7 +220,7 @@ impl HcloudLoadBalancerApi for LiveHcloudLoadBalancerApi { &self.hcloud_config, ChangeAlgorithmParams { id: load_balancer_id, - body: algorithm, + load_balancer_algorithm: algorithm, }, ) .await?; @@ -454,6 +485,10 @@ pub async fn create_load_balancer( network: None, network_zone: None, public_interface: Some(public_interface), + public_net: Some(Box::new(hcloud::models::LoadBalancerCreatePublicNet { + ipv4: None, + ipv6: None, + })), services: Some(vec![]), targets: Some(vec![]), }, diff --git a/src/lb/legacy.rs b/src/lb/legacy.rs index ed56964..be5ab79 100644 --- a/src/lb/legacy.rs +++ b/src/lb/legacy.rs @@ -69,14 +69,12 @@ impl LegacyOwnership { if !self.names.contains(&lb.name) { return false; } - let mut addresses: HashSet = [ - lb.public_net.ipv4.ip.clone().flatten(), - lb.public_net.ipv6.ip.clone().flatten(), - ] - .into_iter() - .flatten() - .collect(); - addresses.extend(lb.private_net.iter().filter_map(|net| net.ip.clone())); + let mut addresses: HashSet = + [lb.public_net.ipv4.ip.clone(), lb.public_net.ipv6.ip.clone()] + .into_iter() + .flatten() + .collect(); + addresses.extend(lb.private_net.iter().map(|net| net.ip.clone())); self.ingress_ips.iter().all(|ip| addresses.contains(ip)) } @@ -150,8 +148,10 @@ mod tests { name: "web.default".into(), public_net: Box::new(hcloud::models::LoadBalancerPublicNet { ipv4: Box::new(hcloud::models::LoadBalancerPublicNetIpv4 { - ip: Some(Some("203.0.113.10".into())), - ..Default::default() + ip: Some("203.0.113.10".into()), + blocked: false, + id: None, + dns_ptr: None, }), ..Default::default() }), @@ -196,7 +196,7 @@ mod tests { fn never_adopts_a_name_collision_or_foreign_owner() { let proof = LegacyOwnership::from_service(&service(), &config()).unwrap(); let mut lb = balancer(); - lb.public_net.ipv4.ip = Some(Some("198.51.100.20".into())); + lb.public_net.ipv4.ip = Some("198.51.100.20".into()); assert!(proof.labels_for_adoption(&lb, "service-uid").is_none()); let mut lb = balancer(); @@ -223,7 +223,7 @@ mod tests { let proof = LegacyOwnership::from_service(&svc, &config()).unwrap(); let mut lb = balancer(); lb.private_net = vec![hcloud::models::LoadBalancerPrivateNet { - ip: Some("10.0.0.10".into()), + ip: "10.0.0.10".into(), ..Default::default() }]; assert!(proof.labels_for_adoption(&lb, "service-uid").is_some()); @@ -286,11 +286,11 @@ mod tests { let mut old_lb = balancer(); old_lb.name = "web".into(); old_lb.private_net = vec![hcloud::models::LoadBalancerPrivateNet { - ip: Some("172.29.0.1".into()), + ip: "172.29.0.1".into(), ..Default::default() }]; assert!(proof.labels_for_adoption(&old_lb, "service-uid").is_some()); - old_lb.private_net[0].ip = Some("172.29.0.2".into()); + old_lb.private_net[0].ip = "172.29.0.2".into(); assert!(proof.labels_for_adoption(&old_lb, "service-uid").is_none()); } @@ -347,21 +347,22 @@ mod tests { replacement .services - .push(hcloud::models::LoadBalancerService { - http: None, - listen_port: 6443, - destination_port: 32767, - protocol: hcloud::models::load_balancer_service::Protocol::Tcp, - proxyprotocol: false, - health_check: Box::new(hcloud::models::LoadBalancerServiceHealthCheck { - http: None, - interval: 15, - port: 32767, - protocol: hcloud::models::load_balancer_service_health_check::Protocol::Tcp, - retries: 3, - timeout: 10, + .push(hcloud::models::LoadBalancerService::LoadBalancerServiceTcp( + Box::new(hcloud::models::LoadBalancerServiceTcp { + listen_port: 6443, + destination_port: 32767, + protocol: hcloud::models::load_balancer_service_tcp::Protocol::Tcp, + proxyprotocol: false, + health_check: Box::new(hcloud::models::LoadBalancerServiceHealthCheck { + http: None, + interval: 15, + port: 32767, + protocol: hcloud::models::load_balancer_service_health_check::Protocol::Tcp, + retries: 3, + timeout: 10, + }), }), - }); + )); assert!(!LegacyOwnership::is_unused_replacement( &replacement, "service-uid", diff --git a/src/lb/mod.rs b/src/lb/mod.rs index 40af13e..62274cf 100644 --- a/src/lb/mod.rs +++ b/src/lb/mod.rs @@ -179,26 +179,21 @@ impl LoadBalancer { listen_port, ); let desired = UpdateLoadBalancerService { + http: None, + protocol: Some(hcloud::models::update_load_balancer_service::Protocol::Tcp), + listen_port, + destination_port: Some(destination_port), + proxyprotocol: Some(self.proxy_mode), + health_check: Some(Box::new(LoadBalancerServiceHealthCheck { + protocol: + hcloud::models::load_balancer_service_health_check::Protocol::Tcp, http: None, - protocol: Some( - hcloud::models::update_load_balancer_service::Protocol::Tcp, - ), - listen_port, - destination_port: Some(destination_port), - proxyprotocol: Some(self.proxy_mode), - health_check: Some(Box::new( - hcloud::models::UpdateLoadBalancerServiceHealthCheck { - protocol: Some( - hcloud::models::update_load_balancer_service_health_check::Protocol::Tcp, - ), - http: None, - interval: Some(self.check_interval), - port: Some(destination_port), - retries: Some(self.retries), - timeout: Some(self.timeout), - }, - )), - }; + interval: self.check_interval, + port: destination_port, + retries: self.retries, + timeout: self.timeout, + })), + }; retry_temporary(|| api.update_service(hcloud_balancer.id, desired.clone())) .await?; } @@ -218,22 +213,23 @@ impl LoadBalancer { "Found missing service. Adding service that listens for port {}", listen_port ); - let desired = LoadBalancerService { - http: None, - listen_port, - destination_port, - protocol: hcloud::models::load_balancer_service::Protocol::Tcp, - proxyprotocol: self.proxy_mode, - health_check: Box::new(LoadBalancerServiceHealthCheck { - http: None, - interval: self.check_interval, - port: destination_port, - protocol: - hcloud::models::load_balancer_service_health_check::Protocol::Tcp, - retries: self.retries, - timeout: self.timeout, - }), - }; + let desired = LoadBalancerService::LoadBalancerServiceTcp(Box::new( + hcloud::models::LoadBalancerServiceTcp { + listen_port, + destination_port, + protocol: hcloud::models::load_balancer_service_tcp::Protocol::Tcp, + proxyprotocol: self.proxy_mode, + health_check: Box::new(LoadBalancerServiceHealthCheck { + http: None, + interval: self.check_interval, + port: destination_port, + protocol: + hcloud::models::load_balancer_service_health_check::Protocol::Tcp, + retries: self.retries, + timeout: self.timeout, + }), + }, + )); retry_temporary(|| api.add_service(hcloud_balancer.id, desired.clone())) .await?; } @@ -348,7 +344,16 @@ impl LoadBalancer { let mut actions = Vec::new(); for service in &hcloud_balancer.services { - if let Some(destination_port) = self.services.get(&service.listen_port) { + let listen_port = match service { + hcloud::models::LoadBalancerService::LoadBalancerServiceTcp(tcp) => tcp.listen_port, + hcloud::models::LoadBalancerService::LoadBalancerServiceHttpProtocol(http) => { + http.listen_port + } + hcloud::models::LoadBalancerService::LoadBalancerServiceHttpsProtocol(https) => { + https.listen_port + } + }; + if let Some(destination_port) = self.services.get(&listen_port) { if !service_matches_desired( service, *destination_port, @@ -358,14 +363,12 @@ impl LoadBalancer { self.proxy_mode, ) { actions.push(ServiceReconcileAction::Update { - listen_port: service.listen_port, + listen_port, destination_port: *destination_port, }); } } else { - actions.push(ServiceReconcileAction::Delete { - listen_port: service.listen_port, - }); + actions.push(ServiceReconcileAction::Delete { listen_port }); } } @@ -373,10 +376,20 @@ impl LoadBalancer { .services .iter() .filter(|(listen_port, _)| { - !hcloud_balancer - .services - .iter() - .any(|service| service.listen_port == **listen_port) + !hcloud_balancer.services.iter().any(|service| { + let svc_listen_port = match service { + hcloud::models::LoadBalancerService::LoadBalancerServiceTcp(tcp) => { + tcp.listen_port + } + hcloud::models::LoadBalancerService::LoadBalancerServiceHttpProtocol( + http, + ) => http.listen_port, + hcloud::models::LoadBalancerService::LoadBalancerServiceHttpsProtocol( + https, + ) => https.listen_port, + }; + svc_listen_port == **listen_port + }) }) .map( |(listen_port, destination_port)| ServiceReconcileAction::Add { @@ -406,7 +419,12 @@ impl LoadBalancer { let existing: HashSet = hcloud_balancer .targets .iter() - .filter_map(|target| target.ip.as_ref().map(|ip| normalize_ip(&ip.ip))) + .filter_map(|target| match target { + hcloud::models::LoadBalancerTarget::LoadBalancerTargetTypeIp(ip_target) => { + Some(normalize_ip(&ip_target.ip.ip)) + } + _ => None, + }) .collect(); let mut missing: Vec<_> = desired.difference(&existing).cloned().collect(); @@ -414,9 +432,13 @@ impl LoadBalancer { let mut obsolete: Vec<_> = hcloud_balancer .targets .iter() - .filter_map(|target| target.ip.as_ref()) - .filter(|ip| !desired.contains(&normalize_ip(&ip.ip))) - .map(|ip| ip.ip.clone()) + .filter_map(|target| match target { + hcloud::models::LoadBalancerTarget::LoadBalancerTargetTypeIp(ip_target) => { + Some(ip_target.ip.ip.clone()) + } + _ => None, + }) + .filter(|ip| !desired.contains(&normalize_ip(ip))) .collect(); obsolete.sort(); obsolete.dedup(); @@ -504,16 +526,9 @@ impl LoadBalancer { let mut is_attached = false; for private_net in &hcloud_balancer.private_net { - let Some(private_net_id) = private_net.network else { - continue; - }; + let private_net_id = private_net.network; - if desired_network == Some(private_net_id) - && private_net - .ip - .as_ref() - .is_some_and(|ip| self.matches_desired_ip(ip)) - { + if desired_network == Some(private_net_id) && self.matches_desired_ip(&private_net.ip) { is_attached = true; continue; } @@ -1033,12 +1048,23 @@ mod tests { _load_balancer_id: i64, service: LoadBalancerService, ) -> RobotLBResult<()> { + let (listen_port, destination_port) = match service { + LoadBalancerService::LoadBalancerServiceTcp(tcp) => { + (tcp.listen_port, tcp.destination_port) + } + LoadBalancerService::LoadBalancerServiceHttpProtocol(http) => { + (http.listen_port, http.destination_port) + } + LoadBalancerService::LoadBalancerServiceHttpsProtocol(https) => { + (https.listen_port, https.destination_port) + } + }; self.calls .lock() .expect("lock should not be poisoned") .push(ApiCall::AddService { - listen_port: service.listen_port, - destination_port: service.destination_port, + listen_port, + destination_port, }); Ok(()) } @@ -1148,21 +1174,22 @@ mod tests { } fn existing_service(listen_port: i32, destination_port: i32) -> LoadBalancerService { - LoadBalancerService { - http: None, - listen_port, - destination_port, - protocol: hcloud::models::load_balancer_service::Protocol::Tcp, - proxyprotocol: false, - health_check: Box::new(LoadBalancerServiceHealthCheck { - http: None, - interval: 5, - port: destination_port, - protocol: hcloud::models::load_balancer_service_health_check::Protocol::Tcp, - retries: 1, - timeout: 2, - }), - } + LoadBalancerService::LoadBalancerServiceTcp(Box::new( + hcloud::models::LoadBalancerServiceTcp { + listen_port, + destination_port, + protocol: hcloud::models::load_balancer_service_tcp::Protocol::Tcp, + proxyprotocol: false, + health_check: Box::new(LoadBalancerServiceHealthCheck { + http: None, + interval: 5, + port: destination_port, + protocol: hcloud::models::load_balancer_service_health_check::Protocol::Tcp, + retries: 1, + timeout: 2, + }), + }, + )) } fn remote_balancer_with_services( @@ -1175,11 +1202,15 @@ mod tests { services, targets: targets .into_iter() - .map(|ip| hcloud::models::LoadBalancerTarget { - ip: Some(Box::new(hcloud::models::LoadBalancerTargetIp { - ip: ip.to_string(), - })), - ..Default::default() + .map(|ip| { + hcloud::models::LoadBalancerTarget::LoadBalancerTargetTypeIp(Box::new( + hcloud::models::LoadBalancerTargetTypeIp { + ip: Box::new(hcloud::models::LoadBalancerTargetIp { + ip: ip.to_string(), + }), + ..Default::default() + }, + )) }) .collect(), algorithm: Box::new(LoadBalancerAlgorithm { @@ -1432,10 +1463,17 @@ mod tests { let mut lb = test_load_balancer(); lb.targets = vec!["10.0.0.1".into()]; let remote = hcloud::models::LoadBalancer { - targets: vec![hcloud::models::LoadBalancerTarget { - server: Some(Box::new(hcloud::models::ResourceId { id: 41 })), - ..Default::default() - }], + targets: vec![ + hcloud::models::LoadBalancerTarget::LoadBalancerTargetTypeServer(Box::new( + hcloud::models::LoadBalancerTargetTypeServer { + server: Box::new(hcloud::models::LoadBalancerTargetServer { + id: 41, + ip: "10.0.0.99".to_string(), + }), + ..Default::default() + }, + )), + ], ..Default::default() }; assert!(matches!( @@ -1485,17 +1523,26 @@ mod tests { match action { TargetReconcileAction::Remove { target_ip } => { remote.targets.retain(|target| { - target.ip.as_ref().is_none_or(|ip| ip.ip != target_ip) + match target { + hcloud::models::LoadBalancerTarget::LoadBalancerTargetTypeIp( + ip_target, + ) => ip_target.ip.ip != target_ip, + _ => true, + } }); } TargetReconcileAction::Add { target_ip } => { assert!(remote.targets.len() < capacity); - remote.targets.push(hcloud::models::LoadBalancerTarget { - ip: Some(Box::new(hcloud::models::LoadBalancerTargetIp { - ip: target_ip, - })), - ..Default::default() - }); + remote.targets.push( + hcloud::models::LoadBalancerTarget::LoadBalancerTargetTypeIp( + Box::new(hcloud::models::LoadBalancerTargetTypeIp { + ip: Box::new(hcloud::models::LoadBalancerTargetIp { + ip: target_ip, + }), + ..Default::default() + }), + ), + ); } } assert!(remote.targets.len() <= capacity); diff --git a/src/lb/types.rs b/src/lb/types.rs index 53d228c..c082c38 100644 --- a/src/lb/types.rs +++ b/src/lb/types.rs @@ -89,15 +89,21 @@ pub(super) fn service_matches_desired( timeout: i32, proxy_mode: bool, ) -> bool { - service.destination_port == destination_port - && service.health_check.port == destination_port - && service.health_check.interval == check_interval - && service.health_check.retries == retries - && service.health_check.timeout == timeout - && service.proxyprotocol == proxy_mode - && service.http.is_none() - && service.health_check.protocol - == hcloud::models::load_balancer_service_health_check::Protocol::Tcp + match service { + LoadBalancerService::LoadBalancerServiceTcp(tcp) => { + tcp.destination_port == destination_port + && tcp.health_check.port == destination_port + && tcp.health_check.interval == check_interval + && tcp.health_check.retries == retries + && tcp.health_check.timeout == timeout + && tcp.proxyprotocol == proxy_mode + && tcp.health_check.protocol + == hcloud::models::load_balancer_service_health_check::Protocol::Tcp + } + // HTTP and HTTPS services don't match our TCP-only desired configuration + LoadBalancerService::LoadBalancerServiceHttpProtocol(_) + | LoadBalancerService::LoadBalancerServiceHttpsProtocol(_) => false, + } } /// Normalize an IP address by removing any CIDR suffix.