diff --git a/.github/workflows/action.yaml b/.github/workflows/action.yaml index 947cf72d..e2dbd6ec 100644 --- a/.github/workflows/action.yaml +++ b/.github/workflows/action.yaml @@ -25,6 +25,7 @@ jobs: just add_helm_repos just setup_cluster just deploy_ame_to_cluster + just set_host_entries - name: Validate commit env: AME_TEST_GH_TOKEN: ${{ secrets.AME_TEST_GH_TOKEN }} diff --git a/Cargo.lock b/Cargo.lock index bfa4caf5..f5d0c413 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.8", + "getrandom", "once_cell", "version_check", ] @@ -26,9 +26,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", - "getrandom 0.2.8", + "getrandom", "once_cell", - "serde", "version_check", ] @@ -61,12 +60,28 @@ name = "ame_client" version = "0.1.0" dependencies = [ "futures-core", - "jsonschema", + "http", + "http-body", + "hyper", + "hyper-rustls", + "hyper-timeout", + "oauth2", + "open", + "openidconnect", "prost", "prost-build", + "reqwest", + "rustls-native-certs", + "schemars", "serde", + "serde_json", + "thiserror", + "tokio-rustls", "tonic", "tonic-build", + "tower", + "tower-http", + "url", ] [[package]] @@ -80,9 +95,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "assert_cmd" @@ -90,7 +105,7 @@ version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9834fcc22e0874394a010230586367d4a3e9f11b560f469262678547e1d2575e" dependencies = [ - "bstr 1.1.0", + "bstr 1.2.0", "doc-comment", "predicates", "predicates-core", @@ -126,37 +141,16 @@ dependencies = [ "tokio", ] -[[package]] -name = "async-stream" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22068c0c19514942eefcfd4daf8976ef1aad84e61539f95cd200c35202f80af5" -dependencies = [ - "async-stream-impl 0.2.1", - "futures-core", -] - [[package]] name = "async-stream" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" dependencies = [ - "async-stream-impl 0.3.3", + "async-stream-impl", "futures-core", ] -[[package]] -name = "async-stream-impl" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "async-stream-impl" version = "0.3.3" @@ -170,9 +164,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -195,17 +189,6 @@ dependencies = [ "wildmatch", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -289,9 +272,9 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ - "getrandom 0.2.8", + "getrandom", "instant", - "rand 0.8.5", + "rand", ] [[package]] @@ -306,21 +289,6 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bitflags" version = "1.3.2" @@ -370,9 +338,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b" +checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832" dependencies = [ "memchr", "once_cell", @@ -386,29 +354,17 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" -[[package]] -name = "bytecount" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -476,31 +432,45 @@ dependencies = [ "ame_client", "assert_cmd", "assert_fs", - "async-stream 0.3.3", + "async-stream", + "bytes", "clap", "common", - "config", "confy", "console", "controller", - "dotenvy", "envconfig", "fs_extra", "futures-util", + "http", + "http-body", + "hyper", + "hyper-rustls", "insta", "k8s-openapi", "kube", + "oauth2", + "open", + "openidconnect", "predicates", - "rand 0.8.5", + "rand", + "reqwest", "rstest", + "rustls-native-certs", "serde", + "serde_json", "serde_yaml 0.9.17", "serial_test", "similar-asserts", "temp-env", "thiserror", "tokio", + "tokio-rustls", "tonic", + "tower", + "tower-http", + "tracing", + "url", "walkdir", ] @@ -525,25 +495,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "config" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" -dependencies = [ - "async-trait", - "json5", - "lazy_static", - "nom", - "pathdiff", - "ron", - "rust-ini", - "serde", - "serde_json", - "toml", - "yaml-rust", -] - [[package]] name = "confy" version = "0.5.1" @@ -566,7 +517,7 @@ dependencies = [ "lazy_static", "libc", "unicode-width", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -584,7 +535,6 @@ dependencies = [ "k8s-openapi", "kube", "predicates", - "prometheus", "reqwest", "schemars", "serde", @@ -634,25 +584,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" -dependencies = [ - "cfg-if", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -665,9 +596,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322296e2f2e5af4270b54df9e85a02ff037e271af20ba3e7fe1575515dc840b8" +checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9" dependencies = [ "cc", "cxxbridge-flags", @@ -677,9 +608,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017a1385b05d631e7875b1f151c9f012d37b53491e2a87f65bff5c262b2111d8" +checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d" dependencies = [ "cc", "codespan-reporting", @@ -692,15 +623,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c26bbb078acf09bc1ecda02d4223f03bdd28bd4874edcb0379138efc499ce971" +checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a" [[package]] name = "cxxbridge-macro" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357f40d1f06a24b60ae1fe122542c1fb05d28d32acb2aed064e84bc2ad1e252e" +checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" dependencies = [ "proc-macro2", "quote", @@ -719,12 +650,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" +checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8" dependencies = [ - "darling_core 0.14.2", - "darling_macro 0.14.2", + "darling_core 0.14.3", + "darling_macro 0.14.3", ] [[package]] @@ -743,9 +674,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" +checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb" dependencies = [ "fnv", "ident_case", @@ -768,11 +699,11 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" +checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685" dependencies = [ - "darling_core 0.14.2", + "darling_core 0.14.3", "quote", "syn", ] @@ -880,12 +811,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" -[[package]] -name = "dotenvy" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" - [[package]] name = "dyn-clone" version = "1.0.10" @@ -906,26 +831,13 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if", ] -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "envconfig" version = "0.10.0" @@ -967,16 +879,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fancy-regex" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0678ab2d46fa5195aaf59ad034c083d351377d4af57f3e073c074d0da3e3c766" -dependencies = [ - "bit-set", - "regex", -] - [[package]] name = "fastrand" version = "1.8.0" @@ -1041,27 +943,17 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fraction" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aa5de57a62c2440ece64342ea59efb7171aa7d016faf8dfcb8795066a17146b" -dependencies = [ - "lazy_static", - "num", -] - [[package]] name = "fs_extra" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -1074,9 +966,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1084,15 +976,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -1101,15 +993,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -1118,15 +1010,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-timer" @@ -1136,9 +1028,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -1162,17 +1054,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.8" @@ -1182,7 +1063,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -1208,7 +1089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", - "bstr 1.1.0", + "bstr 1.2.0", "fnv", "log", "regex", @@ -1255,27 +1136,24 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" dependencies = [ "libc", ] [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "hex" @@ -1340,9 +1218,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.23" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -1388,7 +1266,9 @@ checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" dependencies = [ "http", "hyper", + "log", "rustls", + "rustls-native-certs", "tokio", "tokio-rustls", ] @@ -1509,20 +1389,14 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "integer-encoding" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" - [[package]] name = "io-lifetimes" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1533,23 +1407,14 @@ checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" [[package]] name = "is-terminal" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys", -] - -[[package]] -name = "iso8601" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "296af15e112ec6dc38c9fd3ae027b5337a75466e8eed757bd7d5cf742ea85eb6" -dependencies = [ - "nom", + "windows-sys 0.45.0", ] [[package]] @@ -1578,9 +1443,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -1596,17 +1461,6 @@ dependencies = [ "treediff", ] -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - [[package]] name = "jsonpath_lib" version = "0.3.0" @@ -1618,35 +1472,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "jsonschema" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ca9e2b45609132ae2214d50482c03aeee78826cd6fd53a8940915b81acedf16" -dependencies = [ - "ahash 0.8.3", - "anyhow", - "base64 0.13.1", - "bytecount", - "clap", - "fancy-regex", - "fraction", - "iso8601", - "itoa", - "lazy_static", - "memchr", - "num-cmp", - "parking_lot", - "percent-encoding", - "regex", - "reqwest", - "serde", - "serde_json", - "time", - "url", - "uuid", -] - [[package]] name = "k8s-openapi" version = "0.16.0" @@ -1737,7 +1562,7 @@ version = "0.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1af50996adb7e1251960d278859772fa30df99879dc154d792e36832209637cb" dependencies = [ - "darling 0.14.2", + "darling 0.14.3", "proc-macro2", "quote", "serde_json", @@ -1886,9 +1711,9 @@ checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" [[package]] name = "maybe-async" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6007f9dad048e0a224f27ca599d669fca8cfa0dac804725aab542b2eb032bce6" +checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" dependencies = [ "proc-macro2", "quote", @@ -1922,12 +1747,6 @@ dependencies = [ "rxml", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.6.2" @@ -1945,8 +1764,8 @@ checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "wasi", + "windows-sys 0.42.0", ] [[package]] @@ -1973,16 +1792,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -1999,20 +1808,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.3" @@ -2024,21 +1819,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-cmp" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" - -[[package]] -name = "num-complex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" -dependencies = [ - "num-traits", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -2049,29 +1829,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -2099,9 +1856,9 @@ checksum = "eeaf26a72311c087f8c5ba617c96fac67a5c04f430e716ac8d8ab2de62e23368" dependencies = [ "base64 0.13.1", "chrono", - "getrandom 0.2.8", + "getrandom", "http", - "rand 0.8.5", + "rand", "reqwest", "serde", "serde_json", @@ -2124,7 +1881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" dependencies = [ "pathdiff", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2140,7 +1897,7 @@ dependencies = [ "log", "num-bigint", "oauth2", - "rand 0.8.5", + "rand", "ring", "serde", "serde-value", @@ -2199,86 +1956,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "opentelemetry" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d6c3d7288a106c0a363e4b0e8d308058d56902adefb16f4936f417ffef086e" -dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", -] - -[[package]] -name = "opentelemetry-jaeger" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e785d273968748578931e4dc3b4f5ec86b26e09d9e0d66b55adda7fce742f7a" -dependencies = [ - "async-trait", - "futures", - "futures-executor", - "once_cell", - "opentelemetry", - "opentelemetry-semantic-conventions", - "thiserror", - "thrift", -] - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b02e0230abb0ab6636d18e2ba8fa02903ea63772281340ccac18e0af3ec9eeb" -dependencies = [ - "opentelemetry", -] - -[[package]] -name = "opentelemetry_api" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c24f96e21e7acc813c7a8394ee94978929db2bcc46cf6b5014fc612bf7760c22" -dependencies = [ - "fnv", - "futures-channel", - "futures-util", - "indexmap", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", -] - -[[package]] -name = "opentelemetry_sdk" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca41c4933371b61c2a2f214bf16931499af4ec90543604ec828f7a625c09113" -dependencies = [ - "async-trait", - "crossbeam-channel", - "dashmap", - "fnv", - "futures-channel", - "futures-executor", - "futures-util", - "once_cell", - "opentelemetry_api", - "percent-encoding", - "rand 0.8.5", - "thiserror", -] - -[[package]] -name = "ordered-float" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" -dependencies = [ - "num-traits", -] - [[package]] name = "ordered-float" version = "2.10.0" @@ -2322,15 +1999,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -2354,55 +2031,11 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" -[[package]] -name = "pest" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f" -dependencies = [ - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf026e2d0581559db66d837fe5242320f525d85c76283c61f4d51a1238d65ea" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b27bd18aa01d91c8ed2b61ea23406a676b42d82609c6e2581fba42f0c15f17f" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02b677c1859756359fc9983c2e56a0237f18624a3789528804406b7e915e5d" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", "indexmap", @@ -2518,28 +2151,13 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] -[[package]] -name = "prometheus" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" -dependencies = [ - "cfg-if", - "fnv", - "lazy_static", - "memchr", - "parking_lot", - "protobuf", - "thiserror", -] - [[package]] name = "prost" version = "0.11.6" @@ -2595,12 +2213,6 @@ dependencies = [ "prost", ] -[[package]] -name = "protobuf" -version = "2.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" - [[package]] name = "quote" version = "1.0.23" @@ -2610,19 +2222,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -2630,18 +2229,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -2651,16 +2240,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -2669,16 +2249,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -2696,7 +2267,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.8", + "getrandom", "redox_syscall", "thiserror", ] @@ -2795,17 +2366,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "ron" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" -dependencies = [ - "base64 0.13.1", - "bitflags", - "serde", -] - [[package]] name = "rstest" version = "0.16.0" @@ -2884,16 +2444,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.7" +version = "0.36.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -2908,6 +2468,18 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.2" @@ -2963,7 +2535,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3024,9 +2596,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c4437699b6d34972de58652c68b98cb5b53a4199ab126db8e20ec8ded29a721" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -3066,7 +2638,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ - "ordered-float 2.10.0", + "ordered-float", "serde", ] @@ -3106,9 +2678,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "indexmap", "itoa", @@ -3255,11 +2827,9 @@ dependencies = [ name = "service" version = "0.1.0" dependencies = [ - "async-stream 0.2.1", "async-trait", "common", "controller", - "env_logger", "envconfig", "futures-core", "futures-util", @@ -3267,14 +2837,8 @@ dependencies = [ "k8s-openapi", "kube", "log", - "oauth2", - "open", - "openidconnect", - "opentelemetry", - "opentelemetry-jaeger", "prost", "prost-build", - "rand 0.7.3", "rust-s3", "serde", "serde_json", @@ -3290,7 +2854,6 @@ dependencies = [ "tower-http", "tracing", "tracing-attributes", - "tracing-opentelemetry", "tracing-subscriber", "url", ] @@ -3415,9 +2978,9 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "temp-env" @@ -3481,35 +3044,14 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "50f297120ff9d4efe680df143d5631bba9c75fa371992b7fcb33eb3453cb0a07" dependencies = [ + "cfg-if", "once_cell", ] -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "thrift" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09678c4cdbb4eed72e18b7c2af1329c69825ed16fcbac62d083fc3e2b0590ff0" -dependencies = [ - "byteorder", - "integer-encoding", - "log", - "ordered-float 1.1.1", - "threadpool", -] - [[package]] name = "time" version = "0.3.17" @@ -3548,15 +3090,15 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.24.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ "autocfg", "bytes", @@ -3569,7 +3111,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3595,9 +3137,9 @@ dependencies = [ [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", @@ -3639,9 +3181,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "bc6a3b08b64e6dfad376fa2432c7b1f01522e37a623c3050bc95db2d3ff21583" dependencies = [ "bytes", "futures-core", @@ -3667,7 +3209,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" dependencies = [ - "async-stream 0.3.3", + "async-stream", "async-trait", "axum", "base64 0.13.1", @@ -3683,7 +3225,10 @@ dependencies = [ "pin-project", "prost", "prost-derive", + "rustls-native-certs", + "rustls-pemfile", "tokio", + "tokio-rustls", "tokio-stream", "tokio-util", "tower", @@ -3712,7 +3257,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632faf60b81a5b5f439d9635102b2b2921ee39171faf14f3e0008d99f98689f1" dependencies = [ - "async-stream 0.3.3", + "async-stream", "bytes", "prost", "tokio", @@ -3749,7 +3294,7 @@ dependencies = [ "indexmap", "pin-project", "pin-project-lite", - "rand 0.8.5", + "rand", "slab", "tokio", "tokio-util", @@ -3849,20 +3394,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-opentelemetry" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ebb87a95ea13271332df069020513ab70bdb5637ca42d6e492dc3bbbad48de" -dependencies = [ - "once_cell", - "opentelemetry", - "tracing", - "tracing-core", - "tracing-log", - "tracing-subscriber", -] - [[package]] name = "tracing-subscriber" version = "0.3.16" @@ -3902,12 +3433,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" -[[package]] -name = "ucd-trie" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" - [[package]] name = "unicode-bidi" version = "0.3.10" @@ -3931,9 +3456,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -3965,12 +3490,6 @@ dependencies = [ "serde", ] -[[package]] -name = "uuid" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" - [[package]] name = "valuable" version = "0.1.0" @@ -4019,12 +3538,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4033,9 +3546,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4043,9 +3556,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -4058,9 +3571,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if", "js-sys", @@ -4070,9 +3583,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4080,9 +3593,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -4093,9 +3606,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wasm-streams" @@ -4112,9 +3625,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -4202,6 +3715,30 @@ dependencies = [ "windows_x86_64_msvc", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.1" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 5a520054..e0349fa0 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" [dependencies] async-stream = "0.3.3" clap = { version = "4.0.27", features = ["derive"] } -config = "0.13.2" console = "0.15.2" envconfig = "0.10.0" futures-util = "0.3.25" @@ -15,11 +14,26 @@ serde_yaml = "0.9.14" ame_client = { path = "../client" } thiserror = "1.0.37" tokio = "1.22.0" -tonic = "0.8.2" +tonic = { version= "0.8.2", features = ["transport","tls", "tls-roots"] } walkdir = "2.3.2" rand = "0.8.5" -dotenvy = "0.15.6" confy = "0.5.1" +tokio-rustls = { version = "0.23.4", features = ["dangerous_configuration"] } +rustls-native-certs = "0.6.2" +hyper = "0.14.23" +tower = "0.4.13" +hyper-rustls = { version = "0.23.2", features = ["http2"] } +http-body = "0.4.5" +openidconnect = "2.5.0" +url = "2.3.1" +open = "3.2.0" +serde_json = "1.0.91" +reqwest = "0.11.14" +tower-http = { version = "0.3.5", features = ["auth"] } +http = "0.2.8" +bytes = "1.3.0" +tracing = "0.1.37" +oauth2 = "4.3.0" [dev-dependencies] assert_cmd = "2.0.6" diff --git a/cli/src/lib.rs b/cli/src/lib.rs index c84961e0..48df3b0d 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -1,8 +1,12 @@ pub mod project; +use ame_client::client_builder::AmeServiceClientCfg; use envconfig::Envconfig; + +use http::uri::InvalidUri; use serde::{Deserialize, Serialize}; use thiserror::Error; +use url::ParseError; #[derive(Error, Debug)] pub enum Error { @@ -38,6 +42,15 @@ pub enum Error { #[error("got filesystem related error: {0}")] WalkDir(#[from] walkdir::Error), + + #[error("failed to parse URL: {0}")] + ParseError(#[from] ParseError), + + #[error("Ame errored: {0}")] + ClientError(#[from] ame_client::Error), + + #[error("Invalid URI: {0}")] + UriParseError(#[from] InvalidUri), } pub type Result = std::result::Result; @@ -46,6 +59,9 @@ pub type Result = std::result::Result; pub struct CliConfiguration { #[envconfig(from = "AME_ENDPOINT")] pub endpoint: String, + pub id_token: Option, + pub access_token: Option, + pub refresh_token: Option, } impl CliConfiguration { @@ -67,6 +83,35 @@ impl CliConfiguration { pub fn save(&self) -> Result<()> { Ok(confy::store("ame", None, self)?) } + + pub fn set_auth_details( + &mut self, + id_token: String, + access_token: String, + refresh_token: String, + ) { + self.id_token = Some(id_token); + self.access_token = Some(access_token); + self.refresh_token = Some(refresh_token); + } + + pub fn init_with_endpoint(endpoint: String) -> Self { + CliConfiguration { + endpoint, + ..CliConfiguration::default() + } + } +} + +impl TryFrom for AmeServiceClientCfg { + type Error = Error; + fn try_from(cli_cfg: CliConfiguration) -> std::result::Result { + Ok(AmeServiceClientCfg { + disable_tls_cert_check: true, + endpoint: cli_cfg.endpoint.parse()?, + id_token: cli_cfg.id_token, + }) + } } #[cfg(test)] @@ -97,6 +142,9 @@ mod test { let correct_config = CliConfiguration { endpoint: "anendpoint".to_string(), + id_token: Some("an id token".to_string()), + refresh_token: Some("a refresh token".to_string()), + access_token: Some("an access token".to_string()), }; correct_config.save()?; @@ -113,6 +161,9 @@ mod test { let file_config = CliConfiguration { endpoint: "anendpoint".to_string(), + id_token: Some("an id token".to_string()), + refresh_token: Some("a refresh token".to_string()), + access_token: Some("an access token".to_string()), }; file_config.save()?; diff --git a/cli/src/main.rs b/cli/src/main.rs index aa5d9655..1a497975 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,6 +1,11 @@ -use ame_client::ame_service_client::AmeServiceClient; +use ame_client::{ + auth::browser_login, + client_builder::{build_ame_client, AmeServiceClientCfg}, + TaskIdentifier, +}; use clap::{Parser, Subcommand}; use cli::{project::Project, CliConfiguration, Result}; +use http::StatusCode; use tonic::Request; #[derive(Parser)] @@ -25,6 +30,7 @@ enum Commands { project: String, model: String, }, + Login, #[command(subcommand)] Create(CreateCommands), } @@ -37,7 +43,7 @@ enum CreateCommands { #[tokio::main] async fn main() -> Result<()> { let cli = Cli::parse(); - let config = CliConfiguration::gather()?; + let mut config = CliConfiguration::gather()?; match &cli.command { // TODO: if an error is returned here the output will be confusing to the user. @@ -45,25 +51,74 @@ async fn main() -> Result<()> { Commands::Run { name: name_arg } => { let task_template_name = name_arg.as_ref(); let project = Project::init_from_working_dir()?; - let client = AmeServiceClient::connect(config.endpoint).await?; + let mut client = build_ame_client(AmeServiceClientCfg { + disable_tls_cert_check: true, + endpoint: config.endpoint.parse().unwrap(), + id_token: config.id_token, + }) + .await?; - project.run_task(client, task_template_name).await?; + project.run_task(&mut client, task_template_name).await?; Ok(()) } Commands::Setup { endpoint } => { - CliConfiguration { - endpoint: endpoint.to_string(), + let cli_cfg = CliConfiguration::init_with_endpoint(endpoint.to_string()); + let mut client = build_ame_client(cli_cfg.clone().try_into()?).await?; + + println!("testing connection"); + + let res = client + .get_task(Request::new(TaskIdentifier { + name: "testssfsf".to_string(), + })) + .await; + + if let Err(res) = res { + // TODO: Extract HTTP code properly + if res.to_string().contains("401") { + println!("It looks like your AME instance requires authentication, please run 'ame login'") + } else if res.clone().to_http().status() != StatusCode::NOT_FOUND { + println!( + "Could not reach an AME endpoint at: {}, {:?}", + cli_cfg.endpoint, res + ); + } + cli_cfg.save()?; + println!("configuration saved!"); } - .save()?; - println!("configuration saved!"); - AmeServiceClient::connect(CliConfiguration::gather()?.endpoint).await?; + Ok(()) + } + Commands::Login => { + let provider_url = format!( + "{}/realms/ame", + config.endpoint.replace("://", "://keycloak.") + ); + + tracing::debug!( + "initiating login, with client ID: {} and issuer URL: {:?}", + "ame-cli", + provider_url + ); + + let (id_token, access_token, refresh_token) = + browser_login(provider_url, "ame-cli".to_string()).await?; + + config.set_auth_details(id_token, access_token, refresh_token); + config.save()?; + + println!("success!"); Ok(()) } Commands::Train { project, model } => { - let mut client = AmeServiceClient::connect(config.endpoint).await?; + let mut client = build_ame_client(AmeServiceClientCfg { + disable_tls_cert_check: true, + endpoint: config.endpoint.parse().unwrap(), + id_token: config.id_token, + }) + .await?; client .train_model(Request::new(ame_client::TrainRequest { @@ -74,7 +129,12 @@ async fn main() -> Result<()> { Ok(()) } Commands::Create(CreateCommands::Projectsrc { repository }) => { - let mut client = AmeServiceClient::connect(config.endpoint).await?; + let mut client = build_ame_client(AmeServiceClientCfg { + disable_tls_cert_check: true, + endpoint: config.endpoint.parse().unwrap(), + id_token: config.id_token, + }) + .await?; client .create_project_src(Request::new(ame_client::ProjectSource { diff --git a/cli/src/project.rs b/cli/src/project.rs index 75378ed0..08e9e83b 100644 --- a/cli/src/project.rs +++ b/cli/src/project.rs @@ -1,19 +1,19 @@ use crate::{Error, Result}; +use ame_client::client_builder::AmeClient; use ame_client::TaskLogRequest; use ame_client::{ - ame_service_client::AmeServiceClient, project_file_chunk::Messages, CreateTaskRequest, - FileChunk, ProjectFileChunk, ProjectFileIdentifier, TaskProjectDirectoryStructure, - TaskTemplate, + project_file_chunk::Messages, CreateTaskRequest, FileChunk, ProjectFileChunk, + ProjectFileIdentifier, TaskProjectDirectoryStructure, TaskTemplate, }; use console::Emoji; use futures_util::StreamExt; + use rand::distributions::{Alphanumeric, DistString}; use serde::{Deserialize, Serialize}; use std::fs; use std::fs::File; use std::io::Read; use std::time::Duration; -use tonic::transport::Channel; #[derive(Clone, Default, Deserialize, Serialize)] pub struct Project { @@ -79,11 +79,7 @@ impl Project { Ok(valid_task_templates[0].clone()) } - pub async fn run_task( - &self, - mut client: AmeServiceClient, - template_name: &str, - ) -> Result<()> { + pub async fn run_task(&self, client: &mut AmeClient, template_name: &str) -> Result<()> { let project_file: Project = serde_yaml::from_str(&fs::read_to_string("ame.yaml")?)?; let task_template = project_file.get_task_template(template_name)?; @@ -103,7 +99,7 @@ impl Project { ))) .await?; - let _chunk_size = 1024; + let _chunk_size = 500; for entry in walkdir::WalkDir::new(".").into_iter().flatten() { if entry.metadata()?.is_dir() { diff --git a/cli/tests/cli.rs b/cli/tests/cli.rs index 784e9c3a..293a1456 100644 --- a/cli/tests/cli.rs +++ b/cli/tests/cli.rs @@ -1,7 +1,8 @@ use assert_cmd::prelude::*; use assert_fs::prelude::*; -use common::{find_service_endpoint, setup_cluster}; +use common::{find_ame_endpoint, setup_cluster}; use fs_extra::dir::CopyOptions; +use insta::assert_snapshot; use rstest::*; use serial_test::serial; use std::{ @@ -10,13 +11,13 @@ use std::{ }; static AME_FILE_NAME: &str = "ame.yaml"; -static TARGET_NAMESPACE: &str = "ame-system"; -static AME_SERVICE_NAME: &str = "ame-server-service"; +static INGRESS_NAMESPACE: &str = "ingress-nginx"; +static INGRESS_SERVICE: &str = "ingress-nginx-controller"; async fn test_setup() -> Result<(), Box> { std::env::set_var( "AME_ENDPOINT", - find_service_endpoint(TARGET_NAMESPACE, AME_SERVICE_NAME).await?, + find_ame_endpoint(INGRESS_NAMESPACE, INGRESS_SERVICE).await?, ); Ok(()) @@ -133,6 +134,11 @@ async fn ame_run_task( settings.add_filter("warnings\\.warn.*\\n", ""); settings.add_filter(" \"redacted timestamp", "\"redacted timestamp"); settings.add_filter(" Score:", "Score:"); + settings.add_filter("added seed packages.*", "redacted"); + settings.add_filter("Registered model '.*' already exists.*", "redacted"); + settings.add_filter("Created version '.'.*\\n", ""); + settings.add_filter(", version .", ", version %"); + settings.add_filter("Successfully registered model .*", "redacted"); let _guard = settings.bind_to_scope(); insta::assert_snapshot!(&String::from_utf8(res.get_output().stdout.clone())?); @@ -147,7 +153,7 @@ async fn ame_setup_cli() -> Result<(), Box> { let temp_path = temp.to_str().unwrap(); - let service_endpoint = find_service_endpoint(TARGET_NAMESPACE, AME_SERVICE_NAME) + let service_endpoint = find_ame_endpoint(INGRESS_NAMESPACE, INGRESS_SERVICE) .await .unwrap(); @@ -179,13 +185,14 @@ async fn fail_bad_server_endpoint() -> Result<(), Box> { temp_env::with_vars( vec![("AME_ENDPOINT", None), ("XDG_CONFIG_HOME", Some(temp_path))], || { - Command::cargo_bin("cli") + let output = Command::cargo_bin("cli") .unwrap() .current_dir(temp_path) .arg("setup") .arg(service_endpoint.clone()) - .assert() - .failure(); + .assert(); + + assert_snapshot!(&String::from_utf8(output.get_output().stdout.clone()).unwrap()); }, ); diff --git a/cli/tests/snapshots/cli__ame_run_task-2.snap b/cli/tests/snapshots/cli__ame_run_task-2.snap index feea7836..b19ea1f0 100644 --- a/cli/tests/snapshots/cli__ame_run_task-2.snap +++ b/cli/tests/snapshots/cli__ame_run_task-2.snap @@ -15,10 +15,12 @@ Installed Python-3.8.10 to /home/ame/.pyenv/versions/3.8.10 created virtual environment "redacted" creator "redacted" seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/ame/.local/share/virtualenv) - added seed packages: pip==22.3.1, setuptools==65.6.3, wheel==0.38.4 + redacted activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator "redacted timestamp" INFO mlflow.utils.virtualenv: Installing dependencies "redacted timestamp" INFO mlflow.projects.utils: === Created directory /"redacted temporary directory""redacted timestamp" INFO mlflow.projects.backend.local: === Running command 'source /home/ame/.mlflow/envs/"redacted MLflow env ID"activate && python train.py' in "redacted run ID" + redacted +"redacted timestamp" INFO mlflow.tracking._model_registry.client: Waiting up to 300 seconds for model version to finish creation. Model name: test_model, version % Score: 0.6666666666666666 Model saved in "redacted run ID" "redacted timestamp" INFO mlflow.projects: === Run ("redacted run ID") succeeded === diff --git a/cli/tests/snapshots/cli__ame_run_task.snap b/cli/tests/snapshots/cli__ame_run_task.snap index 0c319fc4..54a6acf6 100644 --- a/cli/tests/snapshots/cli__ame_run_task.snap +++ b/cli/tests/snapshots/cli__ame_run_task.snap @@ -3,4 +3,5 @@ source: cli/tests/cli.rs expression: "&String::from_utf8(res.get_output().stdout.clone())?" --- uploaded project! +myoutput diff --git a/cli/tests/snapshots/cli__fail_bad_server_endpoint.snap b/cli/tests/snapshots/cli__fail_bad_server_endpoint.snap new file mode 100644 index 00000000..901c753e --- /dev/null +++ b/cli/tests/snapshots/cli__fail_bad_server_endpoint.snap @@ -0,0 +1,8 @@ +--- +source: cli/tests/cli.rs +expression: "&String::from_utf8(output.get_output().stdout.clone()).unwrap()" +--- +testing connection +Could not reach an AME endpoint at: wrong_endpoint, Status { code: Unknown, message: "buffer's worker closed unexpectedly", source: Some(Closed) } +configuration saved! + diff --git a/client/Cargo.toml b/client/Cargo.toml index 21a9e11f..cdb396c1 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -8,7 +8,23 @@ futures-core = "0.3.25" tonic = "0.8.3" prost = "0.11" serde = "1.0" -jsonschema = "0.16.1" +thiserror = "1.0.38" +tokio-rustls = "0.23.4" +rustls-native-certs = "0.6.2" +hyper = { version = "0.14.23", features = ["client"] } +openidconnect = "2.5.0" +serde_json = "1.0.91" +tower = "0.4.13" +hyper-rustls = { version = "0.23.2", features = ["http2"] } +http = "0.2.8" +http-body = "0.4.5" +tower-http = { version = "0.3.5", features = ["auth"] } +oauth2 = "4.3.0" +open = "3.2.0" +url = "2.3.1" +reqwest = "0.11.14" +schemars = "0.8.11" +hyper-timeout = "0.4.1" [build-dependencies] tonic-build = "0.8.4" diff --git a/client/build.rs b/client/build.rs index c12138b6..514e2709 100644 --- a/client/build.rs +++ b/client/build.rs @@ -2,7 +2,10 @@ fn main() { // TODO: evaluate state of optionals in protobuf. tonic_build::configure() .build_server(false) - .type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]") + .type_attribute( + ".", + "#[derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema)]", + ) .protoc_arg("--experimental_allow_proto3_optional") .compile(&["../proto/ame.proto"], &["../proto"]) .unwrap_or_else(|e| panic!("Failed to compile protos {e:?}")); diff --git a/client/src/auth.rs b/client/src/auth.rs new file mode 100644 index 00000000..844985cf --- /dev/null +++ b/client/src/auth.rs @@ -0,0 +1,158 @@ +use std::{ + io::BufReader, + net::{TcpListener, TcpStream}, +}; + +use crate::{Error, Result}; + +use openidconnect::{ + core::{CoreClient, CoreProviderMetadata, CoreResponseType}, + AuthorizationCode, ClientId, CsrfToken, IssuerUrl, Nonce, OAuth2TokenResponse, RedirectUrl, + TokenResponse, +}; +use std::io::prelude::*; + +mod async_client { + use oauth2::{HttpRequest, HttpResponse}; + use openidconnect::reqwest::Error; + + pub use reqwest; + + /// + /// Asynchronous HTTP client. + /// + pub async fn async_http_client( + request: HttpRequest, + ) -> Result> { + let client = { + let builder = reqwest::Client::builder(); + + // Following redirects opens the client up to SSRF vulnerabilities. + // but this is not possible to prevent on wasm targets + #[cfg(not(target_arch = "wasm32"))] + let builder = builder + .danger_accept_invalid_certs(true) + .redirect(reqwest::redirect::Policy::none()); + + builder.build().map_err(Error::Reqwest)? + }; + + let mut request_builder = client + .request(request.method, request.url.as_str()) + .body(request.body); + for (name, value) in &request.headers { + request_builder = request_builder.header(name.as_str(), value.as_bytes()); + } + let request = request_builder.build().map_err(Error::Reqwest)?; + + let response = client.execute(request).await.map_err(Error::Reqwest)?; + + let status_code = response.status(); + let headers = response.headers().to_owned(); + let chunks = response.bytes().await.map_err(Error::Reqwest)?; + Ok(HttpResponse { + status_code, + headers, + body: chunks.to_vec(), + }) + } +} +pub async fn browser_login( + provider_url: String, + client_id: String, +) -> Result<(String, String, String)> { + let issuer_url = IssuerUrl::new(provider_url)?; + let provider_metadata = + CoreProviderMetadata::discover_async(issuer_url.clone(), async_client::async_http_client) + .await + .map_err(|_| { + Error::AuthError("failed to discover OpenIDconnect provider metadata".to_string()) + })?; + + let server = TcpListener::bind(("127.0.0.1", 0))?; + + let client = + CoreClient::from_provider_metadata(provider_metadata, ClientId::new(client_id), None) + .set_redirect_uri(RedirectUrl::new(format!( + "http://localhost:{}", + server.local_addr()?.port() + ))?); + + let (authorize_url, csrf_state, _nonce) = client + .authorize_url( + openidconnect::AuthenticationFlow::::AuthorizationCode, + CsrfToken::new_random, + Nonce::new_random, + ) + .add_scope(openidconnect::Scope::new("offline_access".to_string())) + .url(); + + open::that(authorize_url.to_string())?; + println!("Open this URL to login: \n{authorize_url}\n"); + + let (mut stream, _) = server.accept()?; + + let (code, state) = extract_code_from_redirect(&stream).await; + + if csrf_state.secret() != state.secret() { + return Err(Error::AuthError( + "Received incorrect CSRF state".to_string(), + )); + } + + let message = "You are logged in!"; + let response = format!( + "HTTP/1.1 200 OK\r\ncontent-length: {}\r\n\r\n{}", + message.len(), + message + ); + + stream.write_all(response.as_bytes())?; + + let token_response = client + .exchange_code(code) + .request_async(async_client::async_http_client) + .await + .map_err(|_| Error::AuthError("failed to exchange code for token".to_string()))?; + + //TODO: validate claims with nonce. + + Ok(( + token_response.id_token().unwrap().to_string(), + token_response.access_token().secret().to_string(), + token_response.refresh_token().unwrap().secret().to_string(), + )) +} + +async fn extract_code_from_redirect(stream: &TcpStream) -> (AuthorizationCode, CsrfToken) { + let mut reader = BufReader::new(stream); + let mut request_line = String::new(); + reader.read_line(&mut request_line).unwrap(); + + let redirect_url = request_line.split_whitespace().nth(1).unwrap(); + let url = url::Url::parse(&("http://localhost".to_string() + redirect_url)).unwrap(); + + let code_pair = url + .query_pairs() + .find(|pair| { + let (key, _) = pair; + key == "code" + }) + .unwrap(); + + let (_, value) = code_pair; + let code = AuthorizationCode::new(value.into_owned()); + + let state_pair = url + .query_pairs() + .find(|pair| { + let (key, _) = pair; + key == "state" + }) + .unwrap(); + + let (_, value) = state_pair; + let state = CsrfToken::new(value.into_owned()); + + (code, state) +} diff --git a/client/src/client_builder.rs b/client/src/client_builder.rs new file mode 100644 index 00000000..2a14800d --- /dev/null +++ b/client/src/client_builder.rs @@ -0,0 +1,105 @@ +use crate::Result; + +use hyper::{client::HttpConnector, Uri}; + +use tokio_rustls::rustls::{client::ServerCertVerifier, ClientConfig}; + +use tower::util::BoxService; +use tower_http::auth::AddAuthorizationLayer; + +use crate::ame_service_client::AmeServiceClient; + +struct Verifier; + +impl ServerCertVerifier for Verifier { + fn verify_server_cert( + &self, + _end_entity: &tokio_rustls::rustls::Certificate, + _intermediates: &[tokio_rustls::rustls::Certificate], + _server_name: &tokio_rustls::rustls::ServerName, + _scts: &mut dyn Iterator, + _ocsp_response: &[u8], + _now: std::time::SystemTime, + ) -> std::result::Result< + tokio_rustls::rustls::client::ServerCertVerified, + tokio_rustls::rustls::Error, + > { + Ok(tokio_rustls::rustls::client::ServerCertVerified::assertion()) + } +} + +pub struct AmeServiceClientCfg { + pub disable_tls_cert_check: bool, + pub endpoint: Uri, + pub id_token: Option, +} + +pub type AmeClient = AmeServiceClient< + tower::buffer::Buffer< + BoxService< + http::Request, + http::Response, + hyper::Error, + >, + http::Request, + >, +>; + +pub async fn build_ame_client(cfg: AmeServiceClientCfg) -> Result { + let mut roots = tokio_rustls::rustls::RootCertStore::empty(); + for cert in rustls_native_certs::load_native_certs().expect("missing cerst") { + roots + .add(&tokio_rustls::rustls::Certificate(cert.0)) + .unwrap() + } + + let mut tls = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(roots) + .with_no_client_auth(); + + tls.dangerous() + .set_certificate_verifier(std::sync::Arc::new(Verifier {})); + + let mut http = HttpConnector::new(); + http.enforce_http(false); + + let id_token = if let Some(id_token) = cfg.id_token { + id_token + } else { + "".to_string() + }; + + let connector = tower::ServiceBuilder::new() + .layer_fn(move |s| { + let tls = tls.clone(); + + hyper_rustls::HttpsConnectorBuilder::new() + .with_tls_config(tls) + .https_or_http() + .enable_http2() + .wrap_connector(s) + }) + .service(http.clone()); + + let res = hyper::Client::builder().http2_only(true).build(connector); + let svc = tower::ServiceBuilder::new() + .layer(tower::buffer::BufferLayer::new(1024)) + .layer(BoxService::layer()) + .layer(AddAuthorizationLayer::bearer(&id_token)) + .map_request(move |mut req: http::Request| { + let uri = Uri::builder() + .scheme(cfg.endpoint.scheme().unwrap().clone()) + .authority(cfg.endpoint.authority().unwrap().clone()) + .path_and_query(req.uri().path_and_query().unwrap().clone()) + .build() + .unwrap(); + + *req.uri_mut() = uri; + + req + }) + .service(res); + + Ok(AmeServiceClient::new(svc)) +} diff --git a/client/src/lib.rs b/client/src/lib.rs index 33d9cf9a..14f8a0a8 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1,10 +1,40 @@ mod grpc_client { tonic::include_proto!("ame.v1"); } +use url::ParseError; + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Ame errored: {0}")] + FileError(#[from] std::io::Error), + + #[error("Serde errored: {0}")] + SerdeError(#[from] serde_json::Error), + + #[error("Openid errored: {0}")] + OpenIdError(String), + + #[error("Failed to parse metadata: {0}")] + MedatadataError(#[from] InvalidMetadataValue), + + #[error("failed to parse URL: {0}")] + ParseError(#[from] ParseError), + + #[error("Authentication failed: {0}")] + AuthError(String), +} + +pub type Result = std::result::Result; pub use grpc_client::*; pub use grpc_client::{LogEntry, TaskIdentifier, TaskLogRequest}; +use tonic::metadata::errors::InvalidMetadataValue; + +pub mod auth; +pub mod client_builder; impl From<&str> for TaskIdentifier { fn from(name: &str) -> Self { diff --git a/common/src/lib.rs b/common/src/lib.rs index 7086ae45..93bfae9b 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -8,6 +8,33 @@ use kube::{ Api, Client, }; +pub async fn find_ame_endpoint( + namespace: &str, + service_name: &str, +) -> Result> { + let client = Client::try_default().await?; + let services = Api::::namespaced(client.clone(), namespace); + let service = services.get(service_name).await?; + + let Service { spec: Some(ServiceSpec{ + ports: Some(ports), + .. + }), + ..} = service else { + return Err(format!("failed to extract service ips and ports: {service:#?}"))?; + }; + + let port = ports + .iter() + .find(|p| p.name.clone().unwrap_or("".to_string()) == "https"); + + if let Some(port) = port { + Ok(format!("https://ame.local:{}", port.port)) + } else { + Err("failed to find a port".to_string())? + } +} + pub async fn find_service_endpoint( namespace: &str, service_name: &str, diff --git a/controller/Cargo.toml b/controller/Cargo.toml index 9c0db872..15fdcfde 100644 --- a/controller/Cargo.toml +++ b/controller/Cargo.toml @@ -36,7 +36,6 @@ git2 = "0.15.0" humantime = "2.1.0" k8s-openapi = { version = "0.16.0", features = ["v1_23", "schemars" ] } kube = { version = "0.76.0", features = ["runtime", "client", "derive"] } -prometheus = "0.13.3" reqwest = { version = "0.11.14", features = ["json"] } schemars = "0.8.11" serde = {version = "1.0.147", features = ["derive"]} diff --git a/controller/src/manager.rs b/controller/src/manager.rs index d01341af..bba452e7 100644 --- a/controller/src/manager.rs +++ b/controller/src/manager.rs @@ -342,7 +342,17 @@ impl Task { .. }) = self.spec.source { - format!("git clone {repo} .") + format!( + " + git clone {repo} repo + + cp -r repo/* . + + rm -rf repo + + ls + " + ) } else { format!("s3cmd --no-ssl --region eu-central-1 --host=$MINIO_URL --host-bucket=$MINIO_URL get --recursive s3://{} ./", self.task_files_path()) }; diff --git a/controller/src/project.rs b/controller/src/project.rs index f90815f7..09605e56 100644 --- a/controller/src/project.rs +++ b/controller/src/project.rs @@ -6,6 +6,7 @@ use std::{ use crate::{manager, Error, Result, TaskSpec}; +use ame_client::LogEntry; use futures::{future::BoxFuture, FutureExt, StreamExt}; use k8s_openapi::{ api::{ @@ -56,6 +57,9 @@ pub struct ProjectSpec { #[serde(skip_serializing_if = "Option::is_none")] pub templates: Option>, + + #[serde(skip_serializing_if = "Option::is_none")] + pub log_entry: Option, } #[derive(Deserialize, Serialize, Clone, Debug, JsonSchema, PartialEq, Eq, Default)] @@ -236,6 +240,11 @@ impl Model { .clone() .unwrap_or(BTreeMap::::new()); + ingress_annotations.insert( + "nginx.ingress.kubernetes.io/ssl-redirect".to_string(), + "false".to_string(), + ); + if let Some(mut annotations) = model_deployment.ingress_annotations { ingress_annotations.append(&mut annotations); } @@ -282,7 +291,7 @@ impl Model { ..IngressBackend::default() }, path_type: "ImplementationSpecific".to_string(), - path: None, + path: Some("/invocations".to_string()), }], }), }]), diff --git a/controller/src/snapshots/controller__manager__test__task_can_have_git_src.snap b/controller/src/snapshots/controller__manager__test__task_can_have_git_src.snap index a09a73b0..059dcc5f 100644 --- a/controller/src/snapshots/controller__manager__test__task_can_have_git_src.snap +++ b/controller/src/snapshots/controller__manager__test__task_can_have_git_src.snap @@ -60,7 +60,7 @@ spec: volumeMounts: - mountPath: /project name: training-volume - source: "\n git clone gitrepo .\n\n echo \"0\" >> exit.status\n " + source: "\n \n git clone gitrepo repo\n\n cp -r repo/* .\n\n rm -rf repo\n\n ls\n \n\n echo \"0\" >> exit.status\n " podSpecPatch: ~ - - name: main inline: diff --git a/controller/src/snapshots/controller__project__test__produces_valid_ingress.snap b/controller/src/snapshots/controller__project__test__produces_valid_ingress.snap index 73bf09f8..a6c24956 100644 --- a/controller/src/snapshots/controller__project__test__produces_valid_ingress.snap +++ b/controller/src/snapshots/controller__project__test__produces_valid_ingress.snap @@ -1,11 +1,12 @@ --- source: controller/src/project.rs -expression: "&project.spec.models.unwrap().clone()[0].generate_model_ingress(&ctrl_cfg)?" +expression: "&project.spec.models.unwrap()[0].generate_model_ingress(&ctrl_cfg)?" --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - annotations: {} + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "false" labels: ame-model: test name: test @@ -20,6 +21,7 @@ spec: name: test port: number: 5000 + path: /invocations pathType: ImplementationSpecific tls: - hosts: diff --git a/infra/.terraform.lock.hcl b/infra/.terraform.lock.hcl new file mode 100644 index 00000000..5b051e97 --- /dev/null +++ b/infra/.terraform.lock.hcl @@ -0,0 +1,21 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "3.0.0" + constraints = "3.0.0" + hashes = [ + "h1:yZB4RESHY23SOtMyFTXaz7cBaTKK5UnDn/rhIbNgWYg=", + "zh:23a039a606cc194594f7c15cd8deef15c5183e11a40e96adee2f7317dbfa18aa", + "zh:414890618efc6caccf60b81fcce18a7e69a6d81599678d24f538d53726f49c57", + "zh:7c9a5d3c416766c6f624e186ee2f5b216dd5a9ffef40bfea42ceccf2b217e0d3", + "zh:82bbeaa6e10d0834d05c2ea55182ce6e147299b1257b445327ff6ff9dfdff3e7", + "zh:96d5f7737a3d10cc25815f1a220ef8ffe3641ee3229c7738804dc8cff71663fa", + "zh:ac359915e11a4fa234476cca5e701631ba563d8192dd3f1d31b51674411a0394", + "zh:bdf07291bb4f41ba304f12b298a066ac70925b3749c01aa90276727cfb0b2662", + "zh:cf7b4f9c313155b7d5c98e0cbbcfec40c789fccf431875b4db630e9e58f3ae6c", + "zh:d1fd0d3a1017427ab6f4fadb3310b4b488ab020a541778653c03c51e5e1df809", + "zh:db946fc8cfc15abe18314dc3dbcbb630243dc34c29f81a728e1397d797dca6a0", + "zh:e07f73c2745b56043d8b779f2987eb1a5f812645db6ac8fa7878ad23f6a79459", + ] +} diff --git a/infra/main.tf b/infra/main.tf new file mode 100644 index 00000000..29d905a3 --- /dev/null +++ b/infra/main.tf @@ -0,0 +1,53 @@ +# Azure Provider source and version being used +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "=3.0.0" + } + } +} + +# Configure the Microsoft Azure Provider +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_kubernetes_cluster" "example" { + name = "example-ask" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + dns_prefix = "exampleaks" + kubernetes_version = "1.25" + + default_node_pool { + name = "default" + node_count = 1 + vm_size = "Standard_D2_v2" + + } + + identity { + type = "SystemAssigned" + } + + tags = { + Environment = "Production" + } +} + +output "client_certificate" { + value = azurerm_kubernetes_cluster.example.kube_config.0.client_certificate + sensitive = true +} + +output "kube_config" { + value = azurerm_kubernetes_cluster.example.kube_config_raw + + sensitive = true +} diff --git a/justfile b/justfile index 29286867..9819c745 100644 --- a/justfile +++ b/justfile @@ -11,6 +11,8 @@ LOCAL_EXECUTOR_IMAGE_TAG := "main:" + AME_REGISTRY_PORT + "/" + EXECUTOR_IMAGE + CONTROLLER_IMAGE_TAG := AME_REGISTRY + "/" + CONTROLLER_IMAGE + IMG_TAG TARGET_NAMESPACE := "ame-system" TASK_SERVICE_ACCOUNT := "ame-task" +AME_HOST := "ame.local" +KEYCLOAK_HOST := "keycloak.ame.local" # See https://github.com/rust-lang/rustfix/issues/200#issuecomment-923111872 export __CARGO_FIX_YOLO := "1" @@ -29,6 +31,7 @@ tools: cargo install --locked cargo-insta cargo install --locked cargo-audit cargo install --locked cargo-outdated + cargo install --locked cargo-udeps fix: fmt cargo fix --workspace --allow-dirty --tests --allow-staged @@ -46,6 +49,7 @@ check: cargo +nightly fmt --check cargo +nightly clippy --workspace --tests --all -- -D warnings cargo outdated + cargo +nightly udeps --all-targets --workspace --show-unused-transitive test *ARGS: cargo test --workspace {{ARGS}} @@ -89,10 +93,13 @@ run_cli *ARGS: setup_cli: cargo run -p cli setup http://$(kubectl get svc -n {{TARGET_NAMESPACE}} ame-server-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}'):3342 +setup_cli_ingress: + cargo run -p cli setup https://$(kubectl get ingress -n {{TARGET_NAMESPACE}} ame-server -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + # Local cluster utilities -setup_cluster: k3s create_namespace install_cert_manager install_argo_workflows deploy_keycloak deploy_minio +setup_cluster: k3s create_namespace create_service_accounts install_cert_manager install_argo_workflows deploy_keycloak deploy_minio deploy_nginx k3s: k3d cluster create main \ @@ -105,7 +112,9 @@ k3s: create_namespace: kubectl create ns {{TARGET_NAMESPACE}} - kubectl create sa {{TASK_SERVICE_ACCOUNT}} + +create_service_accounts: + kubectl create sa {{TASK_SERVICE_ACCOUNT}} -n {{TARGET_NAMESPACE}} # TODO: move this to vault setup delete_cluster: k3d cluster delete main @@ -115,6 +124,26 @@ install_crd: kubectl apply -f manifests/project_src_crd.yaml kubectl apply -f manifests/project_crd.yaml +set_host_entries: + #!/bin/sh + LB_IP=$(kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + + echo "In order to test AME with SSL a host entry must be set in your local host file, this requires root permissions" + + just ensure_host_entry $LB_IP {{AME_HOST}} + just ensure_host_entry $LB_IP {{KEYCLOAK_HOST}} + +ensure_host_entry IP HOST: + #!/bin/sh + echo "ensure host entry: {{IP}} {{HOST}}" + if grep -q {{HOST}} "/etc/hosts"; then + echo "Found existing ame host entry, will replace the IP to make sure it is up to date." + sudo sed -i "s/.* {{HOST}}.*/{{IP}} {{HOST}}/" /etc/hosts + else + echo "Adding new entry to entry/hosts" + echo "{{IP}} {{HOST}}" | sudo tee -a /etc/hosts + fi + install_argo_workflows: kubectl apply -n {{TARGET_NAMESPACE}} -f https://raw.githubusercontent.com/argoproj/argo-workflows/master/manifests/quick-start-postgres.yaml @@ -137,6 +166,25 @@ deploy_server: kubectl delete pod -n ame-system -l app=ame-server kubectl wait pods -n {{TARGET_NAMESPACE}} -l app=ame-server --for condition=Ready --timeout=90s +deploy_server_to_ask: + #!/bin/sh + cd ./manifests/server/aks/ + kustomize edit set namespace {{TARGET_NAMESPACE}} + kustomize build . | kubectl apply -f - + sleep 1 + kubectl delete pod -n ame-system -l app=ame-server + kubectl wait pods -n {{TARGET_NAMESPACE}} -l app=ame-server --for condition=Ready --timeout=90s + +deploy_controller_to_ask: + #!/bin/sh + cd ./manifests/controller/aks/ + kustomize edit set namespace {{TARGET_NAMESPACE}} + kustomize build . | kubectl apply -f - + sleep 1 + kubectl delete pod -n ame-system -l app=ame-server + kubectl wait pods -n {{TARGET_NAMESPACE}} -l app=ame-server --for condition=Ready --timeout=90s + + deploy_controller: #!/bin/sh CONTROLLER_IMAGE_TAG="main:{{AME_REGISTRY_PORT}}/{{CONTROLLER_IMAGE}}:latest" @@ -180,7 +228,6 @@ push_executor_image: push_controller_image: docker push {{CONTROLLER_IMAGE_TAG}} - remove_server: kustomize build manifests/server/local | kubectl delete --ignore-not-found=true -f - @@ -193,9 +240,6 @@ install_commit_template: start_opentelemtry_collector: docker run -d -p6831:6831/udp -p6832:6832/udp -p16686:16686 jaegertracing/all-in-one:latest -start_keycloak: - docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:20.0.1 start-dev - run_client: cargo run --bin ame-client @@ -221,49 +265,70 @@ add_helm_repos: helm repo update deploy_keycloak: - helm install keycloak bitnami/keycloak --set auth.adminPassword=admin + helm install keycloak bitnami/keycloak --set auth.adminPassword=admin -f ./manifests/keycloak/values_local.yaml + +deploy_keycloak_ask: + helm install keycloak bitnami/keycloak --set auth.adminPassword=admin -f ./manifests/keycloak/values.yaml deploy_oauth2_proxy: helm install oauth2-proxy oauth2-proxy/oauth2-proxy \ - --version 3.3.2 -f ./manifests/oauth2-proxy/oauth2proxy-values.yaml --wait + -f ./manifests/oauth2-proxy/oauth2proxy-values.yaml --wait + +deploy_oauth2_proxy_local: + helm install oauth2-proxy oauth2-proxy/oauth2-proxy \ + -f ./manifests/oauth2-proxy/oauth2proxy-values-local.yaml --wait deploy_mlflow: helm install mlflow ncsa/mlflow deploy_nginx: - helm install ingress-nginx ingress-nginx/ingress-nginx \ - --wait --version 3.34.0 --set-string controller.config.ssl-redirect=false + helm upgrade --install ingress-nginx ingress-nginx \ + --repo https://kubernetes.github.io/ingress-nginx \ + --namespace ingress-nginx --create-namespace + +setup_ask: + # ask ingress nginx install: https://kubernetes.github.io/ingress-nginx/deploy/#azure + kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.5.1/deploy/static/provider/cloud/deploy.yaml + + # Standard cert manager install: https://cert-manager.io/docs/installation/ + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml + kubectl apply -f ./manifests/cert-manager/issuers.yaml deploy_vault: helm install vault hashicorp/vault \ - --set "server.dev.enabled=true" -n vault + --set "server.dev.enabled=true" -n vault --create-namespace + just configure_vault_k8s_auth + just set_vault_secret -configure_vault: +configure_vault_k8s_auth: #!/bin/sh kubectl exec -n vault -it vault-0 -- vault auth enable kubernetes kubectl exec -n vault -it vault-0 -- bin/sh -c 'vault write auth/kubernetes/config \ kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443"' - + kubectl exec -n vault -it vault-0 -- vault policy write {{TASK_SERVICE_ACCOUNT}} - < Result<()> { tracing::info!("Serving at: {}", addr); Server::builder() - .layer(TraceLayer::new_for_grpc()) .accept_http1(true) .add_service(tonic_web::enable(AmeServiceServer::new(svc))) .add_service(health_service) diff --git a/shell.nix b/shell.nix index c027da47..cec0aec1 100644 --- a/shell.nix +++ b/shell.nix @@ -20,6 +20,7 @@ pkgs.mkShell { argo python310Packages.mlflow kubernetes-helm + grpcurl ]; # Certain Rust tools won't work without this