diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53256947..e2fc22c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -255,8 +255,14 @@ jobs: # TODO: Restore a cache of dependencies and 'target'. - # Build and run the test suite. - - name: Test - run: cargo test --all-targets --locked + # Run unit tests. + - name: Unit tests + run: cargo test --locked --bins + + # Run integration tests. + - name: Integration tests + env: + RUST_LOG: debug + run: cargo test --locked --test integration # TODO: Build a cache. diff --git a/.gitignore b/.gitignore index 614dfbfa..220bb77a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ .vscode/ .DS_Store Session.vim + +test-dump-* +/test diff --git a/Cargo.lock b/Cargo.lock index 50e5ff2a..1310abee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,20 +4,25 @@ version = 4 [[package]] name = "aho-corasick" -version = "1.1.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +checksum = "e5bce8d450891e3b36f85a2230cec441fddd60e0c455b61b15bb3ffba955ca85" dependencies = [ "memchr", ] [[package]] -name = "android_system_properties" -version = "0.1.6" +name = "anstream" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +checksum = "4cd2405b3ac1faab2990b74d728624cd9fd115651fcecc7c2d8daf01376275ba" dependencies = [ - "libc", + "anstyle", + "anstyle-parse 0.2.0", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", ] [[package]] @@ -27,7 +32,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", - "anstyle-parse", + "anstyle-parse 1.0.0", "anstyle-query", "anstyle-wincon", "colorchoice", @@ -37,9 +42,18 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.14" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] [[package]] name = "anstyle-parse" @@ -52,60 +66,102 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.11" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.0", ] +[[package]] +name = "antidote" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" + +[[package]] +name = "anyhow" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" + [[package]] name = "arc-swap" -version = "1.9.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" -dependencies = [ - "rustversion", -] +checksum = "6e43c468bcaa343ddcad9e46806e066e39f62434898b20f5af21261da910d5c7" + +[[package]] +name = "arc-swap" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" [[package]] name = "assert-json-diff" -version = "2.0.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +checksum = "e7e8a5b58feafea5db7a9f41fe4b3da8f860b3e82397af2d2ad7c1c36e1867f1" dependencies = [ "serde", "serde_json", ] [[package]] -name = "atomic-waker" -version = "1.1.2" +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "async-trait" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f1418cdc602e31e3ffeea57d8481b8c5db895e733028c2552a06d5cf36beb91" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.56", +] [[package]] name = "autocfg" -version = "1.5.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "axum" -version = "0.8.9" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" dependencies = [ "axum-core", "bytes", @@ -116,13 +172,14 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "itoa", + "itoa 1.0.5", "matchit", "memchr", "mime", "percent-encoding", "pin-project-lite", - "serde_core", + "rustversion", + "serde", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -136,9 +193,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" dependencies = [ "bytes", "futures-core", @@ -147,6 +204,7 @@ dependencies = [ "http-body-util", "mime", "pin-project-lite", + "rustversion", "sync_wrapper", "tower-layer", "tower-service", @@ -155,15 +213,27 @@ dependencies = [ [[package]] name = "base64" -version = "0.22.1" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + +[[package]] +name = "base64" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" [[package]] name = "bcder" -version = "0.7.7" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b593e5aeaf7992d388c08a9831c921cd703718064b3e50ba8e6d666d6cf86ca7" +checksum = "f007d8acfb8ef7d219911c7164c025a6d3504735120fc5df59c3c479ab84ea51" dependencies = [ "bytes", "smallvec", @@ -171,54 +241,119 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.3.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" [[package]] name = "bitflags" -version = "2.13.1" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" + +[[package]] +name = "bollard" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d0a013e3d3ee4edd61e779adf117944c08902d375f18630a0c5b8f95659734" +dependencies = [ + "async-stream", + "base64 0.22.0", + "bitflags 2.7.0", + "bollard-buildkit-proto", + "bollard-stubs", + "bytes", + "chrono", + "futures-core", + "futures-util", + "hex", + "home", + "http", + "http-body-util", + "hyper", + "hyper-named-pipe", + "hyper-rustls", + "hyper-util", + "hyperlocal", + "log", + "num", + "pin-project-lite", + "rand", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "serde", + "serde_derive", + "serde_json", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "tonic", + "tower-service", + "url", + "winapi 0.3.9", +] + +[[package]] +name = "bollard-buildkit-proto" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "06961b3a889aadf51ad938dfcd07a29e49bd77c6e25ed8c1021764ea888ec7bd" +dependencies = [ + "prost", + "prost-types", + "tonic", + "tonic-prost", + "ureq", +] [[package]] -name = "bs58" -version = "0.5.1" +name = "bollard-stubs" +version = "1.53.1-rc.29.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +checksum = "ce412eb6f7096743011dc3cb5c674caeb24ced61d8c498fe07cf7998a4fea889" dependencies = [ - "tinyvec", + "base64 0.22.0", + "bollard-buildkit-proto", + "bytes", + "chrono", + "prost", + "serde", + "serde_json", + "serde_repr", ] [[package]] name = "bumpalo" -version = "3.20.3" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytes" -version = "1.12.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" dependencies = [ "serde", ] [[package]] name = "camino" -version = "1.2.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ - "serde_core", + "serde", ] [[package]] name = "cascade" version = "0.1.0-beta7-dev" dependencies = [ - "anstream", + "anstream 1.0.0", "camino", "cascade-api", "clap", @@ -246,7 +381,7 @@ version = "0.1.0-beta7-dev" dependencies = [ "camino", "clap", - "foldhash", + "foldhash 0.2.0", "serde", "toml", ] @@ -257,7 +392,7 @@ version = "0.1.0-beta7-dev" dependencies = [ "camino", "domain", - "foldhash", + "foldhash 0.2.0", "jiff", "serde", "serde_with", @@ -279,6 +414,7 @@ version = "0.1.0-beta7-dev" dependencies = [ "assert-json-diff", "axum", + "bollard", "bytes", "camino", "cascade-api", @@ -289,77 +425,86 @@ dependencies = [ "daemonbase", "domain", "domain-kmip", - "foldhash", + "foldhash 0.2.0", "futures-util", "hostname", "idna_adapter", "jiff", - "lazy_static", + "lazy_static 1.5.0", + "num", "prometheus-client", "rayon", + "reqwest", "ring", "serde", "serde_json", + "serde_repr", "serde_with", "supports-color", + "tar", "tempfile", "tokio", "toml", "tracing", "tracing-subscriber", "url", + "uuid", ] [[package]] name = "cc" -version = "1.4.2" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e" -dependencies = [ - "find-msvc-tools", - "shlex", -] +checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" [[package]] name = "cfg-if" -version = "1.0.4" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" + +[[package]] +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" -version = "0.10.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "rand_core", ] [[package]] name = "chrono" -version = "0.4.45" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +checksum = "6127248204b9aba09a362f6c930ef6a78f2c1b2215f8a7b398c06e1083f17af0" dependencies = [ - "iana-time-zone", + "js-sys", + "num-integer", "num-traits", "serde", - "windows-link", + "wasm-bindgen", + "winapi 0.3.9", ] [[package]] name = "clap" -version = "4.6.6" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ "clap_builder", "clap_derive", @@ -367,40 +512,40 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.6" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" dependencies = [ - "anstream", + "anstream 0.6.7", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.0", "terminal_size", ] [[package]] name = "clap_derive" -version = "4.6.4" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", "quote", - "syn 3.0.3", + "syn 2.0.98", ] [[package]] name = "clap_lex" -version = "1.1.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" -version = "1.0.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "constant_time_eq" @@ -408,11 +553,21 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" +[[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-sys" -version = "0.8.7" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" @@ -425,28 +580,47 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.7" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ + "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.20" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ + "cfg-if 1.0.0", "crossbeam-utils", + "lazy_static 1.5.0", + "memoffset 0.6.1", + "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +dependencies = [ + "cfg-if 1.0.0", + "lazy_static 1.5.0", +] + +[[package]] +name = "crypt32-sys" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "e34988f7e069e0b2f3bfc064295161e489b2d4e04a2e4248fb94360cdf00b4ec" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] [[package]] name = "daemonbase" @@ -467,9 +641,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.23.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +checksum = "e7c99d16b88c92aef47e58dadd53e87b4bd234c29934947a6cec8b466300f99b" dependencies = [ "darling_core", "darling_macro", @@ -477,66 +651,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.23.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +checksum = "2ea05d2fcb27b53f7a98faddaf5f2914760330ab7703adfc9df13332b42189f9" dependencies = [ + "fnv", "ident_case", "proc-macro2", "quote", - "strsim", - "syn 2.0.119", + "strsim 0.10.0", + "syn 2.0.98", ] [[package]] name = "darling_macro" -version = "0.23.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +checksum = "7bfb82b62b1b8a2a9808fb4caf844ede819a76cfc23b2827d7f94eefb49551eb" dependencies = [ "darling_core", "quote", - "syn 2.0.119", -] - -[[package]] -name = "defmt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" -dependencies = [ - "bitflags 1.3.2", - "defmt-macros", -] - -[[package]] -name = "defmt-macros" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" -dependencies = [ - "defmt-parser", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "defmt-parser" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" -dependencies = [ - "thiserror", -] - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "serde_core", + "syn 2.0.98", ] [[package]] @@ -544,13 +679,13 @@ name = "domain" version = "0.12.2" source = "git+https://github.com/NLnetLabs/domain?branch=main#8abed138580ea4ce9eaf4c6707d2e57521817981" dependencies = [ - "arc-swap", + "arc-swap 1.7.0", "bumpalo", "bytes", "constant_time_eq", "domain-macros", "futures-util", - "hashbrown 0.17.1", + "hashbrown 0.17.0", "jiff", "libc", "log", @@ -589,74 +724,74 @@ source = "git+https://github.com/NLnetLabs/domain?branch=main#8abed138580ea4ce9e dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.98", ] [[package]] name = "dtoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" - -[[package]] -name = "dyn-clone" -version = "1.0.20" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +checksum = "c3447f5c14dcdd36f5edaf76ac30d1abe91eca279d3bd9d7eca5c61826ea6e40" [[package]] name = "either" -version = "1.17.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" +checksum = "5845bf77d497f79416df39462df26d4a8b71dd6440246848ee63709476dbb9a6" [[package]] name = "enum-ordinalize" -version = "4.3.2" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" dependencies = [ "enum-ordinalize-derive", ] [[package]] name = "enum-ordinalize-derive" -version = "4.3.2" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +checksum = "e12d6d72b0a748af4d006a06f6dc14b040225dafdbbe057a472dca7571ed4d05" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.98", ] [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "errno" -version = "0.3.14" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] name = "fastrand" -version = "2.5.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] -name = "find-msvc-tools" -version = "0.1.10" +name = "filetime" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de" +checksum = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" +dependencies = [ + "cfg-if 0.1.6", + "libc", + "redox_syscall 0.1.0", + "winapi 0.3.9", +] [[package]] name = "fnv" @@ -664,6 +799,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d5ac82bdbbd872ce0dfea4e848a678cfcfdc0d210a5b20549b8c659fec0392" + [[package]] name = "foldhash" version = "0.2.0" @@ -672,115 +813,130 @@ checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "foreign-types" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "a21b40436003b2a1e22483c5ed6c3d25e755b6b3120f601cc22aa57e25dc9065" dependencies = [ "foreign-types-shared", ] [[package]] name = "foreign-types-shared" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "baa1839fc3c5487b5e129ea4f774e3fd84e6c4607127315521bc014a722ebc9e" [[package]] name = "form_urlencoded" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "futures-channel" -version = "0.3.34" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +checksum = "d3f9d78ee44e3067fa297c8c2c2313b98d014be8a3783387c500b50d7b769603" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.34" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-macro" -version = "0.3.34" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 2.0.98", ] [[package]] name = "futures-sink" -version = "0.3.34" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" +checksum = "346db18b3daf3e81f94023cd628230a01f34b1e64c5849f2a8308e678e1a21de" [[package]] name = "futures-task" -version = "0.3.34" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.34" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-macro", "futures-task", "pin-project-lite", + "pin-utils", "slab", ] [[package]] name = "getrandom" -version = "0.2.17" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.4.3" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71393ecc86efbf00e4ca13953979ba8b94cfe549a4b74cc26d8b62f4d8feac2b" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.13.0+wasi-0.2.0", + "windows-targets 0.52.0", +] + +[[package]] +name = "getrandom" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +checksum = "cd66c162c2a0609c0507f49814877c621d00cb85978e6fbbf04e88b8048c07c8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "r-efi", "rand_core", + "wasip2", + "wasip3", ] [[package]] name = "h2" -version = "0.4.15" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" dependencies = [ - "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", + "futures-util", "http", - "indexmap 2.14.0", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -789,17 +945,32 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "362385356d610bd1e5a408ddf8d022041774b683f345a1d2cfcb4f60f8ae2db5" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "foldhash 0.1.2", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "hashbrown" -version = "0.17.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" dependencies = [ - "foldhash", + "foldhash 0.2.0", ] [[package]] @@ -808,38 +979,55 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3" +dependencies = [ + "scopeguard", + "winapi 0.3.9", +] + [[package]] name = "hostname" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" +checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "windows-link", + "windows-link 0.1.1", ] [[package]] name = "http" -version = "1.5.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", - "itoa", + "fnv", + "itoa 1.0.5", ] [[package]] name = "http-body" -version = "1.1.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", "http", @@ -847,12 +1035,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.5" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http", "http-body", "pin-project-lite", @@ -860,32 +1048,31 @@ dependencies = [ [[package]] name = "httparse" -version = "1.10.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" [[package]] name = "httpdate" -version = "1.0.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "1.11.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ - "atomic-waker", "bytes", "futures-channel", - "futures-core", + "futures-util", "h2", "http", "http-body", "httparse", "httpdate", - "itoa", + "itoa 1.0.5", "pin-project-lite", "smallvec", "tokio", @@ -893,27 +1080,57 @@ dependencies = [ ] [[package]] -name = "hyper-rustls" -version = "0.27.9" +name = "hyper-named-pipe" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" dependencies = [ - "http", + "hex", "hyper", "hyper-util", - "rustls", + "pin-project-lite", "tokio", - "tokio-rustls", "tower-service", + "winapi 0.3.9", ] [[package]] -name = "hyper-util" -version = "0.1.20" +name = "hyper-rustls" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736f15a50e749d033164c56c09783b6102c4ff8da79ad77dbddbbaea0f8567f7" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +checksum = "14a42d172d2298d46ed0feb19c457a1959c776719894660c4532739d430235d2" dependencies = [ - "base64", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9f1e950e0d9d1d3c47184416723cf29c0d1f93bd8cccf37e4beb6b44f31710" +dependencies = [ + "base64 0.22.0", "bytes", "futures-channel", "futures-util", @@ -924,35 +1141,32 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.5.9", "tokio", "tower-service", "tracing", ] [[package]] -name = "iana-time-zone" -version = "0.1.65" +name = "hyperlocal" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +checksum = "62dc031ed32700046980078657318ec17331f54a91773b4205450442f53225df" dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", + "hex", + "http-body-util", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", ] [[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" +name = "id-arena" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] +checksum = "3a7250033feafee46a1cecd2c2616a64aec1d064f38c9ae2bdd297728542843e" [[package]] name = "ident_case" @@ -962,9 +1176,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", "smallvec", @@ -979,32 +1193,53 @@ checksum = "cfdf4f5d937a025381f5ab13624b1c5f51414bfe5c9885663226eae8d6d39560" [[package]] name = "indexmap" -version = "1.9.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", - "hashbrown 0.12.3", + "hashbrown 0.11.0", "serde", ] [[package]] name = "indexmap" -version = "2.14.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown 0.17.1", + "hashbrown 0.16.1", "serde", "serde_core", ] [[package]] name = "ipnet" -version = "2.12.1" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "iri-string" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21859b667d66a4c1dacd9df0863b3efb65785474255face87f5bca39dd8407c0" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is-terminal" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" +dependencies = [ + "hermit-abi", + "rustix 0.38.28", + "windows-sys 0.48.0", +] [[package]] name = "is_ci" @@ -1014,59 +1249,65 @@ checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "is_terminal_polyfill" -version = "1.70.2" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b52b2de84ed0341893ce61ca1af04fa54eea0a764ecc38c6855cc5db84dc1927" +dependencies = [ + "is-terminal", +] + +[[package]] +name = "itertools" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92a9df60778f789c37f76778ae8d0a2471c41baa8b059d98a5873c978f549587" [[package]] name = "itoa" -version = "1.0.18" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jiff" -version = "0.2.35" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" dependencies = [ - "defmt", - "jiff-core", "jiff-static", "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", - "serde_core", - "windows-link", -] - -[[package]] -name = "jiff-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" -dependencies = [ - "defmt", + "serde", + "windows-sys 0.52.0", ] [[package]] name = "jiff-static" -version = "0.2.35" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ - "jiff-core", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.98", ] [[package]] name = "jiff-tzdb" -version = "0.1.8" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" +checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524" [[package]] name = "jiff-tzdb-platform" @@ -1079,22 +1320,31 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ - "cfg-if", - "futures-util", + "once_cell", "wasm-bindgen", ] +[[package]] +name = "kernel32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1ca084b49bfd975182288e1a5f1d27ea34ff2d6ae084ae5e66e1652427eada" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "kmip-protocol" version = "0.5.0" source = "git+https://github.com/NLnetLabs/kmip-protocol.git?branch=next#03cc2defe51ecbfc89621d92f80f30042bdc0178" dependencies = [ - "bitflags 2.13.1", - "cfg-if", + "bitflags 2.7.0", + "cfg-if 1.0.0", "enum-ordinalize", "hex", "kmip-ttlv", @@ -1116,7 +1366,7 @@ name = "kmip-ttlv" version = "0.4.0" source = "git+https://github.com/NLnetLabs/kmip-ttlv?branch=next#295572e07feb30293462267db2de1640ba1bfabe" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "hex", "maybe-async", "rustc_version", @@ -1124,38 +1374,56 @@ dependencies = [ "tracing", ] +[[package]] +name = "lazy_static" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9e1e434b35b61b6422b19998d5c219f6b4a90aae841583444b44077adb953b" + [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.189" +version = "0.2.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" + +[[package]] +name = "linux-raw-sys" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "linux-raw-sys" -version = "0.12.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9" [[package]] name = "lock_api" -version = "0.4.14" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] [[package]] name = "log" -version = "0.4.33" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "matchers" @@ -1174,74 +1442,141 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "maybe-async" -version = "0.2.11" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "746873a384ad60adc5db74471dfaba74bd278afbdcfd81db93fafcdfc8b5ca0c" +checksum = "6007f9dad048e0a224f27ca599d669fca8cfa0dac804725aab542b2eb032bce6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 1.0.56", ] [[package]] name = "memchr" -version = "2.8.3" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd85c6502c853919a7ffb75f80e67ecca712dda8f07c698f9df6e020a4f3e44" + +[[package]] +name = "memoffset" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +dependencies = [ + "autocfg", +] [[package]] name = "memoffset" -version = "0.9.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "mime" -version = "0.3.17" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mio" -version = "1.2.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi", - "windows-sys 0.61.2", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", ] [[package]] name = "nix" -version = "0.31.3" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +checksum = "db9f2b173ed7678e98df5c31c60c3d49595cb37e9b58c71e85ec03e88a278fae" dependencies = [ - "bitflags 2.13.1", - "cfg-if", + "bitflags 2.7.0", + "cfg-if 1.0.0", "cfg_aliases", "libc", - "memoffset", + "memoffset 0.9.0", ] [[package]] name = "nu-ansi-term" -version = "0.50.3" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] -name = "num-conv" -version = "0.2.2" +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] [[package]] name = "num-traits" @@ -1254,9 +1589,9 @@ dependencies = [ [[package]] name = "num_threads" -version = "0.1.7" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +checksum = "71a1eb3a36534514077c1e079ada2fb170ef30c47d203aa6916138cf882ecd52" dependencies = [ "libc", ] @@ -1274,26 +1609,30 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.4" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "once_cell_polyfill" -version = "1.70.2" +version = "1.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +checksum = "0ecf5dec444661aad892044dfcc6ea9b2d1be3db6c78916b91bbf9d903fc3006" +dependencies = [ + "once_cell", +] [[package]] name = "openssl" -version = "0.10.81" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ - "bitflags 2.13.1", - "cfg-if", + "bitflags 2.7.0", + "cfg-if 1.0.0", "foreign-types", "libc", + "once_cell", "openssl-macros", "openssl-sys", ] @@ -1306,14 +1645,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.98", ] +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + [[package]] name = "openssl-sys" -version = "0.9.117" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", @@ -1323,9 +1668,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.5" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ "lock_api", "parking_lot_core", @@ -1333,73 +1678,103 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.12" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +checksum = "b2f4f894f3865f6c0e02810fc597300f34dc2510f66400da262d8ae10e75767d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.2.8", "smallvec", - "windows-link", + "windows-sys 0.29.0", ] [[package]] name = "percent-encoding" -version = "2.3.2" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.56", +] [[package]] name = "pin-project-lite" -version = "0.2.17" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" + +[[package]] +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.33" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +checksum = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" [[package]] name = "portable-atomic" -version = "1.15.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "portable-atomic-util" -version = "0.2.7" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ "portable-atomic", ] [[package]] -name = "powerfmt" -version = "0.2.0" +name = "prettyplease" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.98", +] [[package]] name = "proc-macro2" -version = "1.0.107" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus-client" -version = "0.24.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca3d75b4566b9a29fe1ed623587fb058e826eb329a0be4b7c4da1ebb2d7a6ca" +checksum = "e4500adecd7af8e0e9f4dbce15cfee07ce913fbf6ad605cc468b83f2d531ee94" dependencies = [ "dtoa", - "itoa", + "itoa 1.0.5", "parking_lot", "prometheus-client-derive-encode", ] @@ -1412,23 +1787,55 @@ checksum = "9adf1691c04c0a5ff46ff8f262b58beb07b0dbb61f96f9f54f6cbd82106ed87f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.98", +] + +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "prost-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +dependencies = [ + "prost", ] [[package]] name = "quote" -version = "1.0.47" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "6.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +checksum = "5a2af567ac9e1e7d2d11097ca14a1e463a5c06a2ee84c23c009b489b00afc1fc" [[package]] name = "r2d2" @@ -1443,20 +1850,20 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20", - "getrandom 0.4.3", + "getrandom 0.4.0", "rand_core", ] [[package]] name = "rand_core" -version = "0.10.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" [[package]] name = "rayon" @@ -1480,38 +1887,24 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags 2.13.1", -] - -[[package]] -name = "ref-cast" -version = "1.0.26" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216e8f773d7923bcba9ceb86a86c93cabb3903a11872fc3f138c49630e50b96d" -dependencies = [ - "ref-cast-impl", -] +checksum = "35a48131ab10dbeb17202bd1dcb9c9798963a58a50c9ec31640f237358832094" [[package]] -name = "ref-cast-impl" -version = "1.0.26" +name = "redox_syscall" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9283685feec7d69af75fb0e858d5e7378f33fe4fc699383b2916ab9273e03c" +checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.3", + "bitflags 1.1.0", ] [[package]] name = "regex-automata" -version = "0.4.18" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +checksum = "5d58da636bd923eae52b7e9120271cbefb16f399069ee566ca5ebf9c30e32238" dependencies = [ "aho-corasick", "memchr", @@ -1520,17 +1913,17 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.11" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +checksum = "c3cbb081b9784b07cceb8824c8583f86db4814d172ab043f3c23f7dc600bf83d" [[package]] name = "reqwest" -version = "0.13.4" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ - "base64", + "base64 0.22.0", "bytes", "futures-core", "h2", @@ -1559,45 +1952,58 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.14" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +checksum = "911b295d2d302948838c8ac142da1ee09fa7863163b44e6715bc9357905878b8" dependencies = [ "cc", - "cfg-if", - "getrandom 0.2.17", + "getrandom 0.2.8", "libc", + "spin", "untrusted", - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] name = "rustc_version" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "1.1.4" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.7.0", "errno", "libc", - "linux-raw-sys", - "windows-sys 0.61.2", + "linux-raw-sys 0.4.11", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustix" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657" +dependencies = [ + "bitflags 2.7.0", + "errno", + "libc", + "linux-raw-sys 0.9.2", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.23.43" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "log", "once_cell", @@ -1608,6 +2014,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "2.2.0" @@ -1619,18 +2038,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.14" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring", "rustls-pki-types", @@ -1639,75 +2058,97 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.23" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.23" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +checksum = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" [[package]] -name = "scheduled-thread-pool" -version = "0.2.7" +name = "schannel" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +checksum = "4183ac471f97fe3e84803e81e40eba6612db22354095321a84000f495845bb09" dependencies = [ - "parking_lot", + "crypt32-sys", + "kernel32-sys", + "lazy_static 0.2.0", + "secur32-sys", + "winapi 0.2.8", ] [[package]] -name = "schemars" -version = "0.9.0" +name = "scheduled-thread-pool" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +checksum = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889" dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", + "antidote", ] [[package]] -name = "schemars" -version = "1.2.2" +name = "scopeguard" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "secrecy" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1f662a494cd3c8dd64a16514bdcd4ebf7d76558fad96392500ea5e0b72b8b68" +dependencies = [ + "zeroize", ] [[package]] -name = "scopeguard" -version = "1.2.0" +name = "secur32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "security-framework" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.7.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] [[package]] -name = "secrecy" -version = "0.10.3" +name = "security-framework-sys" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ - "zeroize", + "core-foundation-sys", + "libc", ] [[package]] name = "semver" -version = "1.0.28" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +checksum = "76b5842e81eb9bbea19276a9dbbda22ac042532f390a67ab08b895617978abf3" [[package]] name = "serde" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -1715,56 +2156,62 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.19" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" dependencies = [ "serde", - "serde_core", ] [[package]] name = "serde_core" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.229" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 2.0.98", ] [[package]] name = "serde_json" -version = "1.0.151" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" dependencies = [ - "itoa", - "memchr", + "itoa 1.0.5", + "ryu", "serde", - "serde_core", - "zmij", ] [[package]] name = "serde_path_to_error" -version = "0.1.20" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +checksum = "184c643044780f7ceb59104cef98a5a6f12cb2288a7bc701ab93a362b49fd47d" dependencies = [ - "itoa", "serde", - "serde_core", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", ] [[package]] @@ -1778,32 +2225,27 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.7.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ "form_urlencoded", - "itoa", + "itoa 0.4.0", "ryu", "serde", ] [[package]] name = "serde_with" -version = "3.22.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" +checksum = "9f02d8aa6e3c385bf084924f660ce2a3a6bd333ba55b35e8590b321f35d88513" dependencies = [ - "base64", - "bs58", + "base64 0.21.0", "chrono", "hex", - "indexmap 1.9.3", - "indexmap 2.14.0", - "jiff", - "schemars 0.9.0", - "schemars 1.2.2", - "serde_core", + "indexmap 1.8.0", + "serde", "serde_json", "serde_with_macros", "time", @@ -1811,80 +2253,96 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.22.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" +checksum = "edc7d5d3932fb12ce722ee5e64dd38c504efba37567f0c402f6ca728c3b8b070" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.98", ] [[package]] name = "sharded-slab" -version = "0.1.7" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" dependencies = [ - "lazy_static", + "lazy_static 1.5.0", ] -[[package]] -name = "shlex" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" - [[package]] name = "signal-hook-registry" -version = "1.4.8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +checksum = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" dependencies = [ - "errno", + "arc-swap 0.4.0", "libc", ] [[package]] name = "siphasher" -version = "1.0.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" +checksum = "54ac45299ccbd390721be55b412d41931911f654fa99e2cb8bfb57184b2061fe" [[package]] name = "slab" -version = "0.4.12" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" -version = "0.6.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.0", +] + +[[package]] +name = "spin" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" + [[package]] name = "strsim" -version = "0.11.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "subtle" -version = "2.6.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "supports-color" @@ -1897,20 +2355,20 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.119" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "unicode-xid", ] [[package]] name = "syn" -version = "3.0.3" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -1938,148 +2396,125 @@ dependencies = [ "time", ] +[[package]] +name = "tar" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "tempfile" -version = "3.27.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.3.0", "once_cell", - "rustix", - "windows-sys 0.61.2", + "rustix 1.0.1", + "windows-sys 0.52.0", ] [[package]] name = "terminal_size" -version = "0.4.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix", - "windows-sys 0.61.2", + "rustix 1.0.1", + "windows-sys 0.60.0", ] [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "15291287e9bff1bc6f9ff3409ed9af665bec7a5fc8ac079ea96be07bca0e2668" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "22efd00f33f93fa62848a7cab956c3d38c8d43095efda1decfc2b3a5dc0b8972" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 2.0.98", ] [[package]] name = "thread_local" -version = "1.1.10" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ - "cfg-if", + "once_cell", ] [[package]] name = "time" -version = "0.3.55" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" dependencies = [ - "deranged", + "itoa 1.0.5", "libc", - "num-conv", "num_threads", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" - -[[package]] -name = "time-macros" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" -dependencies = [ - "tinyvec_macros", + "serde", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.53.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ "bytes", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.1", "tokio-macros", "tracing", - "windows-sys 0.61.2", + "windows-sys 0.61.0", ] [[package]] name = "tokio-macros" -version = "2.7.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 2.0.98", ] [[package]] name = "tokio-rustls" -version = "0.26.4" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ "rustls", + "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.19" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -2088,25 +2523,25 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.19" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" dependencies = [ "bytes", "futures-core", "futures-sink", - "libc", "pin-project-lite", "tokio", + "tracing", ] [[package]] name = "toml" -version = "1.1.4+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.13.0", "serde_core", "serde_spanned", "toml_datetime", @@ -2126,11 +2561,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.13+spec-1.1.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.14.0", + "indexmap 2.13.0", "toml_datetime", "toml_parser", "toml_writer", @@ -2139,50 +2574,94 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.3+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.1.2+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + +[[package]] +name = "tonic" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308e1db96abdccdf0a9150fb69112bf6ea72640e0bd834ef0c4a618ccc8c8ddc" +dependencies = [ + "async-trait", + "axum", + "base64 0.22.0", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2 0.6.1", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8b5b7a44512c59f5ad45e0c40e53263cbbf4426d74fe6b569e04f1d4206e9c" +dependencies = [ + "bytes", + "prost", + "tonic", +] [[package]] name = "tower" -version = "0.5.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", + "indexmap 2.13.0", "pin-project-lite", + "slab", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "tower-http" -version = "0.6.11" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.7.0", "bytes", "futures-util", "http", "http-body", + "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", - "url", ] [[package]] @@ -2199,9 +2678,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.44" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -2211,20 +2690,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.31" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.98", ] [[package]] name = "tracing-core" -version = "0.1.36" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -2243,9 +2722,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.23" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", @@ -2261,15 +2740,21 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.5" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +checksum = "2a31f2d8ccabc3089a7aad162f96d4513034a6c5d2385e93023984c645e65fb6" [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + +[[package]] +name = "unicode-xid" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "untrusted" @@ -2277,19 +2762,52 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "972d7902c8735f2695410b8aed7df6ed12a47394aa1c8d7af49f0497b731a94d" +dependencies = [ + "base64 0.23.1", + "log", + "percent-encoding", + "rustls", + "rustls-pki-types", + "ureq-proto", + "utf8-zero", + "webpki-roots", +] + +[[package]] +name = "ureq-proto" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da5f78b09e6941e1a0f2e30e695e4b120377b54d5e0aec11b594bb57b3971613" +dependencies = [ + "base64 0.23.1", + "http", + "httparse", + "log", +] + [[package]] name = "url" -version = "2.5.8" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", - "serde_derive", ] +[[package]] +name = "utf8-zero" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -2304,70 +2822,114 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.24.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" +checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" dependencies = [ - "getrandom 0.4.3", + "getrandom 0.3.0", "js-sys", "wasm-bindgen", ] [[package]] name = "valuable" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vcpkg" -version = "0.2.15" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" [[package]] name = "want" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ + "log", "try-lock", ] [[package]] name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.13.0+wasi-0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +checksum = "652cd73449d0b957a2743b70c72d79d34a5fa505696488f4ca90b46f6da94118" +dependencies = [ + "bitflags 2.7.0", + "wit-bindgen-rt", +] + +[[package]] +name = "wasip2" +version = "1.0.0+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +dependencies = [ + "wit-bindgen 0.45.0", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", "rustversion", "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.98", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.77" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +checksum = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35" dependencies = [ + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", + "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2375,31 +2937,65 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ - "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 2.0.98", + "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.7.0", + "hashbrown 0.15.2", + "indexmap 2.13.0", + "semver", +] + [[package]] name = "web-sys" -version = "0.3.104" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +checksum = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" dependencies = [ "js-sys", "wasm-bindgen", @@ -2407,70 +3003,79 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.9" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" dependencies = [ "rustls-pki-types", ] [[package]] -name = "windows-core" -version = "0.62.2" +name = "winapi" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] -name = "windows-implement" -version = "0.60.2" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "windows-interface" -version = "0.59.3" +name = "winapi-build" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[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-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-link" -version = "0.2.1" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" [[package]] -name = "windows-result" -version = "0.4.1" +name = "windows-link" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-sys" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceb069ac8b2117d36924190469735767f0990833935ab430155e71a44bafe148" dependencies = [ - "windows-link", + "windows_aarch64_msvc 0.29.0", + "windows_i686_gnu 0.29.0", + "windows_i686_msvc 0.29.0", + "windows_x86_64_gnu 0.29.0", + "windows_x86_64_msvc 0.29.0", ] [[package]] -name = "windows-strings" -version = "0.5.1" +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-link", + "windows-targets 0.48.0", ] [[package]] @@ -2479,99 +3084,357 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-sys" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e5de29ca9cfd0b9822d586cfdcb4e2fe54d71011b33212473628cef1b23a0fe" +dependencies = [ + "windows-targets 0.53.2", ] [[package]] name = "windows-sys" -version = "0.61.2" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" dependencies = [ - "windows-link", + "windows-link 0.2.0", ] [[package]] name = "windows-targets" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.6" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +checksum = "c3d027175d00b01e0cbeb97d6ab6ebe03b12330a35786cbaca5252b1c4bf5d9b" [[package]] name = "windows_aarch64_msvc" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8793f59f7b8e8b01eda1a652b2697d87b93097198ae85f823b969ca5b89bba58" [[package]] name = "windows_i686_gnu" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" [[package]] name = "windows_i686_gnullvm" -version = "0.52.6" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "8602f6c418b67024be2996c512f5f995de3ba417f4c75af68401ab8756796ae4" [[package]] name = "windows_i686_msvc" -version = "0.52.6" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "f3d615f419543e0bd7d2b3323af0d86ff19cbc4f816e6453f36a2c2ce889c354" [[package]] name = "windows_x86_64_gnu" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" -version = "0.52.6" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "11d95421d9ed3672c280884da53201a5c46b7b2765ca6faf34b0d71cf34a3561" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "1.0.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" dependencies = [ "memchr", ] [[package]] -name = "zeroize" -version = "1.9.0" +name = "wit-bindgen" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" [[package]] -name = "zmij" -version = "1.0.23" +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "026d24a27f6712541fa534f2954bd9e0eb66172f033c2157c0f31d106255c497" + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.13.0", + "prettyplease", + "syn 2.0.98", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.98", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.7.0", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "xattr" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7dae5072fe1f8db8f8d29059189ac175196e410e40ba42d5d4684ae2f750995" +dependencies = [ + "libc", + "linux-raw-sys 0.4.11", + "rustix 0.38.28", +] + +[[package]] +name = "zeroize" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml index 87ad1644..fb0f55a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,11 +42,19 @@ readme = "README.md" default-run = "cascaded" +[profile.dev] +# Significantly reduces binary size. +split-debuginfo = "unpacked" [profile.release] panic = "abort" +[[test]] +name = "integration" +harness = false + + # --- Dependencies ------------------------------------------------------------- [workspace.dependencies] @@ -121,6 +129,7 @@ version = "1.40" version = "0.1.40" [workspace.dependencies.tracing-subscriber] version = "0.3.20" +features = ["env-filter"] [dependencies] @@ -257,6 +266,26 @@ workspace = true [dev-dependencies] assert-json-diff = "2.0" +bollard = { version = "0.21", default-features = false, features = ["pipe", "buildkit", "chrono"] } +reqwest = { version = "0.13.3", default-features = false, features = ["http2", "json"] } +uuid = { version = "1.18.0", features = ["v4"] } +tar = "0.4.45" + +# Outdated dependency due to: +# -> `bollard v0.21` (2026-05) +# -> `num v0.4.0` (2021-03) +# -> `num-bigint v0.4.0` (2021-03) +# ... which does not compile at our MSRV. +# Bump `num` to prevent this. +num = { version = "0.4.3", default-features = false } + +# Outdated dependency due to: +# -> `bollard v0.21` (2026-05) +# -> `bollard-stubs v1.53.1-rc.29.3.1` (2026-05) +# -> `serde_repr v0.1.0` (2019-01) +# ... which does not compile at our MSRV. +# Bump `serde_repr` to prevent this. +serde_repr = { version = "0.1.20", default-features = false } # --- Packaging ---------------------------------------------------------------- diff --git a/act-wrapper b/act-wrapper index 50d221d7..e757192d 100755 --- a/act-wrapper +++ b/act-wrapper @@ -131,7 +131,7 @@ done if [[ "$no_build" != true ]]; then if [[ "$build_inside" != true ]]; then cargo build - cargo build --release + # cargo build --release fi docker buildx build . -f integration-tests/cascade-test-image/Dockerfile -t nlnetlabs/cascade-tests-runner --build-arg MSRV=$MSRV "${args[@]}" diff --git a/crates/cfg/src/file/mod.rs b/crates/cfg/src/file/mod.rs index 6e0821f9..7d27f9ef 100644 --- a/crates/cfg/src/file/mod.rs +++ b/crates/cfg/src/file/mod.rs @@ -1,9 +1,9 @@ //! The configuration file. -use std::{fmt, sync::Arc}; +use std::{fmt, io, sync::Arc}; use camino::Utf8Path; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use super::Config; @@ -12,7 +12,7 @@ pub mod v1; //----------- Spec ------------------------------------------------------------- /// A configuration file. -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", tag = "version")] pub enum Spec { /// The version 1 format. @@ -36,6 +36,11 @@ impl Spec { let text = std::fs::read_to_string(path)?; Ok(toml::from_str(&text)?) } + + /// Save the configuration file, formatting in a compact notation. + pub fn save_compact(&self, path: &Utf8Path) -> io::Result<()> { + std::fs::write(path, toml::to_string(self).unwrap()) + } } //----------- FileError -------------------------------------------------------- diff --git a/crates/cfg/src/file/v1.rs b/crates/cfg/src/file/v1.rs index b9afd7a9..b310ebc2 100644 --- a/crates/cfg/src/file/v1.rs +++ b/crates/cfg/src/file/v1.rs @@ -3,7 +3,7 @@ use std::{fmt, net::SocketAddr, num::IntErrorKind, str::FromStr}; use camino::Utf8Path; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use crate::{ Config, DaemonConfig, GroupId, KeyManagerConfig, LoaderConfig, LogLevel, LogTarget, @@ -13,7 +13,7 @@ use crate::{ //----------- Spec ------------------------------------------------------------- /// A configuration file. -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct Spec { /// The directory storing policy files. @@ -135,7 +135,7 @@ impl Spec { //----------- RemoteControlSpec ---------------------------------------------- /// Remote control configuration for Cascade. -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct RemoteControlSpec { /// Where to serve our HTTP API from, e.g. for the Cascade client. @@ -175,7 +175,7 @@ impl RemoteControlSpec { //----------- DaemonSpec ------------------------------------------------------- /// Configuring the Cascade daemon. -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct DaemonSpec { /// The minimum severity of messages to log. @@ -210,7 +210,7 @@ impl DaemonSpec { //----------- LogLevelSpec ----------------------------------------------------- /// A severity level for logging. -#[derive(Copy, Clone, Debug, Deserialize)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum LogLevelSpec { /// A function or variable was interacted with, for debugging. @@ -251,7 +251,7 @@ impl LogLevelSpec { //----------- LogTargetSpec ---------------------------------------------------- /// A logging target. -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, tag = "type")] pub enum LogTargetSpec { /// Append logs to a file. @@ -324,6 +324,23 @@ impl<'de> Deserialize<'de> for IdentitySpec { } } +//--- Serialization + +impl fmt::Display for IdentitySpec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}:{}", self.user, self.group) + } +} + +impl Serialize for IdentitySpec { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.to_string().serialize(serializer) + } +} + //--- Conversion impl IdentitySpec { @@ -363,6 +380,17 @@ impl FromStr for UserIdSpec { } } +//--- Serialization + +impl fmt::Display for UserIdSpec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Numeric(v) => write!(f, "{v}"), + Self::Named(v) => write!(f, "{v}"), + } + } +} + //--- Conversion impl UserIdSpec { @@ -405,6 +433,17 @@ impl FromStr for GroupIdSpec { } } +//--- Serialization + +impl fmt::Display for GroupIdSpec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Numeric(v) => write!(f, "{v}"), + Self::Named(v) => write!(f, "{v}"), + } + } +} + //--- Conversion impl GroupIdSpec { @@ -420,7 +459,7 @@ impl GroupIdSpec { //----------- LoaderSpec ------------------------------------------------------- /// Configuring how zones are loaded. -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct LoaderSpec { /// Configuring whether and how loaded zones are reviewed. @@ -439,7 +478,7 @@ impl LoaderSpec { //----------- SignerSpec ------------------------------------------------------- /// Configuring the zone signer. -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct SignerSpec { /// Configuring whether and how signed zones are reviewed. @@ -458,7 +497,7 @@ impl SignerSpec { //----------- ReviewSpec ------------------------------------------------------- /// Configuring whether and how zones are reviewed. -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct ReviewSpec { /// Where to serve zones for review. @@ -480,7 +519,7 @@ impl ReviewSpec { //----------- KeyManagerSpec --------------------------------------------------- /// Configuring DNSSEC key management. -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct KeyManagerSpec {} @@ -496,7 +535,7 @@ impl KeyManagerSpec { //----------- ServerSpec ------------------------------------------------------- /// Configuring how zones are published. -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, default)] pub struct ServerSpec { /// Where to serve zones. @@ -518,7 +557,7 @@ impl ServerSpec { //----------- SocketSpec ------------------------------------------------------- /// Configuration for serving / listening on a network socket. -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(untagged, expecting = "a URI string or an inline table")] pub enum SocketSpec { /// A simple socket specification. @@ -553,7 +592,7 @@ pub enum SimpleSocketSpec { } /// A complex [`SocketSpec`] as a table. -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "kebab-case", deny_unknown_fields, tag = "type")] pub enum ComplexSocketSpec { /// Listen exclusively over UDP. @@ -612,6 +651,27 @@ impl<'de> Deserialize<'de> for SimpleSocketSpec { } } +//--- Serialization + +impl fmt::Display for SimpleSocketSpec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SimpleSocketSpec::UDP { addr } => write!(f, "udp://{addr}"), + SimpleSocketSpec::TCP { addr } => write!(f, "tcp://{addr}"), + SimpleSocketSpec::TCPUDP { addr } => write!(f, "{addr}"), + } + } +} + +impl Serialize for SimpleSocketSpec { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.to_string().serialize(serializer) + } +} + //--- Conversion impl SocketSpec { diff --git a/tests/integration/Dockerfile b/tests/integration/Dockerfile new file mode 100644 index 00000000..389ebe2d --- /dev/null +++ b/tests/integration/Dockerfile @@ -0,0 +1,88 @@ +# Steps are carefully organized to maximize caching. +# Build flow: `base` -> { `dnst`, `cascade-hsm-bridge` } -> `final` + +# --- Stage `base` + +FROM ubuntu:latest AS base +USER root +SHELL ["/bin/bash", "--login", "-e", "-o", "pipefail", "-c"] + +# NOTE: This step does not invalidate the cache. A cached execution will be used +# most of the time, which means the installed packages might be slightly old. We +# don't strictly require the latest version of anything, so this is fine. +# +# We might not always need every package here; but we install all of them so +# they can be part of the same cached layer. +RUN < `./Dockerfile` +# `tests/integration/data` -> `./` +tar --create \ + --transform='s#tests/integration/#./#' tests/integration/Dockerfile \ + --directory=$PWD/tests/integration/data . \ + | docker buildx build - -t nlnetlabs/cascade-tests-runner diff --git a/tests/integration/infra/cascade.rs b/tests/integration/infra/cascade.rs new file mode 100644 index 00000000..2ca9afcd --- /dev/null +++ b/tests/integration/infra/cascade.rs @@ -0,0 +1,515 @@ +//! Controlling Cascade. + +use std::{ + fmt::{self, Debug}, + net::{IpAddr, SocketAddr}, + pin::Pin, + time::{Duration, SystemTime}, +}; + +use bollard::{container::LogOutput, exec::StartExecResults, plugin::ExecConfig}; +use cascade_api as api; +use futures_util::{Stream, StreamExt}; +use serde::{Serialize, de::DeserializeOwned}; +use tracing::Instrument; + +use super::{Container, ports, strs}; + +//----------- Cascade ---------------------------------------------------------- + +/// A running Cascade instance. +pub struct Cascade { + /// The Docker exec ID. + exec_id: String, + + /// The configuration with which Cascade was launched. + #[expect(dead_code)] + config: CascadeConfig, + + /// An HTTP client for communicating with Cascade. + control: CascadeControl, +} + +impl Cascade { + /// The maximum time Cascade startup is allowed to take. + const STARTUP_TIMEOUT: Duration = Duration::from_secs(10); + + /// The interval between pings to check Cascade's health. + const HEALTH_PING_INTERVAL: Duration = Duration::from_millis(100); + + /// Start Cascade. + pub async fn start(container: &Container) -> Self { + Self::start_with(container, CascadeConfig::default()).await + } + + /// Start Cascade with the given configuration. + pub async fn start_with(container: &Container, config: CascadeConfig) -> Self { + tracing::info!("Starting Cascade"); + + let exec_id = self::start(container, &config).await; + let control = CascadeControl::new(container.ip_addr()); + + let this = Self { + exec_id, + config, + control, + }; + + // Wait until the daemon appears ready. + let ready = tokio::time::timeout(Self::STARTUP_TIMEOUT, async { + loop { + tokio::time::sleep(Self::HEALTH_PING_INTERVAL).await; + if this.health().await.is_ok_and(|h| h.healthy) { + break; + } + } + }) + .await; + if ready.is_err() { + tracing::error!("Cascade did not appear ready in time."); + panic!("Cascade did not appear ready in time") + } + + this + } + + // Stop Cascade. +} + +//--- Debugging + +impl fmt::Debug for Cascade { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Cascade") + .field("exec_id", &self.exec_id) + .finish_non_exhaustive() + } +} + +//----------- CascadeControl --------------------------------------------------- + +/// An HTTP client controlling Cascade. +pub struct CascadeControl { + /// The underlying HTTP client. + inner: reqwest::Client, + + /// The base URL for all requests. + base: url::Url, +} + +impl CascadeControl { + /// Prepare a new [`CascadeControl`]. + fn new(ip_addr: IpAddr) -> Self { + let inner = reqwest::ClientBuilder::new() + .user_agent(Self::USER_AGENT) + .timeout(Self::REQUEST_TIMEOUT) + .http2_prior_knowledge() + .build() + .unwrap(); + + let base = reqwest::Url::parse(&format!( + "http://{}/", + SocketAddr::new(ip_addr, ports::REMOTE_CONTROL.0) + )) + .unwrap(); + + Self { inner, base } + } + + /// The user agent for HTTP requests. + const USER_AGENT: &str = concat!( + env!("CARGO_PKG_NAME"), + "-testing/", + env!("CARGO_PKG_VERSION"), + ); + + /// The maximum time an HTTP request is expected to take. + const REQUEST_TIMEOUT: Duration = Duration::from_secs(10); + + /// Decode a JSON response. + /// + /// ## Panics + /// + /// Panics if the response cannot be deserialized. + async fn decode_json( + response: reqwest::Response, + ) -> Result { + response + .error_for_status() + .map_err(|err| CascadeControlError::BadStatusCode(err.status().unwrap()))? + .json() + .await + .map_err(CascadeControlError::Receive) + } + + /// Make a GET request, receiving JSON data. + #[tracing::instrument(level = "trace", skip_all)] + pub async fn get_json(&self, url: &str) -> Result + where + T: Debug + DeserializeOwned, + { + let url = self.base.join(url).unwrap(); + let response = self + .inner + .get(url.clone()) + .send() + .await + .map_err(CascadeControlError::Send)?; + let result = Self::decode_json(response).await; + tracing::trace!("GET {url:?} -> {result:?}"); + result + } + + /// Make a POST request, sending and receiving JSON data. + #[tracing::instrument(level = "trace", skip_all)] + pub async fn post_json(&self, url: &str, payload: P) -> Result + where + T: Debug + DeserializeOwned, + P: Debug + Serialize, + { + let url = self.base.join(url).unwrap(); + let response = self + .inner + .post(url.clone()) + .json(&payload) + .send() + .await + .map_err(CascadeControlError::Send)?; + let result = Self::decode_json(response).await; + tracing::trace!("POST {url:?} with {payload:?} -> {result:?}"); + result + } + + /// Make a POST request, receiving JSON data. + #[tracing::instrument(level = "trace", skip_all)] + pub async fn post_recv_json(&self, url: &str) -> Result + where + T: Debug + DeserializeOwned, + { + let url = self.base.join(url).unwrap(); + let response = self + .inner + .post(url.clone()) + .send() + .await + .map_err(CascadeControlError::Send)?; + let result = Self::decode_json(response).await; + tracing::trace!("POST {url:?} -> {result:?}"); + result + } +} + +/// # Overall Control +impl Cascade { + /// Overall health. + #[tracing::instrument(level = "trace", skip(self), ret)] + pub async fn health(&self) -> Result { + self.control.get_json("health").await + } +} + +/// # Policy Control +#[allow(dead_code)] +impl Cascade { + /// The names of all known policies. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn policy_names(&self) -> Vec { + self.control + .get_json::("policy/") + .await + .unwrap() + .policies + } + + /// Information about a policy. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn policy_info(&self, name: &str) -> api::PolicyInfo { + self.control + .get_json::(&format!("policy/{name}")) + .await + .unwrap() + } + + /// Reload all policies. + #[allow(clippy::result_large_err)] + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn reload_policies(&self) -> Result { + self.control.post_recv_json("policy/reload").await.unwrap() + } +} + +/// # Zones Control +#[allow(dead_code)] +impl Cascade { + /// The names of all known zones. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn zone_names(&self) -> Vec { + self.control + .get_json::("zone/") + .await + .unwrap() + .zones + } + + /// The status of a zone. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn zone_status(&self, name: &str) -> Result { + self.control + .get_json(&format!("zone/{name}/status")) + .await + .unwrap() + } + + /// The history of important events for a zone. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn zone_history( + &self, + name: &str, + ) -> Result { + self.control + .get_json(&format!("zone/{name}/history")) + .await + .unwrap() + } + + /// Add a new zone. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn add_zone( + &self, + cmd: api::ZoneAdd, + ) -> Result { + self.control.post_json("zone/add", cmd).await.unwrap() + } + + /// Remove a zone. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn remove_zone( + &self, + name: &str, + ) -> Result { + self.control + .post_recv_json(&format!("zone/{name}/remove")) + .await + .unwrap() + } + + /// Reload a zone. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn reload_zone( + &self, + name: &str, + ) -> Result { + self.control + .post_recv_json(&format!("zone/{name}/reload")) + .await + .unwrap() + } + + /// Start moving a zone to maintenance mode. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn start_maintenance_for_zone(&self, name: &str) -> api::ZoneMaintenanceModeResult { + self.control + .post_recv_json(&format!("zone/{name}/maintenance/enable")) + .await + .unwrap() + } + + /// Restore a zone from (moving to) maintenance mode. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn stop_maintenance_for_zone(&self, name: &str) -> api::ZoneMaintenanceModeResult { + self.control + .post_recv_json(&format!("zone/{name}/maintenance/disable")) + .await + .unwrap() + } + + /// Reset the pipeline for a zone. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn reset_pipeline(&self, name: &str) -> api::ZoneResetResult { + self.control + .post_recv_json(&format!("zone/{name}/reset")) + .await + .unwrap() + } + + /// Override a unsigned hard-halt for a zone. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn override_unsigned_hard_halt(&self, name: &str) -> api::ZoneOverrideResult { + self.control + .post_recv_json(&format!("zone/{name}/unsigned/override")) + .await + .unwrap() + } + + /// Override a signed hard-halt for a zone. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn override_signed_hard_halt(&self, name: &str) -> api::ZoneOverrideResult { + self.control + .post_recv_json(&format!("zone/{name}/signed/override")) + .await + .unwrap() + } + + /// Manually approve an unsigned zone instance pending review. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn approve_unsigned(&self, name: &str, serial: api::Serial) -> api::ZoneReviewResult { + self.control + .post_recv_json(&format!("zone/{name}/unsigned/{serial}/approve")) + .await + .unwrap() + } + + /// Manually approve a signed zone instance pending review. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn approve_signed(&self, name: &str, serial: api::Serial) -> api::ZoneReviewResult { + self.control + .post_recv_json(&format!("zone/{name}/signed/{serial}/approve")) + .await + .unwrap() + } + + /// Manually reject an unsigned zone instance pending review. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn reject_unsigned(&self, name: &str, serial: api::Serial) -> api::ZoneReviewResult { + self.control + .post_recv_json(&format!("zone/{name}/unsigned/{serial}/reject")) + .await + .unwrap() + } + + /// Manually reject a signed zone instance pending review. + #[tracing::instrument(level = "debug", skip(self), ret)] + pub async fn reject_signed(&self, name: &str, serial: api::Serial) -> api::ZoneReviewResult { + self.control + .post_recv_json(&format!("zone/{name}/signed/{serial}/reject")) + .await + .unwrap() + } +} + +//----------- Starting Cascade ------------------------------------------------- + +/// Start Cascade and return the Docker exec ID. +async fn start(container: &Container, config: &CascadeConfig) -> String { + let command = strs![ + "/usr/local/bin/cascaded", + "--config", + "/test/cascade/config.toml", + "--state", + "/test/cascade/state.db", + ]; + + let mut env = None::>; + if let Some(time) = &config.faketime { + // Set to seconds since Unix epoch. + let unixtime = time.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let unixtime = unixtime.as_secs(); + env.get_or_insert_default() + .push(format!("CASCADE_FAKETIME={unixtime}")); + } + + let exec_cfg = ExecConfig { + cmd: Some(command), + working_dir: Some("/test/cascade".into()), + env, + ..Default::default() + }; + + let exec_id = container + .docker + .create_exec(&container.id, exec_cfg) + .await + .unwrap() + .id; + + let StartExecResults::Attached { output, input: _ } = + container.docker.start_exec(&exec_id, None).await.unwrap() + else { + unreachable!("Did not enable `detached`") + }; + + tokio::spawn(log_exec_output(container, &exec_id, output)); + + exec_id +} + +type LogOutputResult = Result; + +/// Log unexpected output from Docker exec. +fn log_exec_output( + container: &Container, + exec_id: &str, + mut output: Pin + Send>>, +) -> impl Future + Send + use<> { + let span = tracing::debug_span!( + parent: tracing::Span::none(), + "cascade_output", + %container, + exec_id); + + async move { + while let Some(event) = output.next().await { + match event { + Ok(LogOutput::StdOut { message }) => { + if let Ok(text) = std::str::from_utf8(&message) { + tracing::debug!(text, "stdout"); + } else { + tracing::debug!(text = ?message.utf8_chunks(), "stdout"); + } + } + Ok(LogOutput::StdErr { message }) => { + if let Ok(text) = std::str::from_utf8(&message) { + tracing::debug!(text, "stderr"); + } else { + tracing::debug!(text = ?message.utf8_chunks(), "stderr"); + } + } + Ok(other) => { + tracing::debug!(?other); + } + Err(error) => { + tracing::error!("Listening failed: {error}") + } + } + } + } + .instrument(span) +} + +//------------------------------------------------------------------------------ + +/// Configuration for launching Cascade. +#[derive(Debug, Default)] +pub struct CascadeConfig { + /// The fake time to set. + pub faketime: Option, +} + +/// An error controlling Cascade. +#[derive(Debug)] +pub enum CascadeControlError { + /// Could not send the request. + Send(reqwest::Error), + + /// A bad status code was received. + BadStatusCode(reqwest::StatusCode), + + /// Could not fetch or decode a body. + Receive(reqwest::Error), +} + +impl fmt::Display for CascadeControlError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + CascadeControlError::Send(error) => { + write!(f, "Could not send an HTTP request: {error}") + } + CascadeControlError::BadStatusCode(status_code) => { + write!(f, "HTTP request failed with status code {status_code}") + } + CascadeControlError::Receive(error) => { + write!(f, "Could not receive HTTP response: {error}") + } + } + } +} diff --git a/tests/integration/infra/container.rs b/tests/integration/infra/container.rs new file mode 100644 index 00000000..d06eb512 --- /dev/null +++ b/tests/integration/infra/container.rs @@ -0,0 +1,497 @@ +//! Docker container control. + +use std::{ + collections::HashMap, + fmt, + io::{BufWriter, Write}, + net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, + path::Path, + sync::Arc, + time::SystemTime, +}; + +use bollard::{ + Docker, + plugin::{ContainerCreateBody, ContainerCreateResponse, HostConfig, Mount, MountType}, + query_parameters::{ + CreateContainerOptions, DownloadFromContainerOptionsBuilder, RemoveContainerOptionsBuilder, + }, +}; +use bytes::Bytes; +use domain::{ + base::{Message, MessageBuilder, Name, Rtype}, + net::client::request::{RequestMessage, RequestMessageMulti, SendRequest, SendRequestMulti}, + tsig, +}; +use futures_util::StreamExt; +use tracing::Instrument; + +use super::{Image, ports, strs}; + +#[cfg(doc)] +use super::TestConfig; + +//----------- ContainerBuilder ------------------------------------------------- + +/// A builder for starting a new [`Container`]. +pub struct ContainerBuilder<'image> { + /// The image to build on. + image: &'image Image, + + /// A name to assign the container. + name: Option>, + + /// The path to the Cascade daemon binary. + /// + /// By default, fetched from the `CARGO_BIN_EXE_cascaded` env var. + daemon_path: Option>, + + /// Environment variables to set in the container. + /// + /// [`None`] explicitly unsets a variables. + env: HashMap, Option>>, +} + +impl<'image> ContainerBuilder<'image> { + /// Construct a new [`ContainerBuilder`]. + pub fn new(image: &'image Image) -> Self { + Self { + image, + name: None, + daemon_path: None, + env: HashMap::from_iter([("RUST_BACKTRACE".into(), Some("1".into()))]), + } + } + + /// Set a name for the container. + #[expect(dead_code)] + pub fn name(mut self, name: impl Into>) -> Self { + self.name = Some(name.into()); + self + } + + /// Add an environment variable. + #[expect(dead_code)] + pub fn env(mut self, key: impl Into>, value: impl Into>) -> Self { + let _ = self.env.insert(key.into(), Some(value.into())); + self + } + + /// Build a container using this configuration. + pub fn build(&self) -> impl Future + Send + use<> { + let docker = self.image.docker.clone(); + let image_name = self.image.name.clone(); + let name = self.name.clone(); + + let daemon_path = self + .daemon_path + .clone() + .map(Into::into) + .or_else(|| std::env::var("CARGO_BIN_EXE_cascaded").ok()) + .unwrap_or_else(|| { + let repo_path = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + format!("{repo_path}/target/debug/cascaded") + }); + + let env = self + .env + .iter() + .map(|(k, v)| match v { + Some(v) => format!("{k}={v}"), + None => format!("{k}"), + }) + .collect::>(); + + let span = tracing::debug_span!("build_container"); + async move { + // Expose all known ports. + let exposed_ports = ports::all() + .into_iter() + .map(|p| format!("{p}")) + .collect::>(); + + let options = Some(CreateContainerOptions { + name: name.map(Into::into), + ..Default::default() + }); + let body = ContainerCreateBody { + // These ports will be externally accessible, but they won't + // be connected to ports on the host. We will figure out the + // container's IP address and talk to it there. + exposed_ports: Some(exposed_ports), + env: Some(env), + image: Some(image_name.into()), + host_config: Some(HostConfig { + mounts: Some(vec![Mount { + target: Some("/usr/local/bin/cascaded".into()), + source: Some(daemon_path), + typ: Some(MountType::BIND), + read_only: Some(true), + ..Default::default() + }]), + // Use the custom system resolver. + dns: Some(strs!["127.0.0.1"]), + // TODO: These were copied from an old, hand-written + // `resolv.conf` file. Are they still needed? + dns_options: Some(strs!["edns0", "trust-ad"]), + ..Default::default() + }), + ..Default::default() + }; + let output = docker.create_container(options, body).await.unwrap(); + let ContainerCreateResponse { id, warnings } = output; + for w in warnings { + tracing::warn!(msg = w, "warning during creation"); + } + + // The container must be started before we can exec commands in + // it. Starting causes an initial command to be executed; when the + // command finishes, the container will be stopped again. We don't + // want these semantics. As a workaround, the `Dockerfile` sets + // the entrypoint to `sleep inf`. + docker.start_container(&id, None).await.unwrap(); + + let (details, resolver, parent, primary, secondary) = tokio::join!( + docker.inspect_container(&id, None), + super::UnboundResolver::start(&docker, &id), + super::BindParent::start(&docker, &id), + super::NsdPrimary::start(&docker, &id), + super::NsdSecondary::start(&docker, &id), + ); + + let details = details.unwrap(); + + // If `self.name` was empty, Docker will provide a name for us. + // Read from its output even if `self.name` was not empty. + let mut name = details.name.unwrap(); + // `name` might start with `/` because of a historical quirk in + // the Docker API, see `ContainerInspectResponse`. + if name.starts_with("/") { + name.replace_range(..1, ""); + } + + // TODO: Use `details.created`? + let start_time = SystemTime::now(); + + // Determine IP addresses to reach the container so that we can + // access its exposed ports to talk to running services. + let networks = details.network_settings.unwrap().networks.unwrap(); + let networks = networks.into_iter().collect::>(); + let [(_name, network)] = &*networks else { + panic!("Container is attached to more than one network") + }; + let ipv4_addr = network + .ip_address + .as_ref() + .unwrap() + .parse::() + .unwrap(); + let ipv6_addr = network + .global_ipv6_address + .as_ref() + .filter(|addr| !addr.is_empty()) + .map(|addr| addr.parse::().unwrap()); + + tracing::debug!(id, name, "Started container"); + + Container { + docker, + id: id.into(), + name: name.into(), + ipv4_addr, + ipv6_addr, + start_time, + resolver, + parent, + primary, + secondary, + dropped: false, + } + } + .instrument(span) + } +} + +//----------- Container -------------------------------------------------------- + +/// A Docker container prepared for tests. +pub struct Container { + /// A client for controlling Docker. + pub docker: Arc, + + /// The ID of the container. + pub id: Box, + + /// The name of the container. + pub name: Box, + + /// The IPv4 address of the container. + pub ipv4_addr: Ipv4Addr, + + /// The IPv6 address of the container (if any). + pub ipv6_addr: Option, + + /// When the container was started. + pub start_time: SystemTime, + + /// The system resolver. + #[expect(dead_code)] + pub resolver: super::UnboundResolver, + + /// The parent name server. + #[expect(dead_code)] + pub parent: super::BindParent, + + /// The primary name server. + #[expect(dead_code)] + pub primary: super::NsdPrimary, + + /// The secondary name server. + #[expect(dead_code)] + pub secondary: super::NsdSecondary, + + /// Whether the container has been dropped manually. + dropped: bool, +} + +impl Container { + /// The container's IP address. + /// + /// Returns an IPv6 address if possible, otherwise falls back to IPv4. + pub const fn ip_addr(&self) -> IpAddr { + match self.ipv6_addr { + Some(addr) => IpAddr::V6(addr), + None => IpAddr::V4(self.ipv4_addr), + } + } + + /// Query a DNS server. + pub async fn dns_query( + &self, + port: ports::DnsPort, + name: &str, + rtype: Rtype, + tsig_key: Option>, + ) -> Result, domain::net::client::request::Error> { + let client = self.dns_client(port, tsig_key); + + let mut msg = MessageBuilder::new_vec(); + msg.header_mut().set_rd(true); + msg.header_mut().set_ad(true); + let mut msg = msg.question(); + msg.push((Name::vec_from_str(name).unwrap(), rtype)) + .unwrap(); + let req = RequestMessage::new(msg).unwrap(); + + client.send_request(req).get_response().await + } + + /// Build a simple DNS client for single-response requests. + pub fn dns_client( + &self, + port: ports::DnsPort, + tsig_key: Option>, + ) -> Box>> + Send + Sync> { + use domain::net::client; + + let addr = SocketAddr::new(self.ip_addr(), port.0); + let udp_conn = client::protocol::UdpConnect::new(addr); + let tcp_conn = client::protocol::TcpConnect::new(addr); + if let Some(tsig_key) = tsig_key { + let (client, transport) = client::dgram_stream::Connection::new(udp_conn, tcp_conn); + tokio::task::spawn(transport.run()); + Box::new(client::tsig::Connection::new(tsig_key, client)) as _ + } else { + let (client, transport) = client::dgram_stream::Connection::new(udp_conn, tcp_conn); + tokio::task::spawn(transport.run()); + Box::new(client) as _ + } + } + + /// Build a DNS client for XFR requests. + #[allow(dead_code)] + pub async fn dns_xfr_client( + &self, + port: ports::DnsPort, + tsig_key: Option>, + ) -> Box>> + Send + Sync> { + use domain::net::client; + + let addr = SocketAddr::new(self.ip_addr(), port.0); + let tcp_conn = tokio::net::TcpStream::connect(addr).await.unwrap(); + if let Some(tsig_key) = tsig_key { + let (client, transport) = client::stream::Connection::< + RequestMessage>, + client::tsig::RequestMessage>, Arc>, + >::new(tcp_conn); + tokio::task::spawn(transport.run()); + Box::new(client::tsig::Connection::new(tsig_key, client)) as _ + } else { + let (client, transport) = client::stream::Connection::< + RequestMessage>, + RequestMessageMulti>, + >::new(tcp_conn); + tokio::task::spawn(transport.run()); + Box::new(client) as _ + } + } + + /// Dump the contents of the container. + /// + /// The contents of the specified path in the container will be snapshotted + /// as a tarball and saved to the user's current directory, with a unique + /// filename. + #[expect(dead_code)] + pub async fn dump(&self, path: &str) -> Result<(), bollard::errors::Error> { + Self::dump_impl(&self.docker, &self.id, &self.name, &self.start_time, path).await + } + + #[tracing::instrument(level = "trace", name = "dump")] + async fn dump_impl( + docker: &Docker, + id: &str, + name: &str, + start_time: &SystemTime, + path: &str, + ) -> Result<(), bollard::errors::Error> { + tracing::trace!("Dumping contents of container"); + + let options = Some( + DownloadFromContainerOptionsBuilder::new() + .path(path) + .build(), + ); + let stream = docker.download_from_container(id, options); + + let max_size_setting = super::CURRENT_CONFIG.get().unwrap().max_dump_size; + let max_size = max_size_setting.unwrap_or(2 << 20); + + let mut file = tempfile::Builder::new().tempfile_in(".")?; + let mut writer = BufWriter::new(&mut file); + let mut size = 0usize; + + let mut stream = std::pin::pin!(stream); + while let Some(chunk) = stream.next().await { + let chunk = match chunk { + Ok(chunk) => chunk, + Err(error) => { + tracing::error!("Error while fetching tarball: {error}"); + return Err(error); + } + }; + + let new_total = size + chunk.len(); + if new_total > max_size { + tracing::error!("Truncating dump to {max_size}B"); + if max_size_setting.is_none() { + tracing::warn!("See the `max-dump-size` setting"); + } + let trunc_len = max_size - size; + writer.write_all(&chunk[..trunc_len])?; + break; + } + + tracing::trace!(size = chunk.len(), new_total, "Saving chunk"); + writer.write_all(&chunk)?; + size = new_total; + } + + writer.flush()?; + std::mem::drop(writer); + + let offset = start_time.elapsed().unwrap().as_millis() as u32; + let target = format!("./test-dump-{name}-{offset}"); + file.persist(&target).unwrap(); + + tracing::info!("Dumped {:?}", Path::new(&target).canonicalize().unwrap()); + + Ok(()) + } + + /// Clean up the container. + /// + /// This is performed automatically (under certain conditions) on drop. + #[expect(dead_code)] + pub async fn cleanup(&mut self) { + Self::cleanup_impl(&self.docker, &self.id).await; + self.dropped = true; + } + + #[tracing::instrument(level = "trace", name = "cleanup")] + async fn cleanup_impl(docker: &Docker, id: &str) { + tracing::trace!("Removing container"); + let result = docker + .remove_container( + id, + Some(RemoveContainerOptionsBuilder::new().force(true).build()), + ) + .await; + if let Err(error) = result { + tracing::error!("Failed to remove container: {error}"); + } + + tracing::debug!("Removed container"); + } +} + +impl Drop for Container { + /// Clean up the container on drop. + /// + /// The container is stopped, killed, and removed asynchronously. + /// + /// If a panic occurred and [`TestConfig::leave_containers_on_failure`] is + /// set, the container is not removed. + #[tracing::instrument(level = "trace")] + fn drop(&mut self) { + if self.dropped { + // Nothing to do. + return; + } + + let drop_span = tracing::debug_span!("drop_container"); + let mut dump = false; + let mut cleanup = true; + + if std::thread::panicking() { + // A failure has occurred. Dump the container data out for + // inspection, and determine whether to remove it. + dump = !drop_span.is_disabled(); + let config = super::CURRENT_CONFIG.get().unwrap(); + match config.leave_containers_on_failure { + Some(true) => { + tracing::info!(id = %self.id, name = %self.name, addr = %self.ip_addr(), "Leaving container"); + cleanup = false; + } + Some(false) => {} + None => { + tracing::warn!("Cleaning up container, see `leave-containers-on-failure`"); + } + } + } + + let docker = self.docker.clone(); + let id = self.id.clone(); + let name = self.name.clone(); + let start_time = self.start_time; + super::async_drop(drop_span, async move { + if dump { + let _ = Self::dump_impl(&docker, &id, &name, &start_time, "/test").await; + } + if cleanup { + Self::cleanup_impl(&docker, &id).await; + } + }); + } +} + +impl fmt::Debug for Container { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.name) + } +} + +impl fmt::Display for Container { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.name) + } +} diff --git a/tests/integration/infra/image.rs b/tests/integration/infra/image.rs new file mode 100644 index 00000000..ccc1ccc5 --- /dev/null +++ b/tests/integration/infra/image.rs @@ -0,0 +1,227 @@ +//! Building and managing the Docker image. + +use std::{ + fmt, + path::{Path, PathBuf}, + sync::Arc, +}; + +use bollard::{ + plugin::{BuildInfo, BuildInfoAux, ImageId}, + query_parameters::{BuildImageOptionsBuilder, BuilderVersion}, +}; +use futures_util::StreamExt; + +//----------- ImageBuilder ----------------------------------------------------- + +/// A builder for an [`Image`]. +pub struct ImageBuilder { + /// A client for controlling Docker. + docker: Arc, + + /// The name of the image. + name: Option>, + + /// The repository path. + /// + /// By default, fetched from the `CARGO_MANIFEST_DIR` env var. + repo_path: Option>, +} + +impl ImageBuilder { + /// Construct a new [`ImageBuilder`]. + pub fn new(docker: Arc) -> Self { + Self { + docker, + name: None, + repo_path: None, + } + } + + /// Override the name of the image. + #[expect(dead_code)] + pub fn name(mut self, name: impl Into>) -> Self { + self.name = Some(name.into()); + self + } + + /// Override the repository path. + #[expect(dead_code)] + pub fn repo_path(mut self, repo_path: impl Into>) -> Self { + self.repo_path = Some(repo_path.into()); + self + } + + /// Build the image using this configuration. + #[tracing::instrument(level = "info", name = "build_image", skip_all)] + pub async fn build(self) -> Image { + tracing::info!("Initiating build"); + + let docker = self.docker; + + let name = self + .name + .unwrap_or_else(|| "nlnetlabs/cascade-tests-runner".into()); + + let repo_path = self.repo_path.unwrap_or_else(|| { + PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").unwrap()).into() + }); + + tracing::debug!("Preparing image context"); + + // Build the context tarball in memory without streaming. + // It's very small because its size heavily affects rebuild times. + let mut context = tar::Builder::new(vec![]); + context.follow_symlinks(false); + context.sparse(false); + context.mode(tar::HeaderMode::Deterministic); + context + .append_path_with_name(repo_path.join("tests/integration/Dockerfile"), "Dockerfile") + .unwrap(); + context + .append_dir_all(".", repo_path.join("tests/integration/data")) + .unwrap(); + let body = context.into_inner().unwrap(); + let body = bollard::body_full(body.into()); + + tracing::debug!("Passing on to Docker"); + + let session = uuid::Uuid::new_v4(); + let options = BuildImageOptionsBuilder::new() + .t(&name) + .version(BuilderVersion::BuilderBuildKit) + .session(&session.to_string()) + .build(); + + // Consume build info logs and wait. + let mut state = BuildState::default(); + // NOTE: `stream` borrows `docker` and confuses the borrow checker. + { + let stream = docker.build_image(options, None, Some(body)); + let mut stream = std::pin::pin!(stream); + + while let Some(info) = stream.next().await { + state.consume(info); + } + } + + let Some(id) = state.image_id else { + panic!("Build finished without errors but missing image ID"); + }; + + tracing::info!("Built image"); + + Image { docker, name, id } + } +} + +//----------- Image ------------------------------------------------------------ + +/// A prepared Docker image. +pub struct Image { + /// A client for controlling Docker. + pub docker: Arc, + + /// The name of the image. + pub name: Box, + + /// The ID of the built image. + #[expect(dead_code)] + pub id: Box, +} + +//------------------------------------------------------------------------------ + +/// The state of an image build. +/// +/// This accumulates [`BuildInfo`] data, saving relevant information and +/// logging out the rest. +#[derive(Default)] +struct BuildState { + /// The image ID that has been built. + image_id: Option>, +} + +impl BuildState { + /// Consume the next build info message. + fn consume(&mut self, info: Result) { + let info = match info { + Ok(info) => info, + Err(err) => { + tracing::error!("Error while watching build: {err:?}"); + panic!("Could not build image") + } + }; + + tracing::trace!(?info, "build info"); + + let Some(id) = info.id else { + tracing::warn!("Bug: missing ID in build info"); + return; + }; + + match &*id { + "moby.buildkit.trace" => { + let Some(BuildInfoAux::BuildKit(resp)) = info.aux else { + tracing::warn!("Bug: Missing BuildKit aux data"); + return; + }; + + fn digest(mut digest: &str) -> impl fmt::Display { + if let Some(s) = digest.strip_prefix("sha256:") { + digest = s; + } + format!("{digest:.8}") + } + + for v in resp.vertexes { + if v.started.is_none() { + tracing::info!("[{}] {}", digest(&v.digest), v.name); + } + } + + for s in resp.statuses { + if s.started.is_none() { + tracing::info!( + "[{}] {} {}/{}", + digest(&s.vertex), + s.id, + s.current, + s.total + ); + } + } + + for l in resp.logs { + if let Ok(msg) = std::str::from_utf8(&l.msg) { + tracing::info!("[{}] {msg}", digest(&l.vertex)); + } else { + let msg = l.msg.utf8_chunks(); + tracing::info!("[{}] {msg:?}", digest(&l.vertex)); + } + } + + for w in resp.warnings { + if let Ok(msg) = std::str::from_utf8(&w.short) { + tracing::warn!("[{}] {msg}", digest(&w.vertex)); + } else { + let msg = w.short.utf8_chunks(); + tracing::warn!("[{}] {msg:?}", digest(&w.vertex)); + } + } + } + + "moby.image.id" => { + let Some(BuildInfoAux::Default(ImageId { id: Some(id) })) = info.aux else { + tracing::warn!("Bug: Missing image ID"); + return; + }; + self.image_id = Some(id.into()); + } + + _ => { + tracing::warn!("Bug: Unrecognized build info ID {id:?}"); + } + } + } +} diff --git a/tests/integration/infra/mod.rs b/tests/integration/infra/mod.rs new file mode 100644 index 00000000..cc4e49f0 --- /dev/null +++ b/tests/integration/infra/mod.rs @@ -0,0 +1,75 @@ +//! Infrastructure for integration tests. + +use std::{fmt::Debug, sync::OnceLock, time::Duration}; + +mod image; +pub use image::*; + +mod container; +pub use container::*; + +mod cascade; +pub use cascade::*; + +mod services; +pub use services::*; + +pub mod ports; + +mod test; +pub use test::*; + +pub mod runtime; +pub use runtime::async_drop; + +/// Repeat a measurement until it satisfies a predicate. +/// +/// ## Panics +/// +/// Panics if the measured object does not satisfy the predicate for too long. +pub async fn poll( + mut prepare: impl FnMut() -> S, + mut measure: impl AsyncFnMut(S) -> T, + pred: impl Fn(&T) -> bool, +) -> T { + let timeout = Duration::from_secs(10); + let frequency = Duration::from_millis(100); + + let mut last_seen = None::; + let result = tokio::time::timeout(timeout, async { + loop { + let state = (prepare)(); + let obj = last_seen.insert(measure(state).await); + if (pred)(obj) { + return last_seen.take().unwrap(); + } + tokio::time::sleep(frequency).await; + } + }) + .await; + + match result { + Ok(obj) => obj, + Err(_) => { + tracing::error!(?last_seen, "Polling failed"); + panic!("Polling failed") + } + } +} + +/// Test configuration. +#[derive(Debug, Default)] +pub struct TestConfig { + /// Correct tests where data mismatches occur. + #[expect(dead_code)] + pub bless: Option, + + /// Leave containers behind on failure. + pub leave_containers_on_failure: Option, + + /// The maximum size of a dumped tarball, in bytes. + pub max_dump_size: Option, +} + +/// The configuration for the current invocation. +pub static CURRENT_CONFIG: OnceLock = OnceLock::new(); diff --git a/tests/integration/infra/ports.rs b/tests/integration/infra/ports.rs new file mode 100644 index 00000000..dd3687ab --- /dev/null +++ b/tests/integration/infra/ports.rs @@ -0,0 +1,152 @@ +//! Defining and communicating Internet ports. + +use std::fmt; + +//----------- Hard-coded port numbers ------------------------------------------ + +/// The system resolver. +pub const RESOLVER: DnsPort = DnsPort(53); + +/// The parent name server. +pub const PARENT: DnsPort = DnsPort(1053); + +/// The primary name server. +pub const PRIMARY: DnsPort = DnsPort(1055); + +/// The secondary name server. +pub const SECONDARY: DnsPort = DnsPort(1054); + +/// The Cascade remote control server. +pub const REMOTE_CONTROL: HttpPort = HttpPort(4539); + +/// The Cascade loaded review server. +pub const LOADED_REVIEW: DnsPort = DnsPort(4540); + +/// The Cascade signed review server. +pub const SIGNED_REVIEW: DnsPort = DnsPort(4541); + +/// The Cascade publication server. +pub const PUBLICATION: DnsPort = DnsPort(4542); + +/// All known ports. +pub fn all() -> impl IntoIterator { + [ + RESOLVER, + PARENT, + PRIMARY, + SECONDARY, + LOADED_REVIEW, + SIGNED_REVIEW, + PUBLICATION, + ] + .into_iter() + .flatten() + .chain(REMOTE_CONTROL) +} + +//----------- Typed ports ------------------------------------------------------ + +/// A DNS (TCP + UDP) port. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct DnsPort(pub u16); + +impl IntoIterator for DnsPort { + type Item = InPort; + type IntoIter = std::array::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + [InPort::Tcp(self.0), InPort::Udp(self.0)].into_iter() + } +} + +impl fmt::Display for DnsPort { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// An HTTP (TCP) port. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct HttpPort(pub u16); + +impl IntoIterator for HttpPort { + type Item = InPort; + type IntoIter = std::iter::Once; + + fn into_iter(self) -> Self::IntoIter { + std::iter::once(InPort::Tcp(self.0)) + } +} + +impl fmt::Display for HttpPort { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// A generic (TCP or UDP) Internet port. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum InPort { + /// Over TCP. + Tcp(u16), + /// Over UDP. + Udp(u16), +} + +impl IntoIterator for InPort { + type Item = InPort; + type IntoIter = std::iter::Once; + + fn into_iter(self) -> Self::IntoIter { + std::iter::once(self) + } +} + +impl fmt::Display for InPort { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + InPort::Tcp(p) => write!(f, "{p}/tcp"), + InPort::Udp(p) => write!(f, "{p}/udp"), + } + } +} + +/// A TCP port. +#[allow(dead_code)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TcpPort(pub u16); + +impl IntoIterator for TcpPort { + type Item = InPort; + type IntoIter = std::iter::Once; + + fn into_iter(self) -> Self::IntoIter { + std::iter::once(InPort::Tcp(self.0)) + } +} + +impl fmt::Display for TcpPort { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// A UDP port. +#[allow(dead_code)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct UdpPort(pub u16); + +impl IntoIterator for UdpPort { + type Item = InPort; + type IntoIter = std::iter::Once; + + fn into_iter(self) -> Self::IntoIter { + std::iter::once(InPort::Udp(self.0)) + } +} + +impl fmt::Display for UdpPort { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} diff --git a/tests/integration/infra/runtime.rs b/tests/integration/infra/runtime.rs new file mode 100644 index 00000000..a7531b0e --- /dev/null +++ b/tests/integration/infra/runtime.rs @@ -0,0 +1,82 @@ +//! The async runtime. + +use std::{convert::Infallible, pin::pin, time::Duration}; + +use tokio::{ + signal::unix::{SignalKind, signal}, + sync::Semaphore, +}; +use tracing::Instrument; + +/// Run a future in a Tokio runtime. +/// +/// Async drops will be executed, including on interrupt. +pub fn block_on(future: F) -> F::Output { + let runtime = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap(); + + let output = runtime.block_on(async { + let future = pin!(future); + let interruption = pin!(interruption()); + tokio::select! { + output = future => Some(output), + _ = interruption => None, + } + }); + + runtime.block_on(async { + const TIMEOUT: Duration = Duration::from_secs(5); + const WARNING_TIME: Duration = Duration::from_millis(500); + + let drops = pin!(ONGOING_ASYNC_DROPS.acquire_many(Semaphore::MAX_PERMITS as u32)); + let timeout = pin!(tokio::time::sleep(TIMEOUT)); + let warning = pin!(async move { + tokio::time::sleep(WARNING_TIME).await; + tracing::warn!("Waiting for async drops to finish..."); + std::future::pending::().await + }); + let interruption = pin!(interruption()); + + tokio::select! { + _ = drops => {}, + () = timeout => { + tracing::warn!("Cancelling over-running async drops"); + } + _ = warning => unreachable!(), + _ = interruption => {}, + } + }); + + output.unwrap_or_else(|| std::process::exit(1)) +} + +/// Wait for an interruption. +async fn interruption() { + let mut sigint = signal(SignalKind::interrupt()).unwrap(); + let mut sigterm = signal(SignalKind::terminate()).unwrap(); + + tokio::select! { + _ = sigint.recv() => {} + _ = sigterm.recv() => {} + } +} + +/// A counter of ongoing async drops. +/// +/// When an object needs to be dropped asynchronously, it takes a permit from +/// this semaphore and executes the drop code in a Tokio task. When it finishes, +/// it returns the semaphore. The top-level runner code will wait (up to some +/// limit) for all async drops to finish before exiting. +static ONGOING_ASYNC_DROPS: Semaphore = + Semaphore::const_new(Semaphore::MAX_PERMITS as u32 as usize); + +/// Execute drop glue asynchronously. +pub fn async_drop + Send + 'static>(span: tracing::Span, f: F) { + let drop_permit = ONGOING_ASYNC_DROPS.try_acquire().unwrap(); + tokio::spawn(async move { + f.instrument(span).await; + std::mem::drop(drop_permit); + }); +} diff --git a/tests/integration/infra/services.rs b/tests/integration/infra/services.rs new file mode 100644 index 00000000..7a4091a6 --- /dev/null +++ b/tests/integration/infra/services.rs @@ -0,0 +1,145 @@ +//! Supporting services. + +use bollard::{Docker, exec::StartExecOptions, plugin::ExecConfig}; + +//----------- UnboundResolver -------------------------------------------------- + +/// The system resolver (Unbound). +pub struct UnboundResolver { + /// The Docker exec ID. + #[expect(dead_code)] + exec_id: String, +} + +impl UnboundResolver { + /// Start the service. + #[tracing::instrument(level = "debug", skip_all)] + pub async fn start(docker: &Docker, container_id: &str) -> Self { + let exec_id = exec_detached( + docker, + container_id, + strs!["unbound", "-c", "/test/resolver/unbound.conf"], + "/test/resolver", + ) + .await; + Self { exec_id } + } +} + +//----------- BindParent ------------------------------------------------------- + +/// The parent name server (BIND). +pub struct BindParent { + /// The Docker exec ID. + #[expect(dead_code)] + exec_id: String, +} + +impl BindParent { + /// Start the service. + #[tracing::instrument(level = "debug", skip_all)] + pub async fn start(docker: &Docker, container_id: &str) -> Self { + let exec_id = exec_detached( + docker, + container_id, + strs![ + "named", + "-c", + "/test/parent/bind.conf", + "-d", + "1", + "-L", + "/test/parent/bind.log", + ], + "/test/parent", + ) + .await; + Self { exec_id } + } +} + +//----------- NsdPrimary ------------------------------------------------------- + +/// The primary name server (NSD). +pub struct NsdPrimary { + /// The Docker exec ID. + #[expect(dead_code)] + exec_id: String, +} + +impl NsdPrimary { + /// Start the service. + #[tracing::instrument(level = "debug", skip_all)] + pub async fn start(docker: &Docker, container_id: &str) -> Self { + let exec_id = exec_detached( + docker, + container_id, + strs!["nsd", "-c", "/test/primary/nsd.conf"], + "/test/primary", + ) + .await; + Self { exec_id } + } +} + +//----------- NsdSecondary ----------------------------------------------------- + +/// The secondary name server (NSD). +pub struct NsdSecondary { + /// The Docker exec ID. + #[expect(dead_code)] + exec_id: String, +} + +impl NsdSecondary { + /// Start the service. + #[tracing::instrument(level = "debug", skip_all)] + pub async fn start(docker: &Docker, container_id: &str) -> Self { + let exec_id = exec_detached( + docker, + container_id, + strs!["nsd", "-c", "/test/secondary/nsd.conf"], + "/test/secondary", + ) + .await; + Self { exec_id } + } +} + +//------------------------------------------------------------------------------ + +/// Start a detached process in a container. +/// +/// Returns the Docker exec ID. +#[tracing::instrument(level = "debug", ret)] +async fn exec_detached( + docker: &Docker, + container_id: &str, + command: Vec, + working_dir: &str, +) -> String { + let exec_cfg = ExecConfig { + cmd: Some(command), + working_dir: Some(working_dir.into()), + ..Default::default() + }; + let exec_id = docker.create_exec(container_id, exec_cfg).await.unwrap().id; + docker + .start_exec( + &exec_id, + Some(StartExecOptions { + detach: true, + ..Default::default() + }), + ) + .await + .unwrap(); + exec_id +} + +macro_rules! strs { + [$($e:expr),*$(,)?] => { + vec![$($e.to_string()),*] + }; +} +pub(crate) use strs; diff --git a/tests/integration/infra/test.rs b/tests/integration/infra/test.rs new file mode 100644 index 00000000..ea93e312 --- /dev/null +++ b/tests/integration/infra/test.rs @@ -0,0 +1,95 @@ +//! Defining and running tests. + +use std::{fmt, panic::AssertUnwindSafe, pin::Pin, sync::Arc}; + +use futures_util::FutureExt; +use tokio::task::JoinSet; +use tracing::Instrument; + +pub struct TestPatterns { + pub raw: Vec, +} + +pub struct Test { + pub name: String, + pub default_jobs: Vec, + pub exec: TestExec, +} + +type TestExec = Box, serde_json::Value) -> TestFuture>; +type TestFuture = Pin + Send + 'static>>; + +pub struct TestResult { + pub name: String, + pub job_value: serde_json::Value, + pub result: Result<(), ()>, +} + +impl Test { + /// Construct a new single-job test. + pub fn new + Send + 'static>( + name: impl Into, + exec: fn(Arc) -> F, + ) -> Self { + let name = name.into(); + Self { + name: name.clone(), + default_jobs: vec![serde_json::Value::default()], + exec: Box::new(move |image: Arc, job_value| -> TestFuture { + let container = super::ContainerBuilder::new(&image).build(); + let name = name.clone(); + let span = tracing::info_span!(parent: tracing::Span::none(), "test", name); + Box::pin( + async move { + let fut = (exec)(Arc::new(container.await)); + let result = AssertUnwindSafe(fut).catch_unwind().await.map_err(|_| ()); + TestResult { + name, + job_value, + result, + } + } + .instrument(span), + ) as _ + }) as _, + } + } + + /// Run a test. + /// + /// The test will be matched against the given patterns, and on a hit, will + /// be spawned onto the given [`JoinSet`]. + pub fn run( + &self, + patterns: &TestPatterns, + join_set: &mut JoinSet, + image: &Arc, + ) { + let job_values = self.filter(patterns); + for value in job_values { + let name = Self::job_name(&self.name, &value); + println!("starting test {name}..."); + let job = (self.exec)(image.clone(), value); + join_set.spawn(job); + } + } + + /// Filter this test based on the given patterns. + fn filter(&self, patterns: &TestPatterns) -> Vec { + // TODO: Globs, fuzzy matching, parsing (fuzzy) JSON + if patterns.raw.is_empty() || patterns.raw.contains(&self.name) { + self.default_jobs.clone() + } else { + vec![] + } + } + + /// Format the name of a job. + pub fn job_name(name: &str, value: &serde_json::Value) -> impl fmt::Display + use<> { + if value.is_null() { + name.to_string() + } else { + format!("{name}:{value}") + } + } +} diff --git a/tests/integration/main.rs b/tests/integration/main.rs new file mode 100644 index 00000000..90a3bd0d --- /dev/null +++ b/tests/integration/main.rs @@ -0,0 +1,225 @@ +//! Integration tests. + +#![allow(clippy::disallowed_macros)] + +use std::{ + net::{Ipv4Addr, SocketAddr}, + process::ExitCode, + sync::Arc, +}; + +use camino::Utf8Path; +use cascade_api as api; +use clap::{ArgAction, arg, builder::BoolishValueParser, value_parser}; +use domain::base::{Rtype, iana::OptRcode}; +use tracing_subscriber::EnvFilter; + +mod infra; +use infra::{Test, TestPatterns, ports}; + +fn all_tests() -> Vec { + vec![add_zone_query(), remove_zone()] +} + +fn add_zone_query() -> Test { + Test::new("add-zone-query", |container| async move { + let cascade = Arc::new(infra::Cascade::start(&container).await); + + tracing::info!("Add a zone served by the NSD primary"); + let zone_name: api::ZoneName = "example.test".parse().unwrap(); + cascade + .add_zone(api::ZoneAdd { + name: zone_name.clone(), + source: api::ZoneSource::Server { + addr: SocketAddr::new(Ipv4Addr::LOCALHOST.into(), ports::PRIMARY.0), + tsig_key: None, + }, + policy: "default".into(), + key_imports: vec![], + }) + .await + .unwrap(); + + tracing::info!("Check zone status"); + let _ = infra::poll( + || cascade.clone(), + async |c| c.zone_status("example.test").await, + |status| status.as_ref().is_ok_and(|s| s.last_published.is_some()), + ) + .await; + + tracing::info!("Query the zone"); + let res = container + .dns_query(ports::PUBLICATION, "example.test", Rtype::SOA, None) + .await; + assert!(res.as_ref().is_ok_and(|r| r.no_error()), "{res:?}"); + + tracing::info!("The new zone should now be available via the resolver"); + let _ = infra::poll( + || container.clone(), + async |c| { + c.dns_query(ports::RESOLVER, "example.test", Rtype::SOA, None) + .await + }, + |res| res.as_ref().is_ok_and(|r| r.no_error()), + ) + .await; + }) +} + +fn remove_zone() -> Test { + Test::new("remove-zone", |container| async move { + let cascade = Arc::new(infra::Cascade::start(&container).await); + + tracing::info!("Add a zone"); + let zone_name: api::ZoneName = "example.test".parse().unwrap(); + cascade + .add_zone(api::ZoneAdd { + name: zone_name.clone(), + source: api::ZoneSource::Zonefile { + path: Utf8Path::new("/test/primary/example.test.zone").into(), + }, + policy: "default".into(), + key_imports: vec![], + }) + .await + .unwrap(); + + tracing::info!("Cascade should list the zone"); + infra::poll( + || cascade.clone(), + async |c| c.zone_names().await, + |names| names.contains(&zone_name), + ) + .await; + + tracing::info!("Check zone status"); + let _ = infra::poll( + || cascade.clone(), + async |c| c.zone_status("example.test").await, + |status| status.as_ref().is_ok_and(|s| s.last_published.is_some()), + ) + .await; + + tracing::info!("Querying the zone should succeed"); + let res = container + .dns_query(ports::PUBLICATION, "example.test", Rtype::SOA, None) + .await; + assert!(res.as_ref().is_ok_and(|r| r.no_error()), "{res:?}"); + + tracing::info!("Remove the zone"); + cascade.remove_zone("example.test").await.unwrap(); + + tracing::info!("Cascade should no longer list the zone"); + infra::poll( + || cascade.clone(), + async |c| c.zone_names().await, + |names| !names.contains(&zone_name), + ) + .await; + + tracing::info!("Querying the zone should now fail"); + let res = container + .dns_query(ports::PUBLICATION, "example.test", Rtype::SOA, None) + .await; + assert!( + res.as_ref() + .is_ok_and(|r| r.opt_rcode() == OptRcode::REFUSED), + "{res:?}" + ); + + tracing::info!("Check that Cascade is still running"); + assert!(cascade.health().await.unwrap().healthy); + }) +} + +fn main() -> ExitCode { + tracing_subscriber::fmt() + // Filter out unnecessary noise. + .with_env_filter( + EnvFilter::builder() + .with_default_directive(tracing::Level::WARN.into()) + .from_env_lossy() + .add_directive("h2=error".parse().unwrap()) + .add_directive("tonic=error".parse().unwrap()) + .add_directive("hyper_util=error".parse().unwrap()) + .add_directive("bollard=error".parse().unwrap()), + ) + .init(); + + let matches = clap::command!() + .arg(arg!([patterns] "Patterns for matching tests to run").action(ArgAction::Append)) + .arg( + arg!(-B --"bless" [BOOL] "When a data mismatch occurs, update the test's expectation") + .value_parser(BoolishValueParser::new()) + .num_args(0..=1) + .require_equals(true) + .default_missing_value("true"), + ) + .arg( + arg!(-L --"leave-containers-on-failure" [BOOL] "Leave Docker containers on failure") + .value_parser(BoolishValueParser::new()) + .num_args(0..=1) + .require_equals(true) + .default_missing_value("true"), + ) + .arg( + arg!(--"max-dump-size" "The maximum size of tarball dumps") + .required(false) + .value_parser(value_parser!(usize)), + ) + .get_matches(); + + let _ = infra::CURRENT_CONFIG.set(infra::TestConfig { + bless: matches.get_one("bless").copied(), + leave_containers_on_failure: matches.get_one("leave-containers-on-failure").copied(), + max_dump_size: matches.get_one("max-dump-size").copied(), + }); + + let patterns = TestPatterns { + raw: matches + .get_many::("patterns") + .into_iter() + .flatten() + .cloned() + .collect(), + }; + + infra::runtime::block_on(async { + let docker = Arc::new(bollard::Docker::connect_with_defaults().unwrap()); + + let image = Arc::new(infra::ImageBuilder::new(docker).build().await); + + let mut test_jobs = tokio::task::JoinSet::new(); + for test in all_tests() { + test.run(&patterns, &mut test_jobs, &image); + } + let mut success = 0; + let mut failure = 0; + while let Some(res) = test_jobs.join_next().await { + let res = res.unwrap(); + let name = Test::job_name(&res.name, &res.job_value); + if res.result.is_ok() { + println!("... test {name} passed"); + success += 1; + } else { + eprintln!("... test {name} failed!"); + failure += 1; + } + } + match (success, failure) { + (0, 0) => { + eprintln!("No tests matched the given patterns"); + ExitCode::FAILURE + } + (num, 0) => { + println!("{num} tests passed"); + ExitCode::SUCCESS + } + (s, f) => { + eprintln!("{s} tests passed, {f} tests failed"); + ExitCode::FAILURE + } + } + }) +}