diff --git a/Cargo.lock b/Cargo.lock index 3d3a223bf..40adb12c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.8.11" @@ -24,7 +35,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom 0.2.12", + "getrandom 0.2.14", "once_cell", "version_check", "zerocopy", @@ -32,18 +43,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -110,15 +121,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "arc-swap" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arrayvec" @@ -207,7 +218,7 @@ version = "0.2.3" source = "git+https://github.com/shuttle-hq/posthog-rs?branch=main#4a8299fde3080bff550620c0853be9b83fee8f44" dependencies = [ "posthog-core", - "reqwest 0.11.24", + "reqwest 0.11.27", "serde", "serde_json", "thiserror", @@ -233,7 +244,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -258,13 +269,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -276,21 +287,11 @@ dependencies = [ "num-traits", ] -[[package]] -name = "atomic-write-file" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8204db279bf648d64fe845bd8840f78b39c8132ed4d6a4194c3b10d4b4cfb0b" -dependencies = [ - "nix 0.28.0", - "rand 0.8.5", -] - [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "aws-config" @@ -310,7 +311,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand 2.0.1", + "fastrand 2.0.2", "hex", "http 0.2.12", "hyper 0.14.28", @@ -330,7 +331,7 @@ checksum = "70a66ac8ef5fa9cf01c2d999f39d16812e90ec1467bd382cbbb74ba23ea86201" dependencies = [ "aws-smithy-async", "aws-smithy-types", - "fastrand 2.0.1", + "fastrand 2.0.2", "tokio", "tracing", "zeroize", @@ -369,7 +370,7 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", - "fastrand 2.0.1", + "fastrand 2.0.2", "http 0.2.12", "percent-encoding", "tracing", @@ -491,7 +492,7 @@ dependencies = [ "aws-smithy-http-tower", "aws-smithy-types", "bytes", - "fastrand 2.0.1", + "fastrand 2.0.2", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", @@ -573,7 +574,7 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "bytes", - "fastrand 2.0.1", + "fastrand 2.0.2", "http 0.2.12", "http-body 0.4.6", "once_cell", @@ -733,9 +734,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -780,15 +781,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "basic-toml" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5" -dependencies = [ - "serde", -] - [[package]] name = "bit-set" version = "0.5.3" @@ -812,9 +804,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -877,20 +869,20 @@ checksum = "b58071e8fd9ec1e930efd28e3a90c1251015872a2ce49f81f36421b86466932e" dependencies = [ "serde", "serde_repr", - "serde_with 3.6.1", + "serde_with 3.7.0", ] [[package]] name = "bson" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce21468c1c9c154a85696bb25c20582511438edb6ad67f846ba1378ffdd80222" +checksum = "4d43b38e074cc0de2957f10947e376a1d88b9c4dbab340b590800cc1b2e066b2" dependencies = [ "ahash", "base64 0.13.1", "bitvec", "hex", - "indexmap 2.2.5", + "indexmap 2.2.6", "js-sys", "once_cell", "rand 0.8.5", @@ -914,9 +906,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.3" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -926,9 +918,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bytes-utils" @@ -940,6 +932,27 @@ dependencies = [ "either", ] +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "camino" version = "1.1.6" @@ -951,9 +964,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -988,7 +1001,7 @@ dependencies = [ "percent-encoding", "portpicker", "regex", - "reqwest 0.11.24", + "reqwest 0.11.27", "rexpect", "rmp-serde", "semver 1.0.22", @@ -998,7 +1011,7 @@ dependencies = [ "shuttle-common-tests", "shuttle-proto", "shuttle-service", - "strum 0.26.1", + "strum 0.26.2", "tar", "tempfile", "tokio", @@ -1012,6 +1025,7 @@ dependencies = [ "uuid", "walkdir", "webbrowser", + "zip", ] [[package]] @@ -1030,9 +1044,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.89" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" dependencies = [ "jobserver", "libc", @@ -1050,12 +1064,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "chrono" version = "0.4.34" @@ -1068,14 +1076,24 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", ] [[package]] name = "clap" -version = "4.5.1" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -1083,35 +1101,35 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", ] [[package]] name = "clap_complete" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" +checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -1154,9 +1172,9 @@ dependencies = [ [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "memchr", @@ -1208,6 +1226,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "convert_case" version = "0.4.0" @@ -1241,9 +1265,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -1328,7 +1352,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "crossterm_winapi", "libc", "mio", @@ -1359,12 +1383,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -1412,7 +1436,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -1434,7 +1458,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core 0.20.8", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -1476,9 +1500,9 @@ checksum = "63dfa964fe2a66f3fde91fc70b267fe193d822c7e603e2a675a49a7f46ad3f49" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -1598,7 +1622,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -1621,9 +1645,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" dependencies = [ "serde", ] @@ -1636,9 +1660,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -1649,7 +1673,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 1.0.109", @@ -1705,9 +1729,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "filetime" @@ -1857,7 +1881,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -1913,9 +1937,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", @@ -1932,11 +1956,11 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "git2" -version = "0.18.2" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd" +checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "libgit2-sys", "log", @@ -2008,7 +2032,7 @@ dependencies = [ "gix-utils", "itoa", "thiserror", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -2090,7 +2114,7 @@ dependencies = [ "smallvec", "thiserror", "unicode-bom", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -2099,7 +2123,7 @@ version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbd06203b1a9b33a78c88252a625031b094d9e1b647260070c25b09910c0a804" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "bstr", "gix-path", "libc", @@ -2220,7 +2244,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "682bdc43cb3c00dbedfcc366de2a849b582efd8d886215dbad2ea662ec156bb5" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "bstr", "gix-features", "gix-path", @@ -2266,7 +2290,7 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "881ab3b1fa57f497601a5add8289e72a7ae09471fc0b9bbe483b628ae8e418a1" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "bstr", "filetime", "fnv", @@ -2306,7 +2330,7 @@ checksum = "1dff438f14e67e7713ab9332f5fd18c8f20eb7eb249494f6c2bf170522224032" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -2315,7 +2339,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54ba98f8c8c06870dfc167d192ca38a38261867b836cb89ac80bc9176dba975e" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "gix-commitgraph", "gix-date", "gix-hash", @@ -2341,7 +2365,7 @@ dependencies = [ "itoa", "smallvec", "thiserror", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -2427,7 +2451,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea9f934a111e0efdf93ae06e3648427e60e783099fbebd6a53a7a2ffb10a1e65" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "bstr", "gix-attributes", "gix-config-value", @@ -2464,7 +2488,7 @@ dependencies = [ "gix-utils", "maybe-async", "thiserror", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -2497,7 +2521,7 @@ dependencies = [ "gix-validate", "memmap2", "thiserror", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -2551,7 +2575,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fddc27984a643b20dd03e97790555804f98cf07404e0e552c0ad8133266a79a1" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "gix-path", "libc", "windows-sys 0.52.0", @@ -2616,7 +2640,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4029ec209b0cc480d209da3837a42c63801dd8548f09c1f4502c60accb62aeb" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "gix-commitgraph", "gix-date", "gix-hash", @@ -2647,7 +2671,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35192df7fd0fa112263bad8021e2df7167df4cc2a6e6d15892e1e55621d3d4dc" dependencies = [ - "fastrand 2.0.1", + "fastrand 2.0.2", "unicode-normalization", ] @@ -2715,7 +2739,7 @@ dependencies = [ "bstr", "log", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -2730,7 +2754,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -2749,7 +2773,7 @@ dependencies = [ "futures-sink", "futures-util", "http 1.1.0", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -2814,6 +2838,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -2909,12 +2939,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", - "futures-util", + "futures-core", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -2985,9 +3015,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -3039,7 +3069,7 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "rustls 0.22.4", "rustls-pki-types", @@ -3071,7 +3101,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.3.1", "pin-project-lite", "socket2 0.5.6", "tokio", @@ -3172,9 +3202,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -3196,9 +3226,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "infer" @@ -3206,6 +3236,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -3267,15 +3306,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.12.1" @@ -3287,9 +3317,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jni" @@ -3315,9 +3345,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2" dependencies = [ "libc", ] @@ -3333,13 +3363,13 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "9.2.0" +version = "9.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" +checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" dependencies = [ "base64 0.21.7", "js-sys", - "pem 3.0.3", + "pem 3.0.4", "ring 0.17.8", "serde", "serde_json", @@ -3390,13 +3420,12 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", - "redox_syscall", ] [[package]] @@ -3412,9 +3441,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" +checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" dependencies = [ "cc", "libc", @@ -3503,7 +3532,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -3518,9 +3547,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memmap2" @@ -3585,9 +3614,9 @@ dependencies = [ [[package]] name = "mongodb" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de59562e5c71656c098d8e966641b31da87b89dc3dcb6e761d3b37dcdfa0cb72" +checksum = "ef206acb1b72389b49bc9985efe7eb1f8a9bb18e5680d262fac26c07f44025f1" dependencies = [ "async-trait", "base64 0.13.1", @@ -3650,18 +3679,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags 2.4.2", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -3834,7 +3851,7 @@ checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" dependencies = [ "futures-core", "futures-sink", - "indexmap 2.2.5", + "indexmap 2.2.6", "js-sys", "once_cell", "pin-project-lite", @@ -3906,6 +3923,7 @@ dependencies = [ "futures-core", "http 0.2.12", "opentelemetry 0.21.0", + "opentelemetry-http 0.10.0", "opentelemetry-proto", "opentelemetry-semantic-conventions", "opentelemetry_sdk", @@ -4015,6 +4033,17 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "paste" version = "1.0.14" @@ -4028,6 +4057,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ "digest", + "hmac", + "password-hash", + "sha2", ] [[package]] @@ -4051,11 +4083,11 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "serde", ] @@ -4079,7 +4111,7 @@ name = "permit-client-rs" version = "2.0.0" source = "git+https://github.com/shuttle-hq/permit-client-rs?rev=19085ba#19085ba73bb87c879731590f4a3a988e92d076ac" dependencies = [ - "reqwest 0.11.24", + "reqwest 0.11.27", "serde", "serde_derive", "serde_json", @@ -4093,7 +4125,7 @@ name = "permit-pdp-client-rs" version = "0.2.0" source = "git+https://github.com/shuttle-hq/permit-pdp-client-rs?rev=37c7296#37c72968adf360aa4e2386c3f0c918b823fb919f" dependencies = [ - "reqwest 0.11.24", + "reqwest 0.11.27", "serde", "serde_derive", "serde_json", @@ -4104,29 +4136,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -4262,9 +4294,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -4283,13 +4315,13 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.2", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", "rusty-fork", "tempfile", "unarray", @@ -4307,12 +4339,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" dependencies = [ "bytes", - "prost-derive 0.12.3", + "prost-derive 0.12.4", ] [[package]] @@ -4330,24 +4362,24 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] name = "prost-types" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" dependencies = [ - "prost 0.12.3", + "prost 0.12.4", ] [[package]] @@ -4358,9 +4390,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -4430,7 +4462,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.14", ] [[package]] @@ -4463,7 +4495,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" dependencies = [ - "pem 3.0.3", + "pem 3.0.4", "ring 0.16.20", "time", "yasna", @@ -4480,25 +4512,25 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.14", "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -4518,7 +4550,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -4529,15 +4561,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.11.24" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", @@ -4591,7 +4623,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-rustls 0.26.0", "hyper-util", "ipnet", @@ -4637,7 +4669,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01ff60778f96fb5a48adbe421d21bf6578ed58c0872d712e7e08593c195adff8" dependencies = [ "comma", - "nix 0.25.1", + "nix", "regex", "tempfile", "thiserror", @@ -4666,7 +4698,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.12", + "getrandom 0.2.14", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -4675,9 +4707,9 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" dependencies = [ "byteorder", "num-traits", @@ -4686,9 +4718,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" +checksum = "938a142ab806f18b88a97b0dea523d39e0fd730a064b035726adcfc58a8a5188" dependencies = [ "byteorder", "rmp", @@ -4772,11 +4804,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -4886,9 +4918,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" [[package]] name = "rusty-fork" @@ -4944,9 +4976,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -4957,9 +4989,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -4991,9 +5023,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] @@ -5009,22 +5041,22 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -5032,9 +5064,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -5064,13 +5096,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -5122,15 +5154,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" dependencies = [ "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_derive", "serde_json", @@ -5158,7 +5190,7 @@ dependencies = [ "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -5183,7 +5215,7 @@ checksum = "b93fb4adc70021ac1b47f7d45e8cc4169baaa7ea58483bc5b721d19a26202212" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -5248,7 +5280,7 @@ dependencies = [ "bytes", "clap", "dirs", - "reqwest 0.11.24", + "reqwest 0.11.27", "serde", "serde_json", "shuttle-backends", @@ -5321,7 +5353,7 @@ dependencies = [ "permit-pdp-client-rs", "pin-project", "portpicker", - "reqwest 0.11.24", + "reqwest 0.11.27", "ring 0.17.8", "rustrict", "serde", @@ -5331,7 +5363,7 @@ dependencies = [ "shuttle-common-tests", "shuttle-proto", "sqlx", - "strum 0.26.1", + "strum 0.26.2", "test-context", "thiserror", "tokio", @@ -5355,11 +5387,11 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "reqwest 0.11.24", + "reqwest 0.11.27", "serde", "serde_json", "shuttle-common-tests", - "syn 2.0.52", + "syn 2.0.59", "tokio", "trybuild", ] @@ -5384,12 +5416,12 @@ dependencies = [ "pin-project", "proptest", "rand 0.8.5", - "reqwest 0.11.24", + "reqwest 0.11.27", "semver 1.0.22", "serde", "serde_json", "sqlx", - "strum 0.26.1", + "strum 0.26.2", "thiserror", "tonic 0.10.2", "tower", @@ -5409,7 +5441,7 @@ dependencies = [ "cargo-shuttle", "hyper 0.14.28", "portpicker", - "reqwest 0.11.24", + "reqwest 0.11.27", "serde", "shuttle-common", "shuttle-proto", @@ -5450,7 +5482,7 @@ dependencies = [ "shuttle-proto", "shuttle-service", "sqlx", - "strum 0.26.1", + "strum 0.26.2", "tar", "tempfile", "thiserror", @@ -5498,7 +5530,7 @@ dependencies = [ "portpicker", "rand 0.8.5", "rcgen", - "reqwest 0.11.24", + "reqwest 0.11.27", "ring 0.17.8", "rmp-serde", "rustls 0.21.11", @@ -5512,7 +5544,7 @@ dependencies = [ "shuttle-proto", "snailquote", "sqlx", - "strum 0.26.1", + "strum 0.26.2", "tar", "tempfile", "test-context", @@ -5567,7 +5599,7 @@ dependencies = [ "futures-core", "http 0.2.12", "portpicker", - "prost 0.12.3", + "prost 0.12.4", "prost-types", "serde_json", "shuttle-common", @@ -5589,7 +5621,7 @@ dependencies = [ "mongodb", "once_cell", "portpicker", - "prost 0.12.3", + "prost 0.12.4", "rand 0.8.5", "serde_json", "shuttle-backends", @@ -5620,7 +5652,7 @@ dependencies = [ "shuttle-common-tests", "shuttle-proto", "sqlx", - "strum 0.26.1", + "strum 0.26.2", "thiserror", "tokio", "tonic 0.10.2", @@ -5646,6 +5678,7 @@ dependencies = [ "strfmt", "tokio", "tokio-stream", + "tokio-util", "tonic 0.10.2", "tracing-subscriber", "uuid", @@ -5732,9 +5765,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smart-default" @@ -5824,9 +5857,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" dependencies = [ "sqlx-core", "sqlx-macros", @@ -5837,9 +5870,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" dependencies = [ "ahash", "atoi", @@ -5848,7 +5881,6 @@ dependencies = [ "chrono", "crc", "crossbeam-queue", - "dotenvy", "either", "event-listener", "futures-channel", @@ -5858,7 +5890,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.2.5", + "indexmap 2.2.6", "log", "memchr", "once_cell", @@ -5882,9 +5914,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" dependencies = [ "proc-macro2", "quote", @@ -5895,14 +5927,13 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" dependencies = [ - "atomic-write-file", "dotenvy", "either", - "heck", + "heck 0.4.1", "hex", "once_cell", "proc-macro2", @@ -5922,13 +5953,13 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "bytes", "chrono", @@ -5966,13 +5997,13 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.4.2", + "bitflags 2.5.0", "byteorder", "chrono", "crc", @@ -5994,7 +6025,6 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sha1", "sha2", "smallvec", "sqlx-core", @@ -6007,9 +6037,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" dependencies = [ "atoi", "chrono", @@ -6061,9 +6091,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -6073,11 +6103,11 @@ checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" [[package]] name = "strum" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" dependencies = [ - "strum_macros 0.26.1", + "strum_macros 0.26.2", ] [[package]] @@ -6086,7 +6116,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -6095,15 +6125,15 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -6125,9 +6155,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" dependencies = [ "proc-macro2", "quote", @@ -6203,7 +6233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.1", + "fastrand 2.0.2", "rustix", "windows-sys 0.52.0", ] @@ -6241,27 +6271,27 @@ checksum = "78ea17a2dc368aeca6f554343ced1b1e31f76d63683fa8016e5844bd7a5144a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -6276,9 +6306,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -6299,9 +6329,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -6324,9 +6354,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -6359,7 +6389,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -6385,9 +6415,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -6426,14 +6456,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.6", + "toml_edit 0.22.9", ] [[package]] @@ -6451,22 +6481,22 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.6" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -6515,7 +6545,7 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost 0.12.3", + "prost 0.12.4", "tokio", "tokio-stream", "tower", @@ -6550,7 +6580,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "bytes", "futures-core", "futures-util", @@ -6607,7 +6637,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -6744,17 +6774,17 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9d3ba662913483d6722303f619e75ea10b7855b0f8e0d72799cf8621bb488f" +checksum = "8ad7eb6319ebadebca3dacf1f85a93bc54b73dd81b9036795f73de7ddfe27d5a" dependencies = [ - "basic-toml", "glob", "once_cell", "serde", "serde_derive", "serde_json", "termcolor", + "toml", ] [[package]] @@ -6809,7 +6839,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34778c17965aa2a08913b57e1f34db9b4a63f5de31768b55bf20d2795f921259" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.14", "rand 0.8.5", "serde", "web-time 1.1.0", @@ -6934,11 +6964,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.14", "serde", ] @@ -7039,7 +7069,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", "wasm-bindgen-shared", ] @@ -7073,7 +7103,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7116,9 +7146,9 @@ dependencies = [ [[package]] name = "webbrowser" -version = "0.8.12" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2391658b02c27719fc5a0a73d6e696285138e8b12fba9d4baa70451023c71" +checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" dependencies = [ "core-foundation", "home", @@ -7148,9 +7178,9 @@ dependencies = [ [[package]] name = "whoami" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fec781d48b41f8163426ed18e8fc2864c12937df9ce54c88ede7bd47270893e" +checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ "redox_syscall", "wasite", @@ -7158,9 +7188,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "winapi" @@ -7199,7 +7229,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -7226,7 +7256,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -7261,17 +7291,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -7288,9 +7319,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -7306,9 +7337,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -7324,9 +7355,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -7342,9 +7379,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -7360,9 +7397,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -7378,9 +7415,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -7396,9 +7433,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -7411,9 +7448,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] @@ -7451,7 +7488,7 @@ dependencies = [ "futures", "http 1.1.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "log", "once_cell", @@ -7537,7 +7574,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.59", ] [[package]] @@ -7545,3 +7582,52 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.10+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index e82f35f7e..35d38d1ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,7 +68,7 @@ once_cell = "1.16.0" opentelemetry = "0.21.0" opentelemetry_sdk = { version = "0.21.0", features = ["rt-tokio", "logs"] } opentelemetry-http = "0.10.0" -opentelemetry-otlp = { version = "0.14.0", features = ["logs", "grpc-tonic"] } +opentelemetry-otlp = { version = "0.14.0", features = ["logs", "grpc-tonic", "http-proto"] } opentelemetry-proto = "0.4.0" opentelemetry-contrib = { version = "0.4.0", features = ["datadog"] } opentelemetry-appender-tracing = "0.2.0" @@ -94,6 +94,7 @@ test-context = "0.3.0" thiserror = "1.0.37" tokio = "1.22.0" tokio-stream = "0.1.11" +tokio-util = "0.7.10" toml = "0.8.2" toml_edit = "0.20.2" tonic = "0.10.2" diff --git a/backends/src/client/mod.rs b/backends/src/client/mod.rs index 9319e8f55..2c2f0a424 100644 --- a/backends/src/client/mod.rs +++ b/backends/src/client/mod.rs @@ -60,6 +60,13 @@ impl ServicesApiClient { } } + pub fn new_with_default_headers(base: Uri, headers: HeaderMap) -> Self { + Self { + client: Self::builder().default_headers(headers).build().unwrap(), + base, + } + } + pub async fn get( &self, path: &str, diff --git a/backends/src/headers.rs b/backends/src/headers.rs index 1f9009b7a..27aa05b98 100644 --- a/backends/src/headers.rs +++ b/backends/src/headers.rs @@ -33,6 +33,71 @@ impl Header for XShuttleAdminSecret { } } +pub static X_SHUTTLE_PROJECT_SECRET: HeaderName = + HeaderName::from_static("x-shuttle-project-secret"); + +/// Typed header for sending admin secrets to Shuttle components +pub struct XShuttleProjectSecret(pub String); + +impl Header for XShuttleProjectSecret { + fn name() -> &'static HeaderName { + &X_SHUTTLE_PROJECT_SECRET + } + + fn decode<'i, I>(values: &mut I) -> Result + where + Self: Sized, + I: Iterator, + { + let value = values + .next() + .ok_or_else(headers::Error::invalid)? + .to_str() + .map_err(|_| headers::Error::invalid())? + .to_string(); + + Ok(Self(value)) + } + + fn encode>(&self, values: &mut E) { + if let Ok(value) = HeaderValue::from_str(&self.0) { + values.extend(std::iter::once(value)); + } + } +} + +/// Used to ensure requests originate from the control service. +pub static X_SHUTTLE_CTL_SECRET: HeaderName = HeaderName::from_static("x-shuttle-ctl-secret"); + +pub struct XShuttleCtlSecret(pub String); + +impl Header for XShuttleCtlSecret { + fn name() -> &'static HeaderName { + &X_SHUTTLE_CTL_SECRET + } + + fn decode<'i, I>(values: &mut I) -> Result + where + Self: Sized, + I: Iterator, + { + let value = values + .next() + .ok_or_else(headers::Error::invalid)? + .to_str() + .map_err(|_| headers::Error::invalid())? + .to_string(); + + Ok(Self(value)) + } + + fn encode>(&self, values: &mut E) { + if let Ok(value) = HeaderValue::from_str(self.0.as_str()) { + values.extend(std::iter::once(value)); + } + } +} + /// Used by deployers <=0.38.0. Can be removed when those are no longer supported pub static X_SHUTTLE_PROJECT: HeaderName = HeaderName::from_static("x-shuttle-project"); diff --git a/backends/src/lib.rs b/backends/src/lib.rs index 7e473ff6c..7dad2b884 100644 --- a/backends/src/lib.rs +++ b/backends/src/lib.rs @@ -13,6 +13,7 @@ pub mod headers; pub mod metrics; mod otlp_tracing_bridge; pub mod project_name; +pub mod resource; pub mod trace; #[cfg(any(test, feature = "test-utils"))] diff --git a/backends/src/resource.rs b/backends/src/resource.rs new file mode 100644 index 000000000..ccc6124db --- /dev/null +++ b/backends/src/resource.rs @@ -0,0 +1,16 @@ +use serde::{Deserialize, Serialize}; + +/// Used by the runner service to send requests to control plane, where the requested resources +/// will be provisioned. +#[derive(Serialize, Deserialize)] +pub struct ResourceRequest { + /// The resource input returned from the runtime::load call. + pub resources: Vec>, +} + +/// Used to request the provisioning or deletion of a shared DB from the provisioner service. +#[derive(Deserialize, Serialize)] +pub struct SharedDbRequest { + pub db_name: String, + pub role_name: String, +} diff --git a/backends/src/trace.rs b/backends/src/trace.rs index bd73c82b5..d41bea16b 100644 --- a/backends/src/trace.rs +++ b/backends/src/trace.rs @@ -43,7 +43,7 @@ where .tracing() .with_exporter( opentelemetry_otlp::new_exporter() - .tonic() + .http() .with_endpoint(otlp_address.clone()), ) .with_trace_config(trace::config().with_resource(Resource::new(resources.clone()))) @@ -57,7 +57,7 @@ where .with_log_config(Config::default().with_resource(Resource::new(resources.clone()))) .with_exporter( opentelemetry_otlp::new_exporter() - .tonic() + .http() .with_endpoint(otlp_address), ) .install_batch(Tokio) diff --git a/cargo-shuttle/Cargo.toml b/cargo-shuttle/Cargo.toml index fd10952ba..fed6191f3 100644 --- a/cargo-shuttle/Cargo.toml +++ b/cargo-shuttle/Cargo.toml @@ -4,7 +4,7 @@ version = "0.44.0" edition.workspace = true license.workspace = true repository.workspace = true -description = "A cargo command for the shuttle platform (https://www.shuttle.rs/)" +description = "A cargo command for the Shuttle platform (https://www.shuttle.rs/)" homepage = "https://www.shuttle.rs" [dependencies] @@ -32,10 +32,10 @@ gix = { version = "0.62.0", default-features = false, features = [ "worktree-mutation", ] } globset = "0.4.13" -home = { workspace = true } headers = { workspace = true } -indicatif = "0.17.3" +home = { workspace = true } ignore = "0.4.20" +indicatif = "0.17.3" indoc = "2.0.1" percent-encoding = { workspace = true } portpicker = { workspace = true } @@ -65,6 +65,7 @@ url = { workspace = true } uuid = { workspace = true, features = ["v4"] } walkdir = "2.3.3" webbrowser = "0.8.2" +zip = "0.6.6" [dev-dependencies] assert_cmd = "2.0.6" diff --git a/cargo-shuttle/src/args.rs b/cargo-shuttle/src/args.rs index 16b2652e4..2fdaa65b6 100644 --- a/cargo-shuttle/src/args.rs +++ b/cargo-shuttle/src/args.rs @@ -39,6 +39,9 @@ pub struct ShuttleArgs { /// Turn on tracing output for cargo-shuttle and shuttle libraries. #[arg(long, env = "SHUTTLE_DEBUG")] pub debug: bool, + /// Target Shuttle's development environment + #[arg(long, env = "SHUTTLE_BETA", hide = true)] + pub beta: bool, #[command(subcommand)] pub cmd: Command, @@ -158,13 +161,13 @@ pub enum DeploymentCommand { limit: u32, #[arg(long, default_value_t = false)] - /// Output table in `raw` format + /// Output table without borders raw: bool, }, /// View status of a deployment Status { /// ID of deployment to get status for - id: Uuid, + id: String, }, } @@ -173,7 +176,7 @@ pub enum ResourceCommand { /// List all the resources for a project List { #[arg(long, default_value_t = false)] - /// Output table in `raw` format + /// Output table without borders raw: bool, #[arg( @@ -219,7 +222,7 @@ pub enum ProjectCommand { limit: u32, #[arg(long, default_value_t = false)] - /// Output table in `raw` format + /// Output table without borders raw: bool, }, /// Delete a project and all linked data diff --git a/cargo-shuttle/src/client.rs b/cargo-shuttle/src/client.rs index 4271bbc9a..3991dd15a 100644 --- a/cargo-shuttle/src/client.rs +++ b/cargo-shuttle/src/client.rs @@ -5,16 +5,14 @@ use anyhow::{Context, Result}; use headers::{Authorization, HeaderMapExt}; use percent_encoding::utf8_percent_encode; use reqwest::header::HeaderMap; -use reqwest::RequestBuilder; -use reqwest::Response; +use reqwest::{RequestBuilder, Response}; use serde::{Deserialize, Serialize}; use shuttle_common::constants::headers::X_CARGO_SHUTTLE_VERSION; use shuttle_common::log::LogsRange; use shuttle_common::models::deployment::DeploymentRequest; use shuttle_common::models::team; use shuttle_common::models::{deployment, project, service, ToJson}; -use shuttle_common::secrets::Secret; -use shuttle_common::{resource, ApiKey, ApiUrl, LogItem, VersionInfo}; +use shuttle_common::{resource, ApiKey, LogItem, VersionInfo}; use tokio::net::TcpStream; use tokio_tungstenite::tungstenite::client::IntoClientRequest; use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream}; @@ -22,17 +20,17 @@ use tracing::error; use uuid::Uuid; #[derive(Clone)] -pub struct Client { - api_url: ApiUrl, - api_key: Option>, +pub struct ShuttleApiClient { client: reqwest::Client, + api_url: String, + api_key: Option, + /// alter behaviour to interact with the new platform + beta: bool, } -impl Client { - pub fn new(api_url: ApiUrl) -> Self { +impl ShuttleApiClient { + pub fn new(api_url: String, api_key: Option, beta: bool) -> Self { Self { - api_url, - api_key: None, client: reqwest::Client::builder() .default_headers( HeaderMap::try_from(&HashMap::from([( @@ -44,11 +42,22 @@ impl Client { .timeout(Duration::from_secs(60)) .build() .unwrap(), + api_url, + api_key, + beta, } } pub fn set_api_key(&mut self, api_key: ApiKey) { - self.api_key = Some(Secret::new(api_key)); + self.api_key = Some(api_key); + } + + fn set_auth_bearer(&self, builder: RequestBuilder) -> RequestBuilder { + if let Some(ref api_key) = self.api_key { + builder.bearer_auth(api_key.as_ref()) + } else { + builder + } } pub async fn get_api_versions(&self) -> Result { @@ -87,7 +96,30 @@ impl Client { let url = format!("{}{}", self.api_url, path); let mut builder = self.client.post(url); - builder = self.set_builder_auth(builder); + builder = self.set_auth_bearer(builder); + + builder + .header("Transfer-Encoding", "chunked") + .body(deployment_req) + .send() + .await + .context("failed to send deployment to the Shuttle server")? + .to_json() + .await + } + + pub async fn deploy_beta( + &self, + project: &str, + deployment_req: DeploymentRequest, + ) -> Result { + let path = format!("/projects/{project}"); + let deployment_req = rmp_serde::to_vec(&deployment_req) + .context("serialize DeploymentRequest as a MessagePack byte vector")?; + + let url = format!("{}{}", self.api_url, path); + let mut builder = self.client.put(url); + builder = self.set_auth_bearer(builder); builder .header("Transfer-Encoding", "chunked") @@ -112,7 +144,11 @@ impl Client { } pub async fn get_service_resources(&self, project: &str) -> Result> { - let path = format!("/projects/{project}/services/{project}/resources"); + let path = if self.beta { + format!("/projects/{project}/resources") + } else { + format!("/projects/{project}/services/{project}/resources") + }; self.get(path).await } @@ -122,13 +158,18 @@ impl Client { project: &str, resource_type: &resource::Type, ) -> Result<()> { - let path = format!( - "/projects/{project}/services/{project}/resources/{}", - utf8_percent_encode( - &resource_type.to_string(), - percent_encoding::NON_ALPHANUMERIC - ), - ); + let r#type = resource_type.to_string(); + + let r#type = utf8_percent_encode(&r#type, percent_encoding::NON_ALPHANUMERIC).to_owned(); + + let path = if self.beta { + format!("/projects/{project}/resources/{}", r#type) + } else { + format!( + "/projects/{project}/services/{project}/resources/{}", + r#type + ) + }; self.delete(path).await } @@ -163,10 +204,8 @@ impl Client { self.get(path).await } - pub async fn get_projects_list(&self, page: u32, limit: u32) -> Result> { - let path = format!("/projects?page={}&limit={}", page.saturating_sub(1), limit); - - self.get(path).await + pub async fn get_projects_list(&self) -> Result> { + self.get("/projects".to_owned()).await } pub async fn stop_project(&self, project: &str) -> Result { @@ -176,7 +215,11 @@ impl Client { } pub async fn delete_project(&self, project: &str) -> Result { - let path = format!("/projects/{project}/delete"); + let path = if self.beta { + format!("/projects/{project}") + } else { + format!("/projects/{project}/delete") + }; self.delete(path).await } @@ -231,6 +274,12 @@ impl Client { }; } + pub async fn deployments_beta(&self, project: &str) -> Result> { + let path = format!("/projects/{project}/deployments",); + + self.get(path).await + } + pub async fn get_deployments( &self, project: &str, @@ -246,6 +295,16 @@ impl Client { self.get(path).await } + pub async fn deployment_status( + &self, + project: &str, + deployment_id: &str, + ) -> Result { + let path = format!("/projects/{project}/deployments/{deployment_id}"); + + self.get(path).await + } + pub async fn get_deployment_details( &self, project: &str, @@ -262,12 +321,12 @@ impl Client { } async fn ws_get(&self, path: String) -> Result>> { - let ws_scheme = self.api_url.clone().replace("http", "ws"); - let url = format!("{ws_scheme}{path}"); + let ws_url = self.api_url.clone().replace("http", "ws"); + let url = format!("{ws_url}{path}"); let mut request = url.into_client_request()?; if let Some(ref api_key) = self.api_key { - let auth_header = Authorization::bearer(api_key.expose().as_ref())?; + let auth_header = Authorization::bearer(api_key.as_ref())?; request.headers_mut().typed_insert(auth_header); } @@ -286,8 +345,7 @@ impl Client { let url = format!("{}{}", self.api_url, path); let mut builder = self.client.get(url); - - builder = self.set_builder_auth(builder); + builder = self.set_auth_bearer(builder); builder .send() @@ -301,8 +359,7 @@ impl Client { let url = format!("{}{}", self.api_url, path); let mut builder = self.client.post(url); - - builder = self.set_builder_auth(builder); + builder = self.set_auth_bearer(builder); if let Some(body) = body { let body = serde_json::to_string(&body)?; @@ -317,8 +374,7 @@ impl Client { let url = format!("{}{}", self.api_url, path); let mut builder = self.client.put(url); - - builder = self.set_builder_auth(builder); + builder = self.set_auth_bearer(builder); if let Some(body) = body { let body = serde_json::to_string(&body)?; @@ -336,8 +392,7 @@ impl Client { let url = format!("{}{}", self.api_url, path); let mut builder = self.client.delete(url); - - builder = self.set_builder_auth(builder); + builder = self.set_auth_bearer(builder); builder .send() @@ -346,12 +401,4 @@ impl Client { .to_json() .await } - - fn set_builder_auth(&self, builder: RequestBuilder) -> RequestBuilder { - if let Some(ref api_key) = self.api_key { - builder.bearer_auth(api_key.expose().as_ref()) - } else { - builder - } - } } diff --git a/cargo-shuttle/src/config.rs b/cargo-shuttle/src/config.rs index 73d390d10..7d640081b 100644 --- a/cargo-shuttle/src/config.rs +++ b/cargo-shuttle/src/config.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use anyhow::{anyhow, Context, Result}; use serde::{Deserialize, Serialize}; -use shuttle_common::{constants::API_URL_DEFAULT, ApiKey, ApiUrl}; +use shuttle_common::{constants::API_URL_DEFAULT, ApiKey}; use tracing::trace; use crate::args::ProjectArgs; @@ -122,7 +122,7 @@ impl ConfigManager for LocalConfigManager { #[derive(Deserialize, Serialize, Default)] pub struct GlobalConfig { api_key: Option, - pub api_url: Option, + pub api_url: Option, } impl GlobalConfig { @@ -138,7 +138,7 @@ impl GlobalConfig { self.api_key = None; } - pub fn api_url(&self) -> Option { + pub fn api_url(&self) -> Option { self.api_url.clone() } } @@ -315,7 +315,7 @@ impl RequestContext { self.api_url = api_url; } - pub fn api_url(&self) -> ApiUrl { + pub fn api_url(&self) -> String { if let Some(api_url) = self.api_url.clone() { api_url } else if let Some(api_url) = self.global.as_ref().unwrap().api_url() { diff --git a/cargo-shuttle/src/lib.rs b/cargo-shuttle/src/lib.rs index 21ac3ea0b..78c6d781f 100644 --- a/cargo-shuttle/src/lib.rs +++ b/cargo-shuttle/src/lib.rs @@ -9,7 +9,7 @@ use std::collections::{BTreeMap, HashMap}; use std::ffi::OsString; use std::fmt::Write as FmtWrite; use std::fs::{read_to_string, File}; -use std::io::stdout; +use std::io::{stdout, Read, Write}; use std::net::{Ipv4Addr, SocketAddr}; use std::path::{Path, PathBuf}; use std::process::exit; @@ -32,6 +32,7 @@ use ignore::overrides::OverrideBuilder; use ignore::WalkBuilder; use indicatif::ProgressBar; use indoc::{formatdoc, printdoc}; +use shuttle_common::models::deployment::deployments_table_beta; use shuttle_common::{ constants::{ API_URL_DEFAULT, DEFAULT_IDLE_MINUTES, EXAMPLES_REPO, EXECUTABLE_DIRNAME, @@ -58,6 +59,7 @@ use shuttle_proto::{ provisioner::{provisioner_server::Provisioner, DatabaseRequest}, runtime::{self, LoadRequest, StartRequest, StopRequest}, }; +use shuttle_service::builder::{async_cargo_metadata, find_shuttle_packages}; use shuttle_service::{ builder::{build_workspace, BuiltService}, runner, Environment, @@ -70,13 +72,14 @@ use tokio::time::{sleep, Duration}; use tonic::{Request, Status}; use tracing::{debug, error, trace, warn}; use uuid::Uuid; +use zip::write::FileOptions; pub use crate::args::{Command, ProjectArgs, RunArgs, ShuttleArgs}; use crate::args::{ DeployArgs, DeploymentCommand, InitArgs, LoginArgs, LogoutArgs, LogsArgs, ProjectCommand, ProjectStartArgs, ResourceCommand, TemplateLocation, }; -use crate::client::Client; +use crate::client::ShuttleApiClient; use crate::provisioner_server::LocalProvisioner; const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -97,9 +100,11 @@ pub fn parse_args() -> (ShuttleArgs, bool) { pub struct Shuttle { ctx: RequestContext, - client: Option, + client: Option, version_info: Option, version_warnings: Vec, + /// alter behaviour to interact with the new platform + beta: bool, } impl Shuttle { @@ -110,40 +115,28 @@ impl Shuttle { client: None, version_info: None, version_warnings: vec![], + beta: false, }) } - fn find_available_port(run_args: &mut RunArgs, services_len: usize) { - let default_port = run_args.port; - 'outer: for port in (run_args.port..=std::u16::MAX).step_by(services_len.max(10)) { - for inner_port in port..(port + services_len as u16) { - if !portpicker::is_free_tcp(inner_port) { - continue 'outer; - } - } - run_args.port = port; - break; - } - - if run_args.port != default_port - && !Confirm::with_theme(&ColorfulTheme::default()) - .with_prompt(format!( - "Port {} is already in use. Would you like to continue on port {}?", - default_port, run_args.port - )) - .default(true) - .interact() - .unwrap() - { - exit(0); - } - } - pub async fn run( mut self, args: ShuttleArgs, provided_path_to_init: bool, ) -> Result { + self.beta = args.beta; + if self.beta { + if matches!( + args.cmd, + Command::Project(ProjectCommand::Stop { .. } | ProjectCommand::Restart { .. }) + ) { + unimplemented!("This command is deprecated on the beta platform"); + } + if matches!(args.cmd, Command::Stop | Command::Clean | Command::Status) { + unimplemented!("This command is not yet implemented on the beta platform"); + } + eprintln!("INFO: Using beta platform API"); + } if let Some(ref url) = args.api_url { if url != API_URL_DEFAULT { eprintln!("INFO: Targeting non-standard API: {url}"); @@ -191,13 +184,11 @@ impl Shuttle { | Command::Clean | Command::Project(..) ) { - let mut client = Client::new(self.ctx.api_url()); - if !matches!(args.cmd, Command::Init(..)) { - // init command will handle this by itself (log in and set key) if there is no key yet - client.set_api_key(self.ctx.api_key()?); - } + let client = + ShuttleApiClient::new(self.ctx.api_url(), self.ctx.api_key().ok(), self.beta); self.client = Some(client); - if !args.offline { + if !args.offline && !self.beta { + // TODO: re-implement version checking in control to use the c-s version http header self.check_api_versions().await?; } } @@ -222,11 +213,19 @@ impl Shuttle { Command::Run(run_args) => self.local_run(run_args).await, Command::Deploy(deploy_args) => self.deploy(deploy_args).await, Command::Status => self.status().await, - Command::Logs(logs_args) => self.logs(logs_args).await, + Command::Logs(logs_args) => { + if self.beta { + self.logs_beta(logs_args).await + } else { + self.logs(logs_args).await + } + } Command::Deployment(DeploymentCommand::List { page, limit, raw }) => { self.deployments_list(page, limit, raw).await } - Command::Deployment(DeploymentCommand::Status { id }) => self.deployment_get(id).await, + Command::Deployment(DeploymentCommand::Status { id }) => { + self.deployment_get(id.as_str()).await + } Command::Resource(ResourceCommand::List { raw, show_secrets }) => { self.resources_list(raw, show_secrets).await } @@ -245,9 +244,7 @@ impl Shuttle { Command::Project(ProjectCommand::Status { follow }) => { self.project_status(follow).await } - Command::Project(ProjectCommand::List { page, limit, raw }) => { - self.projects_list(page, limit, raw).await - } + Command::Project(ProjectCommand::List { raw, .. }) => self.projects_list(raw).await, Command::Project(ProjectCommand::Stop) => self.project_stop().await, Command::Project(ProjectCommand::Delete(ConfirmationArgs { yes })) => { self.project_delete(yes).await @@ -839,6 +836,38 @@ impl Shuttle { Ok(CommandOutcome::Ok) } + async fn logs_beta(&self, args: LogsArgs) -> Result { + let client = self.client.as_ref().unwrap(); + let mut stream = client + // TODO: use something else than a fake Uuid + .get_logs_ws(self.ctx.project_name(), &Uuid::new_v4(), LogsRange::All) + .await + .map_err(|err| { + suggestions::logs::get_logs_failure(err, "Connecting to the logs stream failed") + })?; + + while let Some(Ok(msg)) = stream.next().await { + if let tokio_tungstenite::tungstenite::Message::Text(line) = msg { + match serde_json::from_str::(&line) { + Ok(log) => { + if args.raw { + println!("{}", log.line); + } else { + println!("{log}"); + } + } + Err(err) => { + // TODO better handle logs, by returning a different type than the log line + // if an error happened. + bail!(err); + } + } + } + } + + Ok(CommandOutcome::Ok) + } + async fn logs(&self, args: LogsArgs) -> Result { let range = match (args.head, args.tail, args.all) { (Some(num), _, _) => LogsRange::Head(num), @@ -940,21 +969,33 @@ impl Shuttle { let limit = limit + 1; let proj_name = self.ctx.project_name(); - let mut deployments = client - .get_deployments(proj_name, page, limit) - .await - .map_err(suggestions::deployment::get_deployments_list_failure)?; - let page_hint = if deployments.len() == limit as usize { - deployments.pop(); - true + + let deployments_len = if self.beta { + let deployments = client + .deployments_beta(proj_name) + .await + .map_err(suggestions::deployment::get_deployments_list_failure)?; + let table = deployments_table_beta(&deployments, proj_name, raw); + println!("{table}"); + deployments.len() } else { - false - }; - let table = get_deployments_table(&deployments, proj_name, page, raw, page_hint); + let mut deployments = client + .get_deployments(proj_name, page, limit) + .await + .map_err(suggestions::deployment::get_deployments_list_failure)?; + let page_hint = if deployments.len() == limit as usize { + deployments.pop(); + true + } else { + false + }; + let table = get_deployments_table(&deployments, proj_name, page, raw, page_hint); - println!("{table}"); + println!("{table}"); + deployments.len() + }; - if deployments.is_empty() { + if deployments_len == 0 { println!("Run `cargo shuttle deploy` to deploy your project."); } else { println!("Run `cargo shuttle logs ` to get logs for a given deployment."); @@ -963,14 +1004,28 @@ impl Shuttle { Ok(CommandOutcome::Ok) } - async fn deployment_get(&self, deployment_id: Uuid) -> Result { + async fn deployment_get(&self, deployment_id: &str) -> Result { let client = self.client.as_ref().unwrap(); - let deployment = client - .get_deployment_details(self.ctx.project_name(), &deployment_id) - .await - .map_err(suggestions::deployment::get_deployment_status_failure)?; - println!("{deployment}"); + if self.beta { + let deployment = client + .deployment_status(self.ctx.project_name(), deployment_id) + .await + .map_err(suggestions::deployment::get_deployment_status_failure)?; + deployment.colored_println(); + } else { + let deployment = client + .get_deployment_details( + self.ctx.project_name(), + &Uuid::from_str(deployment_id).map_err(|err| { + anyhow!("Provided deployment id is not a valid UUID: {err}") + })?, + ) + .await + .map_err(suggestions::deployment::get_deployment_status_failure)?; + + println!("{deployment}"); + } Ok(CommandOutcome::Ok) } @@ -1037,6 +1092,7 @@ impl Shuttle { } async fn spin_local_runtime( + beta: bool, run_args: &RunArgs, service: &BuiltService, idx: u16, @@ -1100,9 +1156,13 @@ impl Shuttle { } let runtime_executable = service.executable_path.clone(); + let port = + portpicker::pick_unused_port().expect("unable to find available port for gRPC server"); // Child process and gRPC client for sending requests to it let (mut runtime, mut runtime_client) = runner::start( - portpicker::pick_unused_port().expect("unable to find available port for gRPC server"), + beta, + port, + SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port), runtime_executable, service.workspace_path.as_path(), ) @@ -1399,6 +1459,32 @@ impl Shuttle { build_workspace(working_directory, run_args.release, tx, false).await } + fn find_available_port(run_args: &mut RunArgs, services_len: usize) { + let default_port = run_args.port; + 'outer: for port in (run_args.port..=std::u16::MAX).step_by(services_len.max(10)) { + for inner_port in port..(port + services_len as u16) { + if !portpicker::is_free_tcp(inner_port) { + continue 'outer; + } + } + run_args.port = port; + break; + } + + if run_args.port != default_port + && !Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt(format!( + "Port {} is already in use. Would you like to continue on port {}?", + default_port, run_args.port + )) + .default(true) + .interact() + .unwrap() + { + exit(0); + } + } + #[cfg(target_family = "unix")] async fn local_run(&self, mut run_args: RunArgs) -> Result { debug!("starting local run"); @@ -1421,7 +1507,7 @@ impl Shuttle { // We must cover the case of starting multiple workspace services and receiving a signal in parallel. // This must stop all the existing runtimes and creating new ones. signal_received = tokio::select! { - res = Shuttle::spin_local_runtime(&run_args, service, i as u16) => { + res = Shuttle::spin_local_runtime(self.beta, &run_args, service, i as u16) => { match res { Ok(runtime) => { Shuttle::add_runtime_info(runtime, &mut runtimes).await?; @@ -1643,11 +1729,51 @@ impl Shuttle { let client = self.client.as_ref().unwrap(); let working_directory = self.ctx.working_directory(); - let mut deployment_req: DeploymentRequest = DeploymentRequest { + let mut deployment_req = DeploymentRequest { no_test: args.no_test, ..Default::default() }; + if self.beta { + let manifest_path = working_directory.join("Cargo.toml"); + + // Look for a secrets file, first in the command args, and if it isn't there look + // in the root of the crate or workspace. + let secrets_file = args.secret_args.secrets.clone().or_else(|| { + let secrets_file = manifest_path.parent().unwrap().join("Secrets.toml"); + + if secrets_file.exists() && secrets_file.is_file() { + Some(secrets_file) + } else { + None + } + }); + + if let Some(secrets_file) = secrets_file { + trace!("Loading secrets from {}", secrets_file.display()); + if let Ok(secrets_str) = read_to_string(&secrets_file) { + let secrets = toml::from_str::>(&secrets_str)?; + + trace!(keys = ?secrets.keys(), "available secrets"); + + deployment_req.secrets = Some(secrets); + } else { + trace!("No secrets were loaded"); + } + } else { + trace!("No secrets file was found"); + }; + + let metadata = async_cargo_metadata(manifest_path.as_path()).await?; + let packages = find_shuttle_packages(&metadata)?; + let package_name = packages + .first() + .expect("at least one shuttle crate in the workspace") + .name + .to_owned(); + deployment_req.package_name = Some(package_name); + } + if let Ok(repo) = Repository::discover(working_directory) { let repo_path = repo .workdir() @@ -1677,7 +1803,7 @@ impl Shuttle { } } - deployment_req.data = self.make_archive(args.secret_args.secrets.clone())?; + deployment_req.data = self.make_archive(args.secret_args.secrets.clone(), self.beta)?; if deployment_req.data.len() > CREATE_SERVICE_BODY_LIMIT { bail!( r#"The project is too large - the limit is {} MB. \ @@ -1688,6 +1814,17 @@ impl Shuttle { ); } + // End this early for beta platform. + if self.beta { + let deployment = client + .deploy_beta(self.ctx.project_name(), deployment_req) + .await + .map_err(suggestions::deploy::deploy_request_failure)?; + + deployment.colored_println(); + return Ok(CommandOutcome::Ok); + } + let deployment = client .deploy(self.ctx.project_name(), deployment_req) .await @@ -1927,7 +2064,7 @@ impl Shuttle { ) })?; - if idle_minutes > 0 { + if idle_minutes > 0 && !self.beta { let idle_msg = format!( "Your project will sleep if it is idle for {} minutes.", idle_minutes @@ -1953,15 +2090,10 @@ impl Shuttle { Ok(CommandOutcome::Ok) } - async fn projects_list(&self, page: u32, limit: u32, raw: bool) -> Result { + async fn projects_list(&self, raw: bool) -> Result { let client = self.client.as_ref().unwrap(); - if limit == 0 { - println!(); - return Ok(CommandOutcome::Ok); - } - let limit = limit + 1; - let mut projects = client.get_projects_list(page, limit).await.map_err(|err| { + let projects = client.get_projects_list().await.map_err(|err| { suggestions::project::project_request_failure( err, "Getting projects list failed", @@ -1969,40 +2101,31 @@ impl Shuttle { "getting the projects list fails repeatedly", ) })?; - let page_hint = if projects.len() == limit as usize { - projects.pop(); - true - } else { - false - }; - let projects_table = project::get_projects_table(&projects, page, raw, page_hint); + let projects_table = project::get_projects_table(&projects, raw); println!("{}", "Personal Projects".bold()); println!("{projects_table}"); + if self.beta { + println!("Not listing team projects (not implemented yet on beta)"); + return Ok(CommandOutcome::Ok); + } + let teams = client.get_teams_list().await?; for team in teams { - let mut team_projects = - client - .get_team_projects_list(&team.id) - .await - .map_err(|err| { - suggestions::project::project_request_failure( - err, - "Getting teams projects list failed", - false, - "getting the team projects list fails repeatedly", - ) - })?; - let page_hint = if team_projects.len() == limit as usize { - team_projects.pop(); - true - } else { - false - }; - let team_projects_table = - project::get_projects_table(&team_projects, page, raw, page_hint); + let team_projects = client + .get_team_projects_list(&team.id) + .await + .map_err(|err| { + suggestions::project::project_request_failure( + err, + "Getting teams projects list failed", + false, + "getting the team projects list fails repeatedly", + ) + })?; + let team_projects_table = project::get_projects_table(&team_projects, raw); println!("{}", format!("{}'s Projects", team.display_name).bold()); println!("{team_projects_table}"); @@ -2150,10 +2273,8 @@ impl Shuttle { Ok(CommandOutcome::Ok) } - fn make_archive(&self, secrets_file: Option) -> Result> { + fn make_archive(&self, secrets_file: Option, zip: bool) -> Result> { let include_patterns = self.ctx.assets(); - let encoder = GzEncoder::new(Vec::new(), Compression::new(3)); - let mut tar = Builder::new(encoder); let working_directory = self.ctx.working_directory(); @@ -2221,8 +2342,14 @@ impl Shuttle { continue; } + // zip file puts all files in root, tar puts all files nested in a dir at root level + let prefix = if zip { + working_directory + } else { + working_directory.parent().context("get parent dir")? + }; let mut name = path - .strip_prefix(working_directory.parent().context("get parent dir")?) + .strip_prefix(prefix) .context("strip prefix of path")? .to_owned(); @@ -2240,14 +2367,34 @@ impl Shuttle { bail!("No files included in upload."); } - // Append all the entries to the archive. - for (k, v) in archive_files { - debug!("Packing {k:?}"); - tar.append_path_with_name(k, v)?; - } + let bytes = if zip { + debug!("making zip archive"); + let mut zip = zip::ZipWriter::new(std::io::Cursor::new(Vec::new())); + for (path, name) in archive_files { + debug!("Packing {path:?}"); + zip.start_file( + name.to_str().expect("valid filename"), + FileOptions::default(), + )?; + let mut b = Vec::new(); + File::open(path)?.read_to_end(&mut b)?; + zip.write_all(&b)?; + } + let r = zip.finish().context("finish encoding zip archive")?; - let encoder = tar.into_inner().context("get encoder from tar archive")?; - let bytes = encoder.finish().context("finish up encoder")?; + r.into_inner() + } else { + debug!("making tar archive"); + let encoder = GzEncoder::new(Vec::new(), Compression::new(3)); + let mut tar = Builder::new(encoder); + for (path, name) in archive_files { + debug!("Packing {path:?}"); + tar.append_path_with_name(path, name)?; + } + let encoder = tar.into_inner().context("get encoder from tar archive")?; + + encoder.finish().context("finish encoding tar archive")? + }; debug!("Archive size: {} bytes", bytes.len()); Ok(bytes) @@ -2434,10 +2581,12 @@ pub enum CommandOutcome { mod tests { use flate2::read::GzDecoder; use tar::Archive; + use zip::ZipArchive; use crate::args::{DeployArgs, ProjectArgs, SecretsArgs}; use crate::Shuttle; use std::fs::{self, canonicalize}; + use std::io::Cursor; use std::path::PathBuf; pub fn path_from_workspace_root(path: &str) -> PathBuf { @@ -2448,32 +2597,43 @@ mod tests { dunce::canonicalize(path).unwrap() } - fn get_archive_entries(project_args: ProjectArgs, deploy_args: DeployArgs) -> Vec { + fn get_archive_entries( + project_args: ProjectArgs, + deploy_args: DeployArgs, + zip: bool, + ) -> Vec { let mut shuttle = Shuttle::new().unwrap(); shuttle.load_project(&project_args).unwrap(); let archive = shuttle - .make_archive(deploy_args.secret_args.secrets) + .make_archive(deploy_args.secret_args.secrets, zip) .unwrap(); - let tar = GzDecoder::new(&archive[..]); - let mut archive = Archive::new(tar); + if zip { + let mut zip = ZipArchive::new(Cursor::new(archive)).unwrap(); + (0..zip.len()) + .map(|i| zip.by_index(i).unwrap().name().to_owned()) + .collect() + } else { + let tar = GzDecoder::new(&archive[..]); + let mut archive = Archive::new(tar); - archive - .entries() - .unwrap() - .map(|entry| { - entry - .unwrap() - .path() - .unwrap() - .components() - .skip(1) - .collect::() - .display() - .to_string() - }) - .collect() + archive + .entries() + .unwrap() + .map(|entry| { + entry + .unwrap() + .path() + .unwrap() + .components() + .skip(1) + .collect::() + .display() + .to_string() + }) + .collect() + } } #[test] @@ -2497,29 +2657,32 @@ mod tests { working_directory: working_directory.clone(), name: Some("archiving-test".to_owned()), }; - let mut entries = get_archive_entries(project_args.clone(), Default::default()); + let mut entries = get_archive_entries(project_args.clone(), Default::default(), false); entries.sort(); - assert_eq!( - entries, - vec![ - ".gitignore", - ".ignore", - "Cargo.toml", - "Secrets.toml", // always included by default - "Secrets.toml.example", - "Shuttle.toml", - "asset1", // normal file - "asset2", // .gitignore'd, but included in Shuttle.toml - // asset3 is .ignore'd - "asset4", // .gitignore'd, but un-ignored in .ignore - "asset5", // .ignore'd, but included in Shuttle.toml - "dist/dist1", // .gitignore'd, but included in Shuttle.toml - "nested/static/nested1", // normal file - // nested/static/nestedignore is .gitignore'd - "src/main.rs", - ] - ); + let expected = vec![ + ".gitignore", + ".ignore", + "Cargo.toml", + "Secrets.toml", // always included by default + "Secrets.toml.example", + "Shuttle.toml", + "asset1", // normal file + "asset2", // .gitignore'd, but included in Shuttle.toml + // asset3 is .ignore'd + "asset4", // .gitignore'd, but un-ignored in .ignore + "asset5", // .ignore'd, but included in Shuttle.toml + "dist/dist1", // .gitignore'd, but included in Shuttle.toml + "nested/static/nested1", // normal file + // nested/static/nestedignore is .gitignore'd + "src/main.rs", + ]; + assert_eq!(entries, expected); + + // check that zip behaves the same way + let mut entries = get_archive_entries(project_args.clone(), Default::default(), true); + entries.sort(); + assert_eq!(entries, expected); fs::remove_file(working_directory.join("Secrets.toml")).unwrap(); let mut entries = get_archive_entries( @@ -2530,6 +2693,7 @@ mod tests { }, ..Default::default() }, + false, ); entries.sort(); diff --git a/cargo-shuttle/tests/integration/main.rs b/cargo-shuttle/tests/integration/main.rs index fd16de68a..60516f6a7 100644 --- a/cargo-shuttle/tests/integration/main.rs +++ b/cargo-shuttle/tests/integration/main.rs @@ -22,6 +22,7 @@ async fn cargo_shuttle_command( }, offline: false, debug: false, + beta: false, cmd, }, false, diff --git a/common-tests/src/cargo_shuttle.rs b/common-tests/src/cargo_shuttle.rs index 1cfe17d22..9414f6142 100644 --- a/common-tests/src/cargo_shuttle.rs +++ b/common-tests/src/cargo_shuttle.rs @@ -43,6 +43,7 @@ pub async fn cargo_shuttle_run(working_directory: &str, external: bool) -> Strin }, offline: false, debug: false, + beta: false, cmd: Command::Run(run_args), }, false, diff --git a/common/src/deployment.rs b/common/src/deployment.rs index ef93e39a4..65e464760 100644 --- a/common/src/deployment.rs +++ b/common/src/deployment.rs @@ -19,6 +19,21 @@ pub enum State { Unknown, } +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Display, Serialize, EnumString)] +#[serde(rename_all = "lowercase")] +#[strum(serialize_all = "lowercase")] +#[strum(ascii_case_insensitive)] +pub enum EcsState { + Pending, + Building, + Running, + #[strum(serialize = "in progress")] + InProgress, + Stopped, + Stopping, + Failed, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeploymentMetadata { pub env: Environment, diff --git a/common/src/lib.rs b/common/src/lib.rs index c08f3ecc8..6d2ffb36f 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -14,6 +14,8 @@ pub mod limits; pub mod log; #[cfg(feature = "service")] pub use log::LogItem; +#[cfg(feature = "service")] +pub use log::LogItemBeta; #[cfg(feature = "models")] pub mod models; pub mod resource; @@ -29,9 +31,6 @@ use anyhow::bail; use serde::{Deserialize, Serialize}; use zeroize::Zeroize; -pub type ApiUrl = String; -pub type Host = String; - #[derive(Clone, Serialize, Deserialize)] #[cfg_attr(feature = "persist", derive(PartialEq, Eq, Hash, sqlx::Type))] #[cfg_attr(feature = "persist", serde(transparent))] @@ -163,6 +162,14 @@ impl DatabaseInfo { self.database_name, ) } + + pub fn role_name(&self) -> String { + self.role_name.to_string() + } + + pub fn database_name(&self) -> String { + self.database_name.to_string() + } } /// Used to request a container from the local run provisioner diff --git a/common/src/log.rs b/common/src/log.rs index 542abe95d..691c40cc7 100644 --- a/common/src/log.rs +++ b/common/src/log.rs @@ -28,6 +28,7 @@ pub enum Backend { Logger, Provisioner, ResourceRecorder, + Control, Runtime(String), } @@ -54,6 +55,45 @@ pub struct LogItem { pub line: String, } +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct LogItemBeta { + /// Time log was captured + pub timestamp: DateTime, + + /// Stdout/stderr + pub source: String, + + /// The log line + pub line: String, +} + +impl LogItemBeta { + pub fn new(timestamp: DateTime, source: String, line: String) -> Self { + Self { + timestamp, + source, + line, + } + } +} + +#[cfg(feature = "display")] +impl std::fmt::Display for LogItemBeta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let datetime: chrono::DateTime = DateTime::from(self.timestamp); + + write!( + f, + "{} [{}] {}", + datetime + .to_rfc3339_opts(chrono::SecondsFormat::Millis, false) + .dim(), + self.source, + self.line, + ) + } +} + const LOGLINE_MAX_CHARS: usize = 2048; const TRUNC_MSG: &str = "... (truncated)"; diff --git a/common/src/models/deployment.rs b/common/src/models/deployment.rs index aa874460d..fdbf6a390 100644 --- a/common/src/models/deployment.rs +++ b/common/src/models/deployment.rs @@ -6,10 +6,10 @@ use comfy_table::{ }; use crossterm::style::Stylize; use serde::{Deserialize, Serialize}; -use std::{fmt::Display, str::FromStr}; +use std::{collections::HashMap, fmt::Display, str::FromStr}; use uuid::Uuid; -use crate::deployment::State; +use crate::deployment::{EcsState, State}; /// Max length of strings in the git metadata pub const GIT_STRINGS_MAX_LENGTH: usize = 80; @@ -29,6 +29,19 @@ pub struct Response { pub git_dirty: Option, } +#[derive(Deserialize, Serialize)] +pub struct EcsResponse { + pub id: String, + pub latest_deployment_state: EcsState, + pub running_id: Option, + pub updated_at: DateTime, + pub uri: Option, + pub git_commit_id: Option, + pub git_commit_msg: Option, + pub git_branch: Option, + pub git_dirty: Option, +} + impl Display for Response { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( @@ -47,6 +60,59 @@ impl Display for Response { } } +impl EcsResponse { + pub fn colored_println(&self) { + let running_deployment = self + .running_id + .as_ref() + .map(|id| { + format!( + "\nRunning deployment: '{}' - {} {}", + id, + "running".to_string().with( + crossterm::style::Color::from_str(EcsState::Running.get_color()).unwrap() + ), + self.uri + .as_ref() + .map(|inner| format!("({inner})")) + .unwrap_or("".to_string()) + ) + }) + .unwrap_or_default(); + + // Stringify the state. + let latest_state = format!( + "{}", + self.latest_deployment_state + .to_string() + // Unwrap is safe because Color::from_str returns the color white if the argument is not a Color. + .with( + crossterm::style::Color::from_str(self.latest_deployment_state.get_color()) + .unwrap() + ) + ); + + let state_with_uri = match self.running_id { + None if EcsState::Running == self.latest_deployment_state + || EcsState::InProgress == self.latest_deployment_state => + { + let uri = self + .uri + .as_ref() + .map(|inner| format!(" ({inner})")) + .unwrap_or_default(); + format!("{latest_state}{uri}") + } + _ => latest_state, + }; + + println!( + "Current deployment: '{}' - {}{running_deployment}", + self.id, state_with_uri + ) + } +} + impl State { /// We return a &str rather than a Color here, since `comfy-table` re-exports /// crossterm::style::Color and we depend on both `comfy-table` and `crossterm` @@ -62,6 +128,147 @@ impl State { } } +impl EcsState { + /// We return a &str rather than a Color here, since `comfy-table` re-exports + /// crossterm::style::Color and we depend on both `comfy-table` and `crossterm` + /// we may end up with two different versions of Color. + pub fn get_color(&self) -> &str { + match self { + EcsState::Pending => "dark_yellow", + EcsState::Building => "yellow", + EcsState::InProgress => "cyan", + EcsState::Running => "green", + EcsState::Stopped => "dark_blue", + EcsState::Stopping => "blue", + EcsState::Failed => "red", + } + } +} + +pub fn deployments_table_beta( + deployments: &Vec, + project_name: &str, + raw: bool, +) -> String { + if deployments.is_empty() { + // The page starts at 1 in the CLI. + let mut s = "No deployments are linked to this service\n".to_string(); + if !raw { + s = s.yellow().bold().to_string(); + } + + s + } else { + let mut table = Table::new(); + + if raw { + table + .load_preset(NOTHING) + .set_content_arrangement(ContentArrangement::Disabled) + .set_header(vec![ + Cell::new("Deployment ID").set_alignment(CellAlignment::Left), + Cell::new("Status").set_alignment(CellAlignment::Left), + Cell::new("Last updated").set_alignment(CellAlignment::Left), + Cell::new("Commit ID").set_alignment(CellAlignment::Left), + Cell::new("Commit Message").set_alignment(CellAlignment::Left), + Cell::new("Branch").set_alignment(CellAlignment::Left), + Cell::new("Dirty").set_alignment(CellAlignment::Left), + ]); + } else { + table + .load_preset(UTF8_FULL) + .apply_modifier(UTF8_ROUND_CORNERS) + .set_content_arrangement(ContentArrangement::DynamicFullWidth) + .set_header(vec![ + Cell::new("Deployment ID") + .set_alignment(CellAlignment::Center) + .add_attribute(Attribute::Bold), + Cell::new("Status") + .set_alignment(CellAlignment::Center) + .add_attribute(Attribute::Bold), + Cell::new("Last updated") + .set_alignment(CellAlignment::Center) + .add_attribute(Attribute::Bold), + Cell::new("Commit ID") + .set_alignment(CellAlignment::Center) + .add_attribute(Attribute::Bold), + Cell::new("Commit Message") + .set_alignment(CellAlignment::Center) + .add_attribute(Attribute::Bold), + Cell::new("Branch") + .set_alignment(CellAlignment::Center) + .add_attribute(Attribute::Bold), + Cell::new("Dirty") + .set_alignment(CellAlignment::Center) + .add_attribute(Attribute::Bold), + ]); + } + + for deploy in deployments.iter() { + let truncated_commit_id = deploy + .git_commit_id + .as_ref() + .map_or(String::from(GIT_OPTION_NONE_TEXT), |val| { + val.chars().take(7).collect() + }); + + let truncated_commit_msg = deploy + .git_commit_msg + .as_ref() + .map_or(String::from(GIT_OPTION_NONE_TEXT), |val| { + val.chars().take(24).collect::() + }); + + if raw { + table.add_row(vec![ + Cell::new(&deploy.id), + Cell::new(&deploy.latest_deployment_state), + Cell::new(deploy.updated_at.format("%Y-%m-%dT%H:%M:%SZ")), + Cell::new(truncated_commit_id), + Cell::new(truncated_commit_msg), + Cell::new( + deploy + .git_branch + .as_ref() + .map_or(GIT_OPTION_NONE_TEXT, |val| val as &str), + ), + Cell::new( + deploy + .git_dirty + .map_or(String::from(GIT_OPTION_NONE_TEXT), |val| val.to_string()), + ), + ]); + } else { + table.add_row(vec![ + Cell::new(&deploy.id), + Cell::new(&deploy.latest_deployment_state) + // Unwrap is safe because Color::from_str returns the color white if str is not a Color. + .fg(Color::from_str(deploy.latest_deployment_state.get_color()).unwrap()) + .set_alignment(CellAlignment::Center), + Cell::new(deploy.updated_at.format("%Y-%m-%dT%H:%M:%SZ")) + .set_alignment(CellAlignment::Center), + Cell::new(truncated_commit_id), + Cell::new(truncated_commit_msg), + Cell::new( + deploy + .git_branch + .as_ref() + .map_or(GIT_OPTION_NONE_TEXT, |val| val as &str), + ), + Cell::new( + deploy + .git_dirty + .map_or(String::from(GIT_OPTION_NONE_TEXT), |val| val.to_string()), + ) + .set_alignment(CellAlignment::Center), + ]); + } + } + + format!("\nMost recent deployments for {project_name}\n{table}\n") + } +} + pub fn get_deployments_table( deployments: &[Response], service_name: &str, @@ -202,7 +409,13 @@ pub fn get_deployments_table( #[derive(Default, Deserialize, Serialize)] pub struct DeploymentRequest { + /// Alpha: tar archive. Beta: zip archive. pub data: Vec, + /// The cargo package name to compile and run. Required on beta. + pub package_name: Option, + /// Secrets to add before this deployment. Ignored on alpha. + pub secrets: Option>, + /// Ignored on beta. pub no_test: bool, pub git_commit_id: Option, pub git_commit_msg: Option, diff --git a/common/src/models/project.rs b/common/src/models/project.rs index 5cbd8557a..0fd7821a1 100644 --- a/common/src/models/project.rs +++ b/common/src/models/project.rs @@ -174,14 +174,9 @@ pub enum Owner { Team(String), } -pub fn get_projects_table(projects: &[Response], page: u32, raw: bool, page_hint: bool) -> String { +pub fn get_projects_table(projects: &[Response], raw: bool) -> String { if projects.is_empty() { - // The page starts at 1 in the CLI. - let mut s = if page <= 1 { - "No projects are linked to this account\n".to_string() - } else { - "No more projects are linked to this account\n".to_string() - }; + let mut s = "No projects are linked to this account\n".to_string(); if !raw { s = s.yellow().bold().to_string(); } @@ -227,14 +222,6 @@ pub fn get_projects_table(projects: &[Response], page: u32, raw: bool, page_hint } } - let formatted_table = format!("\nThese projects are linked to this account\n{table}\n"); - if page_hint { - format!( - "{formatted_table}More projects are available on the next page using `--page {}`\n", - page + 1 - ) - } else { - formatted_table - } + format!("\nThese projects are linked to this account\n{table}\n") } } diff --git a/deployer/src/runtime_manager.rs b/deployer/src/runtime_manager.rs index a0c261adc..bd9162b4e 100644 --- a/deployer/src/runtime_manager.rs +++ b/deployer/src/runtime_manager.rs @@ -1,5 +1,6 @@ use std::{ collections::HashMap, + net::{Ipv4Addr, SocketAddr}, path::{Path, PathBuf}, sync::Arc, }; @@ -57,9 +58,15 @@ impl RuntimeManager { .unwrap_or_default() ); - let (mut process, runtime_client) = runner::start(port, runtime_executable, project_path) - .await - .context("failed to start shuttle runtime")?; + let (mut process, runtime_client) = runner::start( + false, + port, + SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port), + runtime_executable, + project_path, + ) + .await + .context("failed to start shuttle runtime")?; let stdout = process .stdout diff --git a/extras/otel/otel-collector-config.yaml b/extras/otel/otel-collector-config.yaml index 1eda42279..5f209e83e 100644 --- a/extras/otel/otel-collector-config.yaml +++ b/extras/otel/otel-collector-config.yaml @@ -2,6 +2,7 @@ receivers: otlp: protocols: grpc: + http: # The hostmetrics receiver is required to get correct infrastructure metrics in Datadog. hostmetrics: collection_interval: 10s diff --git a/proto/runtime.proto b/proto/runtime.proto index 3748e6129..1b3617808 100644 --- a/proto/runtime.proto +++ b/proto/runtime.proto @@ -13,6 +13,9 @@ service Runtime { // Channel to notify a service has been stopped rpc SubscribeStop(SubscribeStopRequest) returns (stream SubscribeStopResponse); + + rpc Version(Ping) returns (VersionInfo); + rpc HealthCheck(Ping) returns (Pong); } message LoadRequest { @@ -78,3 +81,10 @@ enum StopReason { // Service crashed Crash = 2; } + +message Ping {} +message Pong {} + +message VersionInfo { + string version = 1; +} diff --git a/proto/src/generated/runtime.rs b/proto/src/generated/runtime.rs index 09eb3cca5..18a3dde62 100644 --- a/proto/src/generated/runtime.rs +++ b/proto/src/generated/runtime.rs @@ -73,6 +73,18 @@ pub struct SubscribeStopResponse { #[prost(string, tag = "2")] pub message: ::prost::alloc::string::String, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Ping {} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Pong {} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VersionInfo { + #[prost(string, tag = "1")] + pub version: ::prost::alloc::string::String, +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum StopReason { @@ -264,6 +276,40 @@ pub mod runtime_client { .insert(GrpcMethod::new("runtime.Runtime", "SubscribeStop")); self.inner.server_streaming(req, path, codec).await } + pub async fn version( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static("/runtime.Runtime/Version"); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("runtime.Runtime", "Version")); + self.inner.unary(req, path, codec).await + } + pub async fn health_check( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static("/runtime.Runtime/HealthCheck"); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("runtime.Runtime", "HealthCheck")); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -298,6 +344,14 @@ pub mod runtime_server { &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; + async fn version( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn health_check( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; } #[derive(Debug)] pub struct RuntimeServer { @@ -534,6 +588,77 @@ pub mod runtime_server { }; Box::pin(fut) } + "/runtime.Runtime/Version" => { + #[allow(non_camel_case_types)] + struct VersionSvc(pub Arc); + impl tonic::server::UnaryService for VersionSvc { + type Response = super::VersionInfo; + type Future = BoxFuture, tonic::Status>; + fn call(&mut self, request: tonic::Request) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { ::version(&inner, request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = VersionSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/runtime.Runtime/HealthCheck" => { + #[allow(non_camel_case_types)] + struct HealthCheckSvc(pub Arc); + impl tonic::server::UnaryService for HealthCheckSvc { + type Response = super::Pong; + type Future = BoxFuture, tonic::Status>; + fn call(&mut self, request: tonic::Request) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = + async move { ::health_check(&inner, request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = HealthCheckSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => Box::pin(async move { Ok(http::Response::builder() .status(200) diff --git a/proto/src/lib.rs b/proto/src/lib.rs index b2676f35a..0a6f221b6 100644 --- a/proto/src/lib.rs +++ b/proto/src/lib.rs @@ -146,16 +146,14 @@ mod _runtime_client { use tracing::{info, trace}; pub type Client = runtime_client::RuntimeClient< - shuttle_common::claims::ClaimService< - shuttle_common::claims::InjectPropagation, - >, + shuttle_common::claims::InjectPropagation, >; /// Get a runtime client that is correctly configured #[cfg(feature = "client")] - pub async fn get_client(port: &str) -> anyhow::Result { + pub async fn get_client(address: String) -> anyhow::Result { info!("connecting runtime client"); - let conn = Endpoint::new(format!("http://127.0.0.1:{port}")) + let conn = Endpoint::new(address) .context("creating runtime client endpoint")? .connect_timeout(Duration::from_secs(5)); @@ -177,7 +175,6 @@ mod _runtime_client { .context("runtime control port did not open in time")?; let runtime_service = tower::ServiceBuilder::new() - .layer(shuttle_common::claims::ClaimLayer) .layer(shuttle_common::claims::InjectPropagationLayer) .service(channel); diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index c4b20b440..9002708f6 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -22,12 +22,13 @@ serde = { workspace = true } serde_json = { workspace = true } strfmt = { workspace = true } tokio = { workspace = true, features = ["full"] } +tokio-util = { workspace = true } tokio-stream = { workspace = true } tonic = { workspace = true } tracing-subscriber = { workspace = true, optional = true } [dev-dependencies] -portpicker = "0.1.1" +portpicker = { workspace = true } shuttle-service = { workspace = true, features = ["builder", "runner"] } shuttle-proto = { workspace = true, features = ["provisioner"] } uuid = { workspace = true } diff --git a/runtime/src/alpha.rs b/runtime/src/alpha.rs index 0675b55f5..8bf0ff543 100644 --- a/runtime/src/alpha.rs +++ b/runtime/src/alpha.rs @@ -2,9 +2,9 @@ use std::{ collections::BTreeMap, iter::FromIterator, net::{Ipv4Addr, SocketAddr}, - ops::DerefMut, + ops::{Deref, DerefMut}, str::FromStr, - sync::Mutex, + sync::{Arc, Mutex}, time::Duration, }; @@ -14,8 +14,8 @@ use core::future::Future; use shuttle_common::{extract_propagation::ExtractPropagationLayer, secrets::Secret}; use shuttle_proto::runtime::{ runtime_server::{Runtime, RuntimeServer}, - LoadRequest, LoadResponse, StartRequest, StartResponse, StopReason, StopRequest, StopResponse, - SubscribeStopRequest, SubscribeStopResponse, + LoadRequest, LoadResponse, Ping, Pong, StartRequest, StartResponse, StopReason, StopRequest, + StopResponse, SubscribeStopRequest, SubscribeStopResponse, VersionInfo, }; use shuttle_service::{ResourceFactory, Service}; use tokio::sync::{ @@ -23,24 +23,70 @@ use tokio::sync::{ mpsc, oneshot, }; use tokio_stream::wrappers::ReceiverStream; +use tokio_util::sync::CancellationToken; use tonic::{transport::Server, Request, Response, Status}; -use crate::args::args; -use crate::print_version; +use crate::version; -// uses custom macro instead of clap to reduce dependency weight -args! { - pub struct Args { - // The port to open the gRPC control layer on. - // The address to expose for the service is given in the StartRequest. - "--port" => pub port: u16, +#[derive(Default)] +struct Args { + /// Enable compatibility with beta platform + beta: bool, + /// Alpha (required): Port to open gRPC server on + port: Option, + /// Beta (required): Address to bind the gRPC server to + address: Option, +} + +impl Args { + // uses simple arg parsing logic instead of clap to reduce dependency weight + fn parse() -> anyhow::Result { + let mut args = Self::default(); + + // The first argument is the path of the executable + let mut args_iter = std::env::args().skip(1); + + while let Some(arg) = args_iter.next() { + match arg.as_str() { + "--beta" => { + args.beta = true; + } + "--port" => { + let port = args_iter + .next() + .context("missing port value")? + .parse() + .context("invalid port value")?; + args.port = Some(port); + } + "--address" => { + let address = args_iter + .next() + .context("missing address value")? + .parse() + .context("invalid address value")?; + args.address = Some(address); + } + _ => {} + } + } + + if args.beta { + if args.address.is_none() { + return Err(anyhow::anyhow!("--address is required with --beta")); + } + } else if args.port.is_none() { + return Err(anyhow::anyhow!("--port is required")); + } + + Ok(args) } } pub async fn start(loader: impl Loader + Send + 'static, runner: impl Runner + Send + 'static) { - // `--version` overrides any other arguments. + // `--version` overrides any other arguments. Used by cargo-shuttle to check compatibility on local runs. if std::env::args().any(|arg| arg == "--version") { - print_version(); + println!("{}", version()); return; } @@ -84,42 +130,73 @@ pub async fn start(loader: impl Loader + Send + 'static, runner: impl Runner + S } // where to serve the gRPC control layer - let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), args.port); + let addr = if args.beta { + args.address.unwrap() + } else { + SocketAddr::new(Ipv4Addr::LOCALHOST.into(), args.port.unwrap()) + }; let mut server_builder = Server::builder() .http2_keepalive_interval(Some(Duration::from_secs(60))) .layer(ExtractPropagationLayer); + // A cancellation token we can use to kill the runtime if it does not start in time. + let token = CancellationToken::new(); + let cloned_token = token.clone(); + let router = { - let alpha = Alpha::new(loader, runner); + let alpha = Alpha::new(args.beta, loader, runner, token); let svc = RuntimeServer::new(alpha); server_builder.add_service(svc) }; - match router.serve(addr).await { - Ok(_) => {} - Err(e) => panic!("Error while serving address {addr}: {e}"), - }; + tokio::select! { + res = router.serve(addr) => { + match res{ + Ok(_) => println!("router completed on its own"), + Err(e) => panic!("Error while serving address {addr}: {e}") + } + } + _ = cloned_token.cancelled() => { + panic!("runtime future was cancelled") + } + } +} + +pub enum State { + Unhealthy, + Loading, + Running, } pub struct Alpha { + /// alter behaviour to interact with the new platform + beta: bool, // Mutexes are for interior mutability stopped_tx: Sender<(StopReason, String)>, kill_tx: Mutex>>, loader: Mutex>, runner: Mutex>, + /// The current state of the runtime, which is used by the ECS task to determine if the runtime + /// is healthy. + state: Arc>, + // A cancellation token we can use to kill the runtime if it does not start in time. + cancellation_token: CancellationToken, } impl Alpha { - pub fn new(loader: L, runner: R) -> Self { + pub fn new(beta: bool, loader: L, runner: R, cancellation_token: CancellationToken) -> Self { let (stopped_tx, _stopped_rx) = broadcast::channel(10); Self { + beta, stopped_tx, kill_tx: Mutex::new(None), loader: Mutex::new(Some(loader)), runner: Mutex::new(Some(runner)), + state: Arc::new(Mutex::new(State::Unhealthy)), + cancellation_token, } } } @@ -223,6 +300,26 @@ where } }; + *self.state.lock().unwrap() = State::Loading; + + let state = self.state.clone(); + let cancellation_token = self.cancellation_token.clone(); + + // State and cancellation is not used in alpha + if self.beta { + // Ensure that the runtime is set to unhealthy if it doesn't reach the running state after + // it has sent a load response, so that the ECS task will fail. + tokio::spawn(async move { + // Note: The timeout is quite long since RDS can take a long time to provision. + tokio::time::sleep(Duration::from_secs(180)).await; + if !matches!(state.lock().unwrap().deref(), State::Running) { + println!("the runtime failed to enter the running state before timing out"); + + cancellation_token.cancel(); + } + }); + } + Ok(Response::new(LoadResponse { success: true, message: String::new(), @@ -355,6 +452,8 @@ where ..Default::default() }; + *self.state.lock().unwrap() = State::Running; + Ok(Response::new(message)) } @@ -398,4 +497,19 @@ where Ok(Response::new(ReceiverStream::new(rx))) } + + async fn version(&self, _requset: Request) -> Result, Status> { + Ok(Response::new(VersionInfo { version: version() })) + } + + async fn health_check(&self, _request: Request) -> Result, Status> { + if matches!(self.state.lock().unwrap().deref(), State::Unhealthy) { + println!("runtime health check failed"); + return Err(Status::unavailable( + "runtime has not reached a healthy state", + )); + } + + Ok(Response::new(Pong {})) + } } diff --git a/runtime/src/args.rs b/runtime/src/args.rs deleted file mode 100644 index 1c2a48b9c..000000000 --- a/runtime/src/args.rs +++ /dev/null @@ -1,80 +0,0 @@ -#[derive(Debug)] -pub enum Error { - DuplicatedArgument { arg: &'static str }, - MissingRequiredArgument { arg: &'static str }, - UnexpectedArgument { arg: String }, - - InvalidValue { arg: &'static str, value: String }, - MissingValue { arg: &'static str }, -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::DuplicatedArgument { arg } => write!(f, "duplicated argument {arg}"), - Self::MissingRequiredArgument { arg } => write!(f, "missing required argument {arg}"), - Self::UnexpectedArgument { arg } => write!(f, "unexpected argument: {arg}"), - - Self::InvalidValue { arg, value } => { - write!(f, "invalid value for argument {arg}: {value}") - } - Self::MissingValue { arg } => write!(f, "missing value for argument {arg}"), - } - } -} - -impl std::error::Error for Error {} - -macro_rules! args { - // Internal rules used to handle optional default values - (@unwrap $arg:literal, $field:ident $(,)?) => { - $field.ok_or_else(|| $crate::args::Error::MissingRequiredArgument { arg: $arg })? - }; - (@unwrap $arg:literal, $field:ident, $default:literal) => { - $field.unwrap_or_else(|| $default.parse().unwrap()) - }; - - ( - pub struct $struct:ident { - $($arg:literal => $(#[arg(default_value = $default:literal)])? pub $field:ident: $ty:ty),+ $(,)? - } - ) => { - #[derive(::std::fmt::Debug)] - pub struct $struct { - $(pub $field: $ty,)+ - } - - impl $struct { - pub fn parse() -> ::std::result::Result { - $(let mut $field: ::std::option::Option<$ty> = None;)+ - - // The first argument is the path of the executable. - let mut args_iter = ::std::env::args().skip(1); - while let ::std::option::Option::Some(arg) = args_iter.next() { - match arg.as_str() { - $($arg => { - if $field.is_some() { - return ::std::result::Result::Err($crate::args::Error::DuplicatedArgument { arg: $arg }); - } - let raw_value = args_iter - .next() - .ok_or_else(|| $crate::args::Error::MissingValue { arg: $arg })?; - let value = raw_value.parse().map_err(|_| $crate::args::Error::InvalidValue { - arg: $arg, - value: raw_value, - })?; - $field = ::std::option::Option::Some(value); - })+ - _ => return ::std::result::Result::Err($crate::args::Error::UnexpectedArgument { arg }), - } - } - - ::std::result::Result::Ok($struct { - $($field: $crate::args::args!(@unwrap $arg, $field, $($default)?),)+ - }) - } - } - } -} - -pub(crate) use args; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 02ebdd4ac..adb3157f6 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -16,12 +16,11 @@ pub use async_trait::async_trait; pub use tokio; mod alpha; -mod args; const NAME: &str = env!("CARGO_PKG_NAME"); const VERSION: &str = env!("CARGO_PKG_VERSION"); -fn print_version() { - println!("{} {}", crate::NAME, crate::VERSION); +fn version() -> String { + format!("{} {}", crate::NAME, crate::VERSION) } // Not part of public API diff --git a/runtime/tests/integration/helpers.rs b/runtime/tests/integration/helpers.rs index 9fe093634..2a5cf1089 100644 --- a/runtime/tests/integration/helpers.rs +++ b/runtime/tests/integration/helpers.rs @@ -45,8 +45,14 @@ pub async fn spawn_runtime(project_path: &str) -> Result { let runtime_executable = service.executable_path.clone(); - let (runtime, runtime_client) = - runner::start(runtime_port, runtime_executable, Path::new(project_path)).await?; + let (runtime, runtime_client) = runner::start( + false, + runtime_port, + runtime_address, + runtime_executable, + Path::new(project_path), + ) + .await?; Ok(TestRuntime { runtime_client, diff --git a/service/src/builder.rs b/service/src/builder.rs index e60eaa3a4..a6f86828a 100644 --- a/service/src/builder.rs +++ b/service/src/builder.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use std::process::Stdio; use anyhow::{anyhow, bail, Context}; -use cargo_metadata::Package; +use cargo_metadata::{Metadata, Package}; use shuttle_common::constants::RUNTIME_NAME; use tokio::io::AsyncBufReadExt; use tracing::{debug, error, info, trace}; @@ -99,12 +99,30 @@ pub async fn build_workspace( } notification.abort(); + let metadata = async_cargo_metadata(manifest_path.as_path()).await?; + let packages = find_shuttle_packages(&metadata)?; + + let services = compile( + packages, + release_mode, + project_path.clone(), + metadata.target_directory.clone(), + deployment, + tx.clone(), + ) + .await?; + trace!("alpha packages compiled"); + + Ok(services) +} + +pub async fn async_cargo_metadata(manifest_path: &Path) -> anyhow::Result { let metadata = { // Modified implementaion of `cargo_metadata::MetadataCommand::exec` (from v0.15.3). // Uses tokio Command instead of std, to make this operation non-blocking. let mut cmd = tokio::process::Command::from( cargo_metadata::MetadataCommand::new() - .manifest_path(&manifest_path) + .manifest_path(manifest_path) .cargo_command(), ); @@ -120,11 +138,13 @@ pub async fn build_workspace( .ok_or(cargo_metadata::Error::NoJson)?; cargo_metadata::MetadataCommand::parse(json)? }; - trace!("Cargo metadata parsed"); - let mut alpha_packages = Vec::new(); + Ok(metadata) +} +pub fn find_shuttle_packages(metadata: &Metadata) -> anyhow::Result> { + let mut packages = Vec::new(); for member in metadata.workspace_packages() { // skip non-Shuttle-related crates if !member @@ -141,23 +161,12 @@ pub async fn build_workspace( .map(|d| format!("{} '{}'", d.name, d.req)) .collect::>(); shuttle_deps.sort(); - info!(name = member.name, deps = ?shuttle_deps, "Compiling workspace member with shuttle dependencies"); + info!(name = member.name, deps = ?shuttle_deps, "Found workspace member with shuttle dependencies"); ensure_binary(member)?; - alpha_packages.push(member); + packages.push(member.to_owned()); } - let services = compile( - alpha_packages, - release_mode, - project_path.clone(), - metadata.target_directory.clone(), - deployment, - tx.clone(), - ) - .await?; - trace!("alpha packages compiled"); - - Ok(services) + Ok(packages) } // Only used in deployer @@ -191,7 +200,7 @@ fn ensure_binary(package: &Package) -> anyhow::Result<()> { } async fn compile( - packages: Vec<&Package>, + packages: Vec, release_mode: bool, project_path: PathBuf, target_path: impl Into, diff --git a/service/src/runner.rs b/service/src/runner.rs index 5cb949558..b324c62f1 100644 --- a/service/src/runner.rs +++ b/service/src/runner.rs @@ -1,4 +1,5 @@ use std::{ + net::SocketAddr, path::{Path, PathBuf}, process::Stdio, }; @@ -9,12 +10,24 @@ use tokio::process; use tracing::info; pub async fn start( + beta: bool, port: u16, + // only used on beta. must match port. + address: SocketAddr, runtime_executable: PathBuf, project_path: &Path, ) -> anyhow::Result<(process::Child, runtime::Client)> { - let port = &port.to_string(); - let args = vec!["--port", port]; + let mut args = vec![]; + if beta { + let addr_str = address.to_string(); + args.push("--beta".to_owned()); + args.push("--address".to_owned()); + args.push(addr_str); + } else { + let port_str = port.to_string(); + args.push("--port".to_owned()); + args.push(port_str); + } info!( args = %format!("{} {}", runtime_executable.display(), args.join(" ")), @@ -30,7 +43,8 @@ pub async fn start( .spawn() .context("spawning runtime process")?; - let runtime_client = runtime::get_client(port).await?; + // runtime might start on localhost or 0.0.0.0, but we can reach it on localhost:port + let runtime_client = runtime::get_client(format!("http://localhost:{port}")).await?; Ok((runtime, runtime_client)) }