diff --git a/.gitignore b/.gitignore index ea8c4bf..96ef6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index 704bb08..6a8715f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,7 +105,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -115,7 +115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -150,6 +150,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -161,6 +167,18 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] [[package]] name = "bollard" @@ -168,7 +186,7 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d41711ad46fda47cd701f6908e59d1bd6b9a2b7464c0d0aeab95c6d37096ff8a" dependencies = [ - "base64", + "base64 0.22.1", "bollard-stubs", "bytes", "futures-core", @@ -270,7 +288,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -319,12 +337,70 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "config" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" +dependencies = [ + "async-trait", + "convert_case", + "json5", + "lazy_static", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml", + "yaml-rust", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + [[package]] name = "crankshaft" version = "0.1.0" @@ -333,18 +409,38 @@ dependencies = [ "bollard", "bytes", "clap", + "config", + "dirs", "futures", "indexmap 2.5.0", "nonempty", "paste", "rand", "random_word", + "serde", "tokio", + "toml", "tracing", "tracing-subscriber", "url", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "deranged" version = "0.3.11" @@ -355,6 +451,46 @@ dependencies = [ "serde", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -465,6 +601,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -488,6 +634,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + [[package]] name = "hashbrown" version = "0.14.5" @@ -704,6 +856,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -716,6 +879,22 @@ version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "lock_api" version = "0.4.12" @@ -747,6 +926,12 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.4" @@ -765,7 +950,17 @@ dependencies = [ "hermit-abi", "libc", "wasi", - "windows-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", ] [[package]] @@ -814,6 +1009,22 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-multimap" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ed8acf08e98e744e5384c8bc63ceb0364e68a6854187221c18df61c4797690e" +dependencies = [ + "dlv-list", + "hashbrown 0.13.2", +] + [[package]] name = "overload" version = "0.1.1" @@ -840,7 +1051,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -849,12 +1060,63 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -973,6 +1235,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.6" @@ -1017,6 +1290,28 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags", + "serde", + "serde_derive", +] + +[[package]] +name = "rust-ini" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e2a3bcec1f113553ef1c88aae6c020a369d03d55b58de9869a0908930385091" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1078,6 +1373,15 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1096,7 +1400,7 @@ version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -1107,6 +1411,17 @@ dependencies = [ "time", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -1153,7 +1468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1234,6 +1549,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -1264,7 +1588,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1291,6 +1615,40 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +dependencies = [ + "indexmap 2.5.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -1385,6 +1743,18 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "unicase" version = "2.7.0" @@ -1415,6 +1785,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + [[package]] name = "url" version = "2.5.2" @@ -1542,7 +1918,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -1551,7 +1936,22 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1560,28 +1960,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1594,30 +2012,72 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/Cargo.toml b/Cargo.toml index 3f96628..0828ffa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,13 +8,17 @@ async-trait = "0.1.82" bollard = "0.17.1" bytes = "1.7.1" clap = { version = "4.5.16", features = ["derive"] } +config = "0.14.0" +dirs = "5.0.1" futures = "0.3.30" indexmap = "2.5.0" nonempty = "0.10.0" paste = "1.0.15" rand = "0.8.5" random_word = { version = "0.4.3", features = ["en"] } +serde = "1.0.209" tokio = { version = "1.40.0", features = ["full", "time"] } +toml = "0.8.19" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } url = "2.5.2" diff --git a/configs/example.toml b/configs/example.toml new file mode 100644 index 0000000..789964a --- /dev/null +++ b/configs/example.toml @@ -0,0 +1,15 @@ +[[backends]] +name = "test" +kind = "Generic" +command = "echo ${name}" + +[[backends]] +name = "quux" +kind = "Generic" +command = "bsub ${script}" +default-cpu = 1 +default-ram = 1 + +[[backends]] +name = "docker" +kind = "Docker" diff --git a/configs/generic_simple.toml b/configs/generic_simple.toml new file mode 100644 index 0000000..db271be --- /dev/null +++ b/configs/generic_simple.toml @@ -0,0 +1,10 @@ +[[backends]] +name = "HelloGeneric" +kind = "Generic" +command = "echo Hello ${name}" + +[[backends]] +name = "HelloGenericWithDefaults" +kind = "Generic" +command = "echo I have ${ram} mb of ram" +default-ram = 4096 diff --git a/src/engine.rs b/src/engine.rs index 7120055..fefcaab 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,5 +1,6 @@ //! Engine. +pub mod config; pub mod service; pub mod task; @@ -7,6 +8,7 @@ use futures::future::join_all; pub use task::Task; use tracing::debug; +use crate::engine::service::runner::backend::docker; use crate::engine::service::runner::Handle; use crate::engine::service::runner::Runner; @@ -18,6 +20,15 @@ pub struct Engine { } impl Engine { + /// Gets an engine with a Docker backend. + pub fn with_docker() -> docker::Result { + let docker = docker::Runner::try_new()?; + + Ok(Self { + runner: Runner::new(docker), + }) + } + /// Submits a [`Task`] to be executed. /// /// A [`Handle`] is returned, which contains a channel that can be awaited @@ -35,8 +46,6 @@ impl Engine { impl Default for Engine { fn default() -> Self { - Self { - runner: Runner::docker(), - } + Self::with_docker().expect("could not initialize engine") } } diff --git a/src/engine/config.rs b/src/engine/config.rs new file mode 100644 index 0000000..42f4f80 --- /dev/null +++ b/src/engine/config.rs @@ -0,0 +1,62 @@ +//! Global config options and loading from .crankshaft + +use std::path::PathBuf; + +use config::ConfigError; +use serde::{Deserialize, Serialize}; + +use super::service::runner::backend::backend_config::BackendConfig; + +/// The config loaded from a global file. +/// Currently contains just a list of available backends +#[derive(Serialize, Deserialize, Debug)] +pub struct Config { + /// All backends that exist + pub backends: Vec, +} + +impl Config { + /// Loads a config from the global .crankshaft file found in the user's home directory + pub fn load_from_global_config() -> Result { + let home_dir = dirs::home_dir().unwrap(); + let config_path = home_dir.join(".crankshaft"); + + Self::load_from_file(config_path) + } + + /// Loads a config file from a given path + pub fn load_from_file

(path: P) -> Result + where + P: Into, + { + let path = path.into(); + let config_file: config::File<_, _> = path.into(); + + let settings = config::Config::builder().add_source(config_file); + settings.build()?.try_deserialize() + } +} + +#[cfg(test)] +mod tests { + use super::Config; + + #[test] + fn loading_file_returns_valid_backends() { + let config = + Config::load_from_file("configs/example.toml").expect("Load from example config"); + + assert_eq!(config.backends.len(), 3) + } + + #[test] + fn loading_config_holds_valid_fields() { + let config = + Config::load_from_file("configs/example.toml").expect("Load from example config"); + let backend = &config.backends[1]; + + assert_eq!(backend.name, "quux"); + assert_eq!(backend.default_cpu, Some(1)); + assert_eq!(backend.default_ram, Some(1)); + } +} diff --git a/src/engine/service/runner.rs b/src/engine/service/runner.rs index c7b1f96..6af2172 100644 --- a/src/engine/service/runner.rs +++ b/src/engine/service/runner.rs @@ -4,7 +4,6 @@ use futures::future::BoxFuture; use futures::stream::FuturesUnordered; use tokio::sync::oneshot::Receiver; -use crate::engine::service::runner::backend::docker; use crate::engine::service::runner::backend::Backend; use crate::engine::service::runner::backend::Reply; use crate::engine::Task; @@ -22,21 +21,17 @@ pub struct Handle { #[derive(Debug)] pub struct Runner { /// The task runner itself. - runner: Box, + backend: Box, /// The list of submitted tasks. pub tasks: FuturesUnordered>, } impl Runner { - /// Creates a Docker-backed [`Runner`]. - /// - /// # Panics - /// - /// If initialization of the [`bollard`](bollard) client fails. - pub fn docker() -> Self { + /// Creates a new [`Runner`]. + pub fn new(backend: impl Backend) -> Self { Self { - runner: Box::new(docker::Runner::try_new().unwrap()), + backend: Box::new(backend), tasks: Default::default(), } } @@ -44,8 +39,7 @@ impl Runner { /// Submits a task to be executed by the backend. pub fn submit(&self, task: Task) -> Handle { let (tx, rx) = tokio::sync::oneshot::channel(); - let a = Box::pin(self.runner.run(task, tx)); - self.tasks.push(a); + self.tasks.push(Box::pin(self.backend.run(task, tx))); Handle { callback: rx } } diff --git a/src/engine/service/runner/backend.rs b/src/engine/service/runner/backend.rs index 7801336..d899c48 100644 --- a/src/engine/service/runner/backend.rs +++ b/src/engine/service/runner/backend.rs @@ -7,6 +7,9 @@ use futures::future::BoxFuture; use nonempty::NonEmpty; use tokio::sync::oneshot::Sender; +pub mod backend_config; +pub mod generic; + pub use std::fmt::Debug; use crate::engine::Task; diff --git a/src/engine/service/runner/backend/backend_config.rs b/src/engine/service/runner/backend/backend_config.rs new file mode 100644 index 0000000..9e49529 --- /dev/null +++ b/src/engine/service/runner/backend/backend_config.rs @@ -0,0 +1,140 @@ +//! Configuration for different types of backends + +use std::{ + collections::HashMap, + process::{Command, Output}, +}; + +use serde::{Deserialize, Serialize}; + +/// Configuration for an arbitrary backend +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct BackendConfig { + /// The backend's name + pub name: String, + /// The backend's type + #[serde(flatten)] + pub kind: BackendType, + /// The default cpu count if present + #[serde(rename = "default-cpu", default)] + pub default_cpu: Option, + /// The default ram if present + #[serde(rename = "default-ram", default)] + pub default_ram: Option, +} + +impl BackendConfig { + /// Submits a backend based on its config. Likely this method will be removed and the branch for Generic will be moved to GenericBackend's submit method. + /// Instead of this method we should have a to_backend() method or something similar that creates a Box based on config. + pub fn submit( + &self, + replacements: &mut HashMap, + left_placeholder: &str, + right_placeholder: &str, + ) -> Option { + // Replace default flags only if it isn't already set + + if let Some(cpu) = self.default_cpu { + replacements + .entry("cpu".to_string()) + .or_insert(cpu.to_string()); + } + + if let Some(ram) = self.default_ram { + replacements + .entry("ram".to_string()) + .or_insert(ram.to_string()); + } + + match &self.kind { + BackendType::Generic(generic) => { + let mut command_str = generic.command.clone(); + for (key, value) in replacements { + let placeholder_key = + format!("{}{}{}", left_placeholder, key, right_placeholder); + command_str = command_str.replace(&placeholder_key, value); + } + + let output = Command::new("sh") + .arg("-c") + .arg(command_str) + .output() + .expect("Failed to run command"); + Some(output) + } + BackendType::Docker(_docker) => { + // Because this method is really only to test the generic backend's submitting, I'm going to leave Docker unimplemented unless otherwise requested + None + } + } + } +} + +/// An enum representing extra metadata supplied in the config file depending on the kind of backend +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "kind")] +pub enum BackendType { + /// Generic backend config, will contain the shell script string for submitting + Generic(GenericBackendConfig), + /// Docker config details + Docker(DockerBackendConfig), +} + +/// Extra attributes for Generic Backends +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct GenericBackendConfig { + /// The script command that will be run on submit + command: String, +} + +/// Extra attributes for Docker backends +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct DockerBackendConfig; + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + + use crate::engine::config::Config; + + #[test] + fn simple_generic_config_loads_and_runs() { + let config = Config::load_from_file("configs/generic_simple.toml") + .expect("Load from example config"); + let backend = &config.backends[0]; + let mut replacements = HashMap::new(); + replacements.insert("name".to_string(), "Kids24".to_string()); + + let output = backend + .submit(&mut replacements, "${", "}") + .expect("Get output from generic backend"); + assert_eq!(output.stdout, b"Hello Kids24\n"); + } + + #[test] + fn generic_config_with_defaults_uses_them() { + let config = Config::load_from_file("configs/generic_simple.toml") + .expect("Load from example config"); + let backend = &config.backends[1]; + let mut replacements = HashMap::new(); + + let output = backend + .submit(&mut replacements, "${", "}") + .expect("Get output from generic backend"); + assert_eq!(output.stdout, b"I have 4096 mb of ram\n"); + } + + #[test] + fn generic_config_with_defaults_and_parameters_set_uses_parameters() { + let config = Config::load_from_file("configs/generic_simple.toml") + .expect("Load from example config"); + let backend = &config.backends[1]; + let mut replacements = HashMap::new(); + replacements.insert("ram".to_string(), 2.to_string()); + + let output = backend + .submit(&mut replacements, "${", "}") + .expect("Get output from generic backend"); + assert_eq!(output.stdout, b"I have 2 mb of ram\n"); + } +} diff --git a/src/engine/service/runner/backend/generic.rs b/src/engine/service/runner/backend/generic.rs new file mode 100644 index 0000000..4a06cd2 --- /dev/null +++ b/src/engine/service/runner/backend/generic.rs @@ -0,0 +1,14 @@ +//! Generic backend implementation +//! +//! Note: Generic backend isn't actually constructed currently. Once we have a `Backend` trait, I'd like to add a `to_backend` method to `BackendConfig` +//! that returns something like a `Box.` For now since we don't have this yet, I just have the submit method directly in `BackendConfig` + +/// A generic backend +pub struct GenericBackend { + /// Default cpu count + pub default_cpu: Option, + /// Default ram amount in mb + pub default_ram_mb: Option, + /// command to run on submit + pub submit: String, +}