From ec458ae95eec4f10724c55b41b91f593d067c49d Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Mon, 8 Jun 2026 15:55:55 -0400 Subject: [PATCH] feat(export): support s3 and configurable location for helm cache Add an `s3://` backend and a configurable location for the experimental helmTemplate export cache. - Replace `--helm-cache-dir` with `--helm-cache-path`, accepting a local path, `file://` URL, or `s3://bucket/prefix` URL; setting it enables the cache and overrides the default `/helm-cache` - Add `--helm-cache-on-error=warn|fail` to choose whether load/save failures warn and continue or abort the export - Abstract the cache behind a CacheLocation backend (local dir or S3 prefix); the S3 backend lists/gets entries on load and puts touched entries plus prunes stale ones on save Co-authored-by: Cursor --- Cargo.lock | 1168 ++++++++++++++++++++++- cmds/rtk/Cargo.toml | 4 + cmds/rtk/src/commands/export.rs | 12 + cmds/rtk/src/environments/export.rs | 71 +- cmds/rtk/src/environments/helm_cache.rs | 392 +++++++- cmds/rtk/tests/export_test.rs | 2 + 6 files changed, 1544 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 362d75773..4396282aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -144,6 +144,15 @@ dependencies = [ "object", ] +[[package]] +name = "arc-swap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" +dependencies = [ + "rustversion", +] + [[package]] name = "arraydeque" version = "0.5.1" @@ -223,6 +232,479 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-config" +version = "1.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33f815b73a3899c03b380d543532e5865f230dce9678d108dc10732a8682275" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sdk-sso", + "aws-sdk-ssooidc", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-schema", + "aws-smithy-types", + "aws-types", + "bytes 1.11.1", + "fastrand", + "hex", + "http 1.4.0", + "sha1 0.10.6", + "time", + "tokio", + "tracing", + "url", + "zeroize", +] + +[[package]] +name = "aws-credential-types" +version = "1.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f20799b373a1be121fe3005fba0c2090af9411573878f224df44b42727fcaf7" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + +[[package]] +name = "aws-lc-rs" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "aws-runtime" +version = "1.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ed8e8c52d2dc2390ad9f15647fe663f71e9780b4262c190fbb823a32721566" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes 1.11.1", + "bytes-utils", + "fastrand", + "http 0.2.12", + "http 1.4.0", + "http-body 0.4.6", + "http-body 1.0.1", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-s3" +version = "1.135.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f97e3e7e7d86fd26fcdc18bc382da5ca9e8b2ff8d54030d187fd0dac8a236d96" +dependencies = [ + "arc-swap", + "aws-credential-types", + "aws-runtime", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-checksums", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "bytes 1.11.1", + "fastrand", + "hex", + "hmac 0.13.0", + "http 0.2.12", + "http 1.4.0", + "http-body 1.0.1", + "lru", + "percent-encoding", + "regex-lite", + "sha2 0.11.0", + "tracing", + "url", +] + +[[package]] +name = "aws-sdk-sso" +version = "1.101.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b647baea49ff551960b904f905681e9b4765a6c4ea08631e89dc52d8bd3f5896" +dependencies = [ + "arc-swap", + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes 1.11.1", + "fastrand", + "http 0.2.12", + "http 1.4.0", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-ssooidc" +version = "1.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ae401c65ff288aa7873117fe535cd32b7b1bb0bc43751d28901a1d5f20636b9" +dependencies = [ + "arc-swap", + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes 1.11.1", + "fastrand", + "http 0.2.12", + "http 1.4.0", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "1.106.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c80de7bb7d03e9ca8c9fd7b489f20f3948d3f3be91a7953591347d238115408" +dependencies = [ + "arc-swap", + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-observability", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "fastrand", + "http 0.2.12", + "http 1.4.0", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae38512beae0ffee7010fc24e7a8a123c53efdfef42a61e80fda4882418dc71" +dependencies = [ + "aws-credential-types", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes 1.11.1", + "crypto-bigint", + "form_urlencoded", + "hex", + "hmac 0.13.0", + "http 0.2.12", + "http 1.4.0", + "p256", + "percent-encoding", + "sha2 0.11.0", + "subtle", + "time", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-async" +version = "1.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffcaf626bdda484571968400c326a244598634dc75fd451325a54ad1a59acfc" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-checksums" +version = "0.64.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e8e65f4f81fcccdeb6c3eca2af17ac21d421a1786a26a394aecf421d616d3a" +dependencies = [ + "aws-smithy-http", + "aws-smithy-types", + "bytes 1.11.1", + "crc-fast", + "hex", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "md-5", + "pin-project-lite", + "sha1 0.11.0", + "sha2 0.11.0", + "tracing", +] + +[[package]] +name = "aws-smithy-eventstream" +version = "0.60.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf09d74e5e32f76b8762da505a3cd59303e367a664ca67295387baa8c1d7548" +dependencies = [ + "aws-smithy-types", + "bytes 1.11.1", + "crc32fast", +] + +[[package]] +name = "aws-smithy-http" +version = "0.63.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1ab2dc1c2c3749ead27180d333c42f11be8b0e934058fb4b2258ee8dbe5231" +dependencies = [ + "aws-smithy-eventstream", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes 1.11.1", + "bytes-utils", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-http-client" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3ef8931ad1c98aa6a55b4256f847f3116090819844e0dd41ea682cac5dd2d3" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "h2 0.3.27", + "h2 0.4.13", + "http 0.2.12", + "http 1.4.0", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper 1.8.1", + "hyper-rustls 0.24.2", + "hyper-rustls 0.27.7", + "hyper-util", + "pin-project-lite", + "rustls 0.21.12", + "rustls 0.23.37", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.4", + "tower", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.62.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "701a947f4797e52a911e114a898667c746c39feea467bbd1abd7b3721f702ffa" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-schema", + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-observability" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06c2315d173edbf1920da8ba3a7189695827002e4c0fc961973ab1c54abca9c" +dependencies = [ + "aws-smithy-runtime-api", +] + +[[package]] +name = "aws-smithy-query" +version = "0.60.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a56d79744fb3edb5d722ef79d86081e121d3b9422cb209eb03aea6aa4f21ebd" +dependencies = [ + "aws-smithy-types", + "urlencoding", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e6f5caf6fea86f8c2206541ab5857cfcda9013426cdbe8fa0098b9e2d32182" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-http-client", + "aws-smithy-observability", + "aws-smithy-runtime-api", + "aws-smithy-schema", + "aws-smithy-types", + "bytes 1.11.1", + "fastrand", + "http 0.2.12", + "http 1.4.0", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "pin-project-lite", + "pin-utils", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9db177daa6ba8afb9ee1aefcf548c907abcf52065e394ee11a92780057fe0e8c" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api-macros", + "aws-smithy-types", + "bytes 1.11.1", + "http 0.2.12", + "http 1.4.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-runtime-api-macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d7396fd9500589e62e460e987ecb671bad374934e55ec3b5f498cc7a8a8a7b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "aws-smithy-schema" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7442cb268338f0eb8278140a107c046756aa01093d8ef5e99628d34ae09c94f5" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-types", + "http 1.4.0", +] + +[[package]] +name = "aws-smithy-types" +version = "1.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53f93074121a1be41317b9aa607143ae17900631f7f59a99f2b905d519d6783b" +dependencies = [ + "base64-simd", + "bytes 1.11.1", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.4.0", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "itoa", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.60.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce02add1aa3677d022f8adf81dcbe3046a95f17a1b1e8979c145cd21d3d22b3" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "1.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16bf10b03a3c01e6b3b7d47cd964e873ffe9e7d4e80fad16bd4c077cb068531" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-schema", + "aws-smithy-types", + "rustc_version", + "tracing", +] + [[package]] name = "backon" version = "1.6.0" @@ -234,6 +716,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.11.0" @@ -246,6 +734,22 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "bincode" version = "1.3.3" @@ -285,6 +789,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bon" version = "3.9.0" @@ -347,6 +860,16 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes 1.11.1", + "either", +] + [[package]] name = "cast" version = "0.3.0" @@ -360,6 +883,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -464,6 +989,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "colorchoice" version = "1.0.4" @@ -502,6 +1042,18 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "core-foundation" version = "0.10.1" @@ -533,6 +1085,25 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc-fast" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75b2483e97a5a7da73ac68a05b629f9c53cff58d8ed1c77866079e18b00dba5" +dependencies = [ + "digest 0.10.7", + "spin", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -606,6 +1177,18 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -616,6 +1199,24 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "darling" version = "0.23.0" @@ -668,6 +1269,26 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid 0.9.6", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + [[package]] name = "derive_more" version = "2.1.1" @@ -701,8 +1322,22 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "const-oid 0.9.6", + "crypto-common 0.1.7", + "subtle", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "const-oid 0.10.2", + "crypto-common 0.2.2", + "ctutils", ] [[package]] @@ -758,12 +1393,32 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "educe" version = "0.6.0" @@ -782,6 +1437,26 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encode_unicode" version = "1.0.0" @@ -891,6 +1566,16 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -934,6 +1619,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.32" @@ -1036,6 +1727,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1109,6 +1801,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "gtmpl" version = "0.7.1" @@ -1132,6 +1835,25 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes 1.11.1", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.13.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.13" @@ -1214,6 +1936,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hi-doc" version = "0.3.0" @@ -1242,6 +1970,24 @@ dependencies = [ "str_indices", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest 0.11.3", +] + [[package]] name = "hostname" version = "0.4.2" @@ -1274,6 +2020,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes 1.11.1", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -1293,7 +2050,7 @@ dependencies = [ "bytes 1.11.1", "futures-core", "http 1.4.0", - "http-body", + "http-body 1.0.1", "pin-project-lite", ] @@ -1309,6 +2066,39 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "typenum", +] + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes 1.11.1", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.8.1" @@ -1319,9 +2109,9 @@ dependencies = [ "bytes 1.11.1", "futures-channel", "futures-core", - "h2", + "h2 0.4.13", "http 1.4.0", - "http-body", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -1332,6 +2122,21 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.32", + "log", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-rustls" version = "0.27.7" @@ -1339,14 +2144,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.4.0", - "hyper", + "hyper 1.8.1", "hyper-util", "log", - "rustls", + "rustls 0.23.37", "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.4", "tower-service", "webpki-roots", ] @@ -1357,7 +2162,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper", + "hyper 1.8.1", "hyper-util", "pin-project-lite", "tokio", @@ -1375,13 +2180,13 @@ dependencies = [ "futures-channel", "futures-util", "http 1.4.0", - "http-body", - "hyper", + "http-body 1.0.1", + "hyper 1.8.1", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.3", "tokio", "tower-service", "tracing", @@ -1653,6 +2458,16 @@ dependencies = [ "syn", ] +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "jrsonnet" version = "0.5.0-pre97" @@ -1819,8 +2634,8 @@ dependencies = [ "serde-saphyr", "serde_json", "serde_yaml_with_quirks", - "sha1", - "sha2", + "sha1 0.10.6", + "sha2 0.10.9", "sha3", ] @@ -1932,7 +2747,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -1959,10 +2774,10 @@ dependencies = [ "either", "futures", "http 1.4.0", - "http-body", + "http-body 1.0.1", "http-body-util", - "hyper", - "hyper-rustls", + "hyper 1.8.1", + "hyper-rustls 0.27.7", "hyper-timeout", "hyper-util", "jiff", @@ -1970,7 +2785,7 @@ dependencies = [ "k8s-openapi", "kube-core", "pem", - "rustls", + "rustls 0.23.37", "secrecy", "serde", "serde_json", @@ -2170,6 +2985,16 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "md-5" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest 0.11.3", +] + [[package]] name = "md5" version = "0.8.0" @@ -2311,6 +3136,12 @@ dependencies = [ "serde", ] +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + [[package]] name = "num-integer" version = "0.1.46" @@ -2493,6 +3324,24 @@ dependencies = [ "syn", ] +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.9", +] + [[package]] name = "parking" version = "2.2.1" @@ -2582,6 +3431,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -2628,7 +3486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -2706,6 +3564,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "plotters" version = "0.3.7" @@ -2758,6 +3626,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -2777,6 +3651,15 @@ dependencies = [ "syn", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -2853,8 +3736,8 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", - "rustls", - "socket2", + "rustls 0.23.37", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -2873,7 +3756,7 @@ dependencies = [ "rand", "ring", "rustc-hash 2.1.1", - "rustls", + "rustls 0.23.37", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -2891,7 +3774,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.6.3", "tracing", "windows-sys 0.59.0", ] @@ -2924,7 +3807,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.5", ] [[package]] @@ -2934,7 +3817,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", ] [[package]] @@ -3047,6 +3939,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-lite" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" + [[package]] name = "regex-syntax" version = "0.8.10" @@ -3071,17 +3969,17 @@ dependencies = [ "futures-core", "futures-util", "http 1.4.0", - "http-body", + "http-body 1.0.1", "http-body-util", - "hyper", - "hyper-rustls", + "hyper 1.8.1", + "hyper-rustls 0.27.7", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", "quinn", - "rustls", + "rustls 0.23.37", "rustls-native-certs", "rustls-pki-types", "serde", @@ -3089,7 +3987,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.4", "tower", "tower-http", "tower-service", @@ -3099,6 +3997,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + [[package]] name = "ring" version = "0.17.14" @@ -3160,6 +4068,8 @@ version = "0.1.0" dependencies = [ "anyhow", "assert_matches", + "aws-config", + "aws-sdk-s3", "bon", "bytes 1.11.1", "clap", @@ -3169,7 +4079,7 @@ dependencies = [ "gtmpl", "http 1.4.0", "http-body-util", - "hyper", + "hyper 1.8.1", "indoc", "jrsonnet-evaluator", "jrsonnet-gcmodule", @@ -3197,7 +4107,7 @@ dependencies = [ "serde_json", "serde_yaml", "serde_yaml_with_quirks", - "sha2", + "sha2 0.10.9", "stats_alloc", "tabwriter", "tempfile", @@ -3261,17 +4171,30 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + [[package]] name = "rustls" version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.9", "subtle", "zeroize", ] @@ -3298,12 +4221,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustls-webpki" version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -3379,6 +4313,30 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secrecy" version = "0.10.3" @@ -3552,8 +4510,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -3563,8 +4532,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -3573,7 +4553,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest", + "digest 0.10.7", "keccak", ] @@ -3602,6 +4582,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.8" @@ -3638,6 +4628,16 @@ version = "2.0.0-alpha.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef784004ca8777809dcdad6ac37629f0a97caee4c685fcea805278d81dd8b857" +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "socket2" version = "0.6.3" @@ -3648,6 +4648,22 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -3862,6 +4878,36 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinystr" version = "0.8.2" @@ -3935,7 +4981,7 @@ dependencies = [ "mio", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] @@ -3951,13 +4997,23 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls", + "rustls 0.23.37", "tokio", ] @@ -4078,9 +5134,9 @@ dependencies = [ "base64 0.22.1", "bytes 1.11.1", "http 1.4.0", - "http-body", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-timeout", "hyper-util", "percent-encoding", @@ -4135,7 +5191,7 @@ dependencies = [ "bytes 1.11.1", "futures-util", "http 1.4.0", - "http-body", + "http-body 1.0.1", "iri-string", "mime", "pin-project-lite", @@ -4397,6 +5453,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.1" @@ -4409,6 +5475,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "vte" version = "0.14.1" @@ -4772,7 +5844,7 @@ dependencies = [ "futures", "http 1.4.0", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-util", "log", "once_cell", @@ -4877,6 +5949,12 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + [[package]] name = "xshell" version = "0.2.7" diff --git a/cmds/rtk/Cargo.toml b/cmds/rtk/Cargo.toml index 6f66fa596..099b37976 100644 --- a/cmds/rtk/Cargo.toml +++ b/cmds/rtk/Cargo.toml @@ -55,6 +55,10 @@ http = "1.4.0" tempfile = "3.10" either = "1.15.0" +# S3 backend for the experimental helmTemplate cache +aws-config = { version = "1", features = ["behavior-version-latest"] } +aws-sdk-s3 = "1" + [target.'cfg(target_os = "linux")'.dependencies] mimallocator = { workspace = true, optional = true } diff --git a/cmds/rtk/src/commands/export.rs b/cmds/rtk/src/commands/export.rs index b3891cd92..5be51b573 100644 --- a/cmds/rtk/src/commands/export.rs +++ b/cmds/rtk/src/commands/export.rs @@ -73,6 +73,16 @@ pub struct ExportArgs { #[arg(long)] pub helm_cache: bool, + /// Experimental: location to store the helmTemplate cache. Accepts a local + /// path, a `file://` URL, or an `s3://bucket/prefix` URL. Defaults to + /// `/helm-cache`. Setting this enables the helm cache. + #[arg(long)] + pub helm_cache_path: Option, + + /// Experimental: what to do when loading or saving the helm cache fails. + #[arg(long, default_value = "warn")] + pub helm_cache_on_error: String, + /// Regex filter on '/'. See https://tanka.dev/output-filtering #[arg(short = 't', long)] pub target: Vec, @@ -176,6 +186,8 @@ fn build_export_opts(args: ExportArgs) -> Result<(Vec, ExportOpts)> { merge_deleted_envs: args.merge_deleted_envs, show_timing: false, helm_cache: args.helm_cache, + helm_cache_path: args.helm_cache_path, + helm_cache_on_error: args.helm_cache_on_error.parse()?, }; Ok((paths, opts)) } diff --git a/cmds/rtk/src/environments/export.rs b/cmds/rtk/src/environments/export.rs index 41d70cc01..70b40e51d 100644 --- a/cmds/rtk/src/environments/export.rs +++ b/cmds/rtk/src/environments/export.rs @@ -20,7 +20,7 @@ use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rustc_hash::FxHashMap; use serde::Serialize; use serde_json::Value as JsonValue; -use tracing::{debug, trace}; +use tracing::{debug, trace, warn}; use super::{compile_target_matchers, keep_target, manifest_kind_name, TargetMatcher}; use crate::{ @@ -132,6 +132,13 @@ pub struct ExportOpts { /// Maintain a `helm-cache/` metadata directory in the output dir to cache /// `helmTemplate` results across runs and environments (experimental). pub helm_cache: bool, + /// Override the location used for the `helmTemplate` cache. Accepts a local + /// path, a `file://` URL, or an `s3://bucket/prefix` URL. Defaults to + /// `/helm-cache`. When set, the helm cache is enabled even if + /// `helm_cache` is false (experimental). + pub helm_cache_path: Option, + /// What to do when loading or saving the helm cache fails (experimental). + pub helm_cache_on_error: helm_cache::OnError, } impl Default for ExportOpts { @@ -152,6 +159,8 @@ impl Default for ExportOpts { merge_deleted_envs: vec![], show_timing: false, helm_cache: false, + helm_cache_path: None, + helm_cache_on_error: helm_cache::OnError::default(), } } } @@ -325,6 +334,47 @@ fn matches_target_patterns(manifest: &JsonValue, matchers: &[TargetMatcher]) -> } /// Export environments from given paths to the output directory +/// Resolve the helm-cache location from the options, if caching is enabled. +/// +/// An explicit `helm_cache_path` enables caching at that location (local or +/// `s3://`); otherwise `helm_cache` enables the default `/helm-cache` +/// directory. A bad `helm_cache_path` is treated according to `helm_cache_on_error`. +fn resolve_helm_cache_location(opts: &ExportOpts) -> Result> { + if let Some(ref raw) = opts.helm_cache_path { + match helm_cache::parse_location(raw) { + Ok(loc) => Ok(Some(loc)), + Err(err) => { + handle_helm_cache_error(opts.helm_cache_on_error, "configure", err)?; + Ok(None) + } + } + } else if opts.helm_cache { + Ok(Some(helm_cache::CacheLocation::Local( + helm_cache::cache_dir(&opts.output_dir), + ))) + } else { + Ok(None) + } +} + +/// Apply the configured severity to a helm-cache failure: either warn and +/// continue, or propagate the error to abort the export. +fn handle_helm_cache_error( + on_error: helm_cache::OnError, + action: &str, + err: anyhow::Error, +) -> Result<()> { + match on_error { + helm_cache::OnError::Warn => { + warn!("helm-cache: failed to {action} cache: {err:#}"); + Ok(()) + } + helm_cache::OnError::Fail => { + Err(err.context(format!("helm-cache: failed to {action} cache"))) + } + } +} + pub fn export(paths: &[PathBuf], opts: ExportOpts) -> Result { use std::time::Instant; let export_start = Instant::now(); @@ -431,11 +481,14 @@ pub fn export(paths: &[PathBuf], opts: ExportOpts) -> Result { // process-global in-memory cache (shared across all worker threads) and the // directory is removed so only entries touched this run are written back. // Done before the emptiness check so a stale cache dir does not trip it. - let helm_cache_dir = opts - .helm_cache - .then(|| helm_cache::cache_dir(&opts.output_dir)); - if let Some(ref dir) = helm_cache_dir { - helm_cache::load_and_clear(dir); + // An explicit --helm-cache-path enables caching and overrides the default + // `/helm-cache` location. It may point at a local directory or + // an `s3://` prefix. + let helm_cache_location = resolve_helm_cache_location(&opts)?; + if let Some(ref loc) = helm_cache_location { + if let Err(err) = helm_cache::load_and_clear(loc) { + handle_helm_cache_error(opts.helm_cache_on_error, "load", err)?; + } } // Check if directory is empty (if required by merge strategy) @@ -570,8 +623,10 @@ pub fn export(paths: &[PathBuf], opts: ExportOpts) -> Result { // Experimental helm-cache: persist the touched entries exactly once, now // that the parallel loop is done (single-threaded, so writes never race). - if let Some(ref dir) = helm_cache_dir { - helm_cache::save(dir); + if let Some(ref loc) = helm_cache_location { + if let Err(err) = helm_cache::save(loc) { + handle_helm_cache_error(opts.helm_cache_on_error, "save", err)?; + } } // Summarize results diff --git a/cmds/rtk/src/environments/helm_cache.rs b/cmds/rtk/src/environments/helm_cache.rs index c3c8a6aa6..2fc8707b0 100644 --- a/cmds/rtk/src/environments/helm_cache.rs +++ b/cmds/rtk/src/environments/helm_cache.rs @@ -1,38 +1,41 @@ -//! On-disk `helmTemplate` cache for exports (experimental). +//! On-disk / remote `helmTemplate` cache for exports (experimental). //! -//! The export driver maintains a single global `helm-cache/` metadata directory -//! inside the export output directory. It stores the rendered output of every -//! `helmTemplate` call under: +//! The export driver maintains a single global cache location that stores the +//! rendered output of every `helmTemplate` call as one JSON document per call: //! //! ```text -//! /helm-cache/.json +//! /.json //! ``` //! //! where `` is a hash of the entire `helmTemplate` call (release name, //! chart path + `Chart.yaml`, namespace, values, flags, `nameFormat`, ...) and //! the JSON file contains the map of all resources that call produced. //! +//! The cache location can be either a local directory or an S3 prefix, selected +//! via [`parse_location`]: +//! +//! - `file:///abs/path` or a bare path -> [`CacheLocation::Local`] +//! - `s3://bucket/prefix` -> [`CacheLocation::S3`] +//! //! The cache is global and is loaded and written exactly once per export run: //! //! 1. Before the parallel export loop, [`load_and_clear`] reads every cached //! entry into the process-global in-memory Helm cache (shared across all //! worker threads, so a chart rendered for one environment is reused by -//! every other) and then deletes the directory. It also begins recording -//! which cache keys get touched. +//! every other) and begins recording which cache keys get touched. For the +//! local backend it then deletes the directory so stale entries are pruned. //! 2. During evaluation, each `helmTemplate` call that hits the in-memory cache //! is served without invoking helm or parsing YAML, and its key is recorded //! as "touched" (across all threads). //! 3. After the parallel loop completes, [`save`] writes only the touched -//! entries back. Stale entries that were not referenced this run are pruned, -//! because the directory was deleted in step 1 and only touched keys are -//! rewritten. +//! entries back and prunes entries that were not referenced this run. use std::{ collections::HashSet, path::{Path, PathBuf}, }; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use tracing::{debug, warn}; use crate::jsonnet::evaluator::jrsonnet::builtins; @@ -40,37 +43,119 @@ use crate::jsonnet::evaluator::jrsonnet::builtins; /// Name of the metadata directory created inside the export output directory. pub const HELM_CACHE_DIR: &str = "helm-cache"; -/// Resolve the single global cache directory inside `output_dir`. +/// Where the helmTemplate cache is stored. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum CacheLocation { + /// A local directory of `.json` files. + Local(PathBuf), + /// An S3 bucket + key prefix. `prefix` is empty or ends with `/`. + S3 { bucket: String, prefix: String }, +} + +/// What to do when a cache load/save operation fails. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub enum OnError { + /// Log a warning and continue the export. + #[default] + Warn, + /// Abort the export with an error. + Fail, +} + +impl std::str::FromStr for OnError { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "warn" => Ok(Self::Warn), + "fail" => Ok(Self::Fail), + _ => bail!("invalid helm-cache-on-error value `{s}` (expected `warn` or `fail`)"), + } + } +} + +/// Resolve the default local cache directory inside `output_dir`. pub fn cache_dir(output_dir: &Path) -> PathBuf { output_dir.join(HELM_CACHE_DIR) } -/// Begin recording touched cache keys for the whole run, preload any previously -/// persisted entries into the global in-memory cache, then delete the directory -/// so only entries touched this run are written back. +/// Parse a cache path into a [`CacheLocation`]. /// -/// Best-effort: a failure to read the existing cache is logged and ignored. -/// Must be called once, before the parallel export loop. -pub fn load_and_clear(dir: &Path) { +/// Supports `s3://bucket/prefix`, `file:///path`, and bare local paths. +pub fn parse_location(raw: &str) -> Result { + if let Some(rest) = raw.strip_prefix("s3://") { + let mut parts = rest.splitn(2, '/'); + let bucket = parts.next().unwrap_or(""); + if bucket.is_empty() { + bail!("invalid s3 helm-cache path `{raw}`: missing bucket"); + } + let prefix = normalize_prefix(parts.next().unwrap_or("")); + Ok(CacheLocation::S3 { + bucket: bucket.to_owned(), + prefix, + }) + } else if let Some(rest) = raw.strip_prefix("file://") { + Ok(CacheLocation::Local(PathBuf::from(rest))) + } else { + Ok(CacheLocation::Local(PathBuf::from(raw))) + } +} + +/// Normalize an S3 key prefix so it is either empty or ends with a single `/`. +fn normalize_prefix(prefix: &str) -> String { + let trimmed = prefix.trim_start_matches('/'); + if trimmed.is_empty() { + String::new() + } else if trimmed.ends_with('/') { + trimmed.to_owned() + } else { + format!("{trimmed}/") + } +} + +/// Begin recording touched cache keys for the whole run and preload any +/// previously persisted entries into the global in-memory cache. +/// +/// For the local backend the directory is then deleted so only entries touched +/// this run are written back. Must be called once, before the parallel export +/// loop. +pub fn load_and_clear(loc: &CacheLocation) -> Result<()> { builtins::helm_disk_cache_begin(); - if !dir.exists() { - return; + match loc { + CacheLocation::Local(dir) => load_and_clear_local(dir), + CacheLocation::S3 { bucket, prefix } => load_s3(bucket, prefix), } +} - if let Err(err) = preload(dir) { - warn!("helm-cache: failed to preload {}: {err:#}", dir.display()); +/// Stop recording and persist the entries touched during this run. +/// +/// Stale entries that were not referenced this run are pruned. Must be called +/// once, after the parallel export loop completes (single-threaded), so writes +/// never race. +pub fn save(loc: &CacheLocation) -> Result<()> { + let touched = builtins::helm_disk_cache_take(); + match loc { + CacheLocation::Local(dir) => save_local(dir, &touched), + CacheLocation::S3 { bucket, prefix } => save_s3(bucket, prefix, &touched), } +} - if let Err(err) = std::fs::remove_dir_all(dir) { - warn!( - "helm-cache: failed to clear {} (stale entries may persist): {err:#}", - dir.display() - ); +// --- Local backend ------------------------------------------------------- + +fn load_and_clear_local(dir: &Path) -> Result<()> { + if !dir.exists() { + return Ok(()); } + + preload_local(dir).with_context(|| format!("preloading helm-cache from {}", dir.display()))?; + + std::fs::remove_dir_all(dir) + .with_context(|| format!("clearing helm-cache dir {}", dir.display()))?; + Ok(()) } -fn preload(dir: &Path) -> Result<()> { +fn preload_local(dir: &Path) -> Result<()> { let mut loaded = 0usize; for entry in std::fs::read_dir(dir).context("reading helm-cache directory")? { let entry = entry.context("reading helm-cache entry")?; @@ -96,38 +181,186 @@ fn preload(dir: &Path) -> Result<()> { Ok(()) } -/// Stop recording and persist the entries touched during this run to `dir`. -/// -/// Best-effort: write failures are logged and ignored so caching never breaks -/// an otherwise successful export. Must be called once, after the parallel -/// export loop completes (single-threaded), so writes never race. -pub fn save(dir: &Path) { - let touched: HashSet = builtins::helm_disk_cache_take(); +fn save_local(dir: &Path, touched: &HashSet) -> Result<()> { if touched.is_empty() { - return; + return Ok(()); } - if let Err(err) = std::fs::create_dir_all(dir) { - warn!( - "helm-cache: failed to create {}: {err:#} (not caching)", - dir.display() - ); - return; - } + std::fs::create_dir_all(dir) + .with_context(|| format!("creating helm-cache dir {}", dir.display()))?; let mut written = 0usize; - for key in &touched { + for key in touched { let Some(json) = builtins::helm_cache_get_json(key) else { // The entry was evicted or never stored; nothing to persist. continue; }; let path = dir.join(format!("{key}.json")); - match std::fs::write(&path, json) { - Ok(()) => written += 1, - Err(err) => warn!("helm-cache: failed to write {}: {err:#}", path.display()), - } + std::fs::write(&path, json) + .with_context(|| format!("writing helm-cache entry {}", path.display()))?; + written += 1; } debug!("helm-cache: wrote {written} entries to {}", dir.display()); + Ok(()) +} + +// --- S3 backend ---------------------------------------------------------- + +const S3_SUFFIX: &str = ".json"; + +/// Build a current-thread tokio runtime for the blocking S3 calls. Cache +/// load/save run single-threaded outside the rayon export pool, so a private +/// runtime here never collides with one already running. +fn s3_runtime() -> Result { + tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .context("creating tokio runtime for s3 helm-cache") +} + +async fn s3_client() -> aws_sdk_s3::Client { + let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await; + aws_sdk_s3::Client::new(&config) +} + +/// Convert an S3 object key back into the in-memory cache key (the sha stem). +fn s3_cache_key(prefix: &str, object_key: &str) -> Option { + object_key + .strip_prefix(prefix)? + .strip_suffix(S3_SUFFIX) + .map(ToOwned::to_owned) +} + +fn load_s3(bucket: &str, prefix: &str) -> Result<()> { + let rt = s3_runtime()?; + rt.block_on(async { + let client = s3_client().await; + let mut continuation: Option = None; + let mut loaded = 0usize; + loop { + let mut req = client.list_objects_v2().bucket(bucket).prefix(prefix); + if let Some(token) = &continuation { + req = req.continuation_token(token); + } + let resp = req + .send() + .await + .with_context(|| format!("listing s3://{bucket}/{prefix}"))?; + + for obj in resp.contents() { + let Some(object_key) = obj.key() else { + continue; + }; + if !object_key.ends_with(S3_SUFFIX) { + continue; + } + let Some(cache_key) = s3_cache_key(prefix, object_key) else { + continue; + }; + let out = client + .get_object() + .bucket(bucket) + .key(object_key) + .send() + .await + .with_context(|| format!("getting s3://{bucket}/{object_key}"))?; + let data = out + .body + .collect() + .await + .with_context(|| format!("reading s3://{bucket}/{object_key}"))? + .into_bytes(); + let json = String::from_utf8(data.to_vec()) + .with_context(|| format!("s3://{bucket}/{object_key} is not valid utf-8"))?; + builtins::helm_cache_put_json(cache_key, json); + loaded += 1; + } + + if resp.is_truncated().unwrap_or(false) { + continuation = resp.next_continuation_token().map(ToOwned::to_owned); + if continuation.is_none() { + break; + } + } else { + break; + } + } + debug!("helm-cache: preloaded {loaded} entries from s3://{bucket}/{prefix}"); + Ok::<(), anyhow::Error>(()) + }) +} + +fn save_s3(bucket: &str, prefix: &str, touched: &HashSet) -> Result<()> { + let rt = s3_runtime()?; + rt.block_on(async { + let client = s3_client().await; + + // Write the entries touched this run. + let mut written = 0usize; + for key in touched { + let Some(json) = builtins::helm_cache_get_json(key) else { + continue; + }; + let object_key = format!("{prefix}{key}{S3_SUFFIX}"); + client + .put_object() + .bucket(bucket) + .key(&object_key) + .body(aws_sdk_s3::primitives::ByteStream::from(json.into_bytes())) + .send() + .await + .with_context(|| format!("writing s3://{bucket}/{object_key}"))?; + written += 1; + } + + // Prune entries that were not referenced this run. + let mut continuation: Option = None; + let mut pruned = 0usize; + loop { + let mut req = client.list_objects_v2().bucket(bucket).prefix(prefix); + if let Some(token) = &continuation { + req = req.continuation_token(token); + } + let resp = req + .send() + .await + .with_context(|| format!("listing s3://{bucket}/{prefix}"))?; + + for obj in resp.contents() { + let Some(object_key) = obj.key() else { + continue; + }; + if !object_key.ends_with(S3_SUFFIX) { + continue; + } + let Some(cache_key) = s3_cache_key(prefix, object_key) else { + continue; + }; + if touched.contains(&cache_key) { + continue; + } + client + .delete_object() + .bucket(bucket) + .key(object_key) + .send() + .await + .with_context(|| format!("deleting s3://{bucket}/{object_key}"))?; + pruned += 1; + } + + if resp.is_truncated().unwrap_or(false) { + continuation = resp.next_continuation_token().map(ToOwned::to_owned); + if continuation.is_none() { + break; + } + } else { + break; + } + } + debug!("helm-cache: wrote {written} and pruned {pruned} entries on s3://{bucket}/{prefix}"); + Ok::<(), anyhow::Error>(()) + }) } #[cfg(test)] @@ -145,6 +378,61 @@ mod tests { ); } + #[test] + fn test_parse_location_local() { + assert_eq!( + parse_location("/tmp/foo").unwrap(), + CacheLocation::Local(PathBuf::from("/tmp/foo")) + ); + assert_eq!( + parse_location("file:///tmp/foo").unwrap(), + CacheLocation::Local(PathBuf::from("/tmp/foo")) + ); + } + + #[test] + fn test_parse_location_s3() { + assert_eq!( + parse_location("s3://my-bucket/some/prefix").unwrap(), + CacheLocation::S3 { + bucket: "my-bucket".to_owned(), + prefix: "some/prefix/".to_owned(), + } + ); + assert_eq!( + parse_location("s3://my-bucket").unwrap(), + CacheLocation::S3 { + bucket: "my-bucket".to_owned(), + prefix: String::new(), + } + ); + assert_eq!( + parse_location("s3://my-bucket/already/slash/").unwrap(), + CacheLocation::S3 { + bucket: "my-bucket".to_owned(), + prefix: "already/slash/".to_owned(), + } + ); + assert!(parse_location("s3:///no-bucket").is_err()); + } + + #[test] + fn test_on_error_from_str() { + assert_eq!("warn".parse::().unwrap(), OnError::Warn); + assert_eq!("fail".parse::().unwrap(), OnError::Fail); + assert!("nope".parse::().is_err()); + } + + #[test] + fn test_s3_cache_key() { + assert_eq!( + s3_cache_key("prefix/", "prefix/abc123.json").as_deref(), + Some("abc123") + ); + assert_eq!(s3_cache_key("prefix/", "other/abc123.json"), None); + assert_eq!(s3_cache_key("", "abc123.json").as_deref(), Some("abc123")); + } + #[test] fn test_save_writes_only_touched_present_entries() { let _guard = HELM_CACHE_TEST_LOCK @@ -164,7 +452,7 @@ mod tests { record_helm_disk_touch(touched_present); // Touched but never stored in the cache: must be skipped, not error. record_helm_disk_touch(touched_absent); - save(&dir); + save(&CacheLocation::Local(dir.clone())).unwrap(); let present_file = dir.join(format!("{touched_present}.json")); assert_eq!(std::fs::read_to_string(&present_file).unwrap(), "{\"k\":1}"); @@ -181,7 +469,7 @@ mod tests { let dir = tmp.path().join("helm-cache"); helm_disk_cache_begin(); - save(&dir); + save(&CacheLocation::Local(dir.clone())).unwrap(); assert!(!dir.exists()); } @@ -203,7 +491,7 @@ mod tests { std::fs::write(dir.join("README.txt"), "ignore me").unwrap(); assert_eq!(builtins::helm_cache_get_json(key), None); - load_and_clear(&dir); + load_and_clear(&CacheLocation::Local(dir.clone())).unwrap(); // Entry is now in the global in-memory cache, and the directory is gone. assert_eq!( @@ -226,7 +514,7 @@ mod tests { let dir = tmp.path().join("does-not-exist"); // Must not panic, and recording is still enabled. - load_and_clear(&dir); + load_and_clear(&CacheLocation::Local(dir.clone())).unwrap(); assert!(!dir.exists()); helm_disk_cache_take(); diff --git a/cmds/rtk/tests/export_test.rs b/cmds/rtk/tests/export_test.rs index 25144c069..d3ec0dbfc 100644 --- a/cmds/rtk/tests/export_test.rs +++ b/cmds/rtk/tests/export_test.rs @@ -410,6 +410,8 @@ fn test_export_merge_strategies() { merge_deleted_envs: vec![inline_env_path.to_string_lossy().into_owned()], show_timing: false, helm_cache: false, + helm_cache_path: None, + helm_cache_on_error: rtk::environments::helm_cache::OnError::Warn, }; let result = export(&[(*static_envs[0].path).clone()], delete_opts).unwrap();