diff --git a/.forgejo/workflows/docker.yaml b/.forgejo/workflows/docker.yaml index a8c493d..dfbdb95 100644 --- a/.forgejo/workflows/docker.yaml +++ b/.forgejo/workflows/docker.yaml @@ -4,7 +4,6 @@ on: push: branches: ["main"] paths: - - "Cargo.toml" - ".forgejo/workflows/docker.yaml" - "nix/image/**" @@ -17,9 +16,10 @@ jobs: strategy: matrix: - php-version: ["8.0", "8.1", "8.2", "8.3", "8.4", "8.5"] + php-version: ["8.2", "8.3", "8.4"] + variant: [""] - name: haze-${{ matrix.php-version }} + name: haze-${{ matrix.php-version }}${{ matrix.variant }} steps: - name: Checkout repository diff --git a/Cargo.lock b/Cargo.lock index 821ff04..4cfe4f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,14 +18,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] -name = "aes" -version = "0.8.4" +name = "android-tzdata" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "cfg-if", - "cipher", - "cpufeatures 0.2.17", + "libc", ] [[package]] @@ -86,13 +90,13 @@ checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -118,36 +122,13 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "aws-lc-rs" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a7b350e3bb1767102698302bc37256cbd48422809984b98d292c40e2579aa9" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.37.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", -] - [[package]] name = "axum" -version = "0.8.8" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8" dependencies = [ "axum-core", - "axum-macros", "bytes", "form_urlencoded", "futures-util", @@ -162,7 +143,8 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "serde_core", + "rustversion", + "serde", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -176,34 +158,24 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733" dependencies = [ "bytes", - "futures-core", + "futures-util", "http", "http-body", "http-body-util", "mime", "pin-project-lite", + "rustversion", "sync_wrapper", "tower-layer", "tower-service", "tracing", ] -[[package]] -name = "axum-macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "backtrace" version = "0.3.74" @@ -216,7 +188,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -228,12 +200,6 @@ dependencies = [ "backtrace", ] -[[package]] -name = "base16ct" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" - [[package]] name = "base64" version = "0.22.1" @@ -246,29 +212,11 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" -[[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 = "block-buffer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" -dependencies = [ - "hybrid-array", -] - [[package]] name = "bollard" -version = "0.21.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d0a013e3d3ee4edd61e779adf117944c08902d375f18630a0c5b8f95659734" +checksum = "97ccca1260af6a459d75994ad5acc1651bcabcbdbc41467cc9786519ab854c30" dependencies = [ "base64", "bollard-stubs", @@ -287,6 +235,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "serde_repr", "serde_urlencoded", "thiserror 2.0.12", "tokio", @@ -298,13 +247,13 @@ dependencies = [ [[package]] name = "bollard-stubs" -version = "1.53.1-rc.29.3.1" +version = "1.47.1-rc.27.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce412eb6f7096743011dc3cb5c674caeb24ced61d8c498fe07cf7998a4fea889" +checksum = "3f179cfbddb6e77a5472703d4b30436bff32929c0aa8a9008ecf23d1d3cdd0da" dependencies = [ "serde", - "serde_json", "serde_repr", + "serde_with", ] [[package]] @@ -320,9 +269,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byteorder" @@ -336,42 +285,26 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" -[[package]] -name = "bzip2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" -dependencies = [ - "libbz2-rs-sys", -] - [[package]] name = "camino" -version = "1.2.2" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ - "serde_core", + "serde", ] [[package]] name = "cc" -version = "1.2.56" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ - "find-msvc-tools", "jobserver", "libc", "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.0" @@ -379,30 +312,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cfg_aliases" -version = "0.2.1" +name = "chrono" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chacha20" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "rand_core 0.10.1", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.7", - "inout", + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-link", ] [[package]] @@ -436,7 +355,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -445,244 +364,46 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" -[[package]] -name = "cmake" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" -dependencies = [ - "cc", -] - [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "console" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4" -dependencies = [ - "encode_unicode", - "libc", - "once_cell", - "unicode-width 0.2.0", - "windows-sys 0.61.2", -] - -[[package]] -name = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - -[[package]] -name = "constant_time_eq" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[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.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" -version = "1.5.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] -name = "crossbeam-deque" -version = "0.8.6" +name = "dbus" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", + "libc", + "libdbus-sys", + "winapi", ] -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-common" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "deflate64" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2" - [[package]] name = "deranged" -version = "0.5.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", -] - -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "crypto-common 0.1.7", - "subtle", -] - -[[package]] -name = "digest" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "285743a676ccb6b3e116bc14cc69319b957867930ae9c4822f8e0f54509d7243" -dependencies = [ - "block-buffer 0.12.0", - "const-oid", - "crypto-common 0.2.1", + "serde", ] [[package]] @@ -714,27 +435,15 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "either" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - [[package]] name = "enum_dispatch" version = "0.3.13" @@ -744,7 +453,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -775,21 +484,14 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - [[package]] name = "flate2" -version = "1.1.9" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", "miniz_oxide", - "zlib-rs", ] [[package]] @@ -798,12 +500,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -813,12 +509,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures-channel" version = "0.3.31" @@ -830,19 +520,19 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-macro" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -853,33 +543,24 @@ checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-macro", "futures-task", "pin-project-lite", + "pin-utils", "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" @@ -887,52 +568,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi", - "wasip2", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi", - "rand_core 0.10.1", - "wasip2", - "wasip3", - "wasm-bindgen", -] - -[[package]] -name = "getset" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" -dependencies = [ - "proc-macro-error2", - "proc-macro2", - "quote", - "syn", ] [[package]] @@ -943,39 +580,55 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "git2" -version = "0.21.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddddbf932745a6be37109b6112d3ee09696106f848449069d3a57bba937ab82e" +checksum = "3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff" dependencies = [ "bitflags", "libc", "libgit2-sys", "log", + "url", ] +[[package]] +name = "h2" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.7.1", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "foldhash", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "haze" -version = "2.3.0" +version = "2.1.5" dependencies = [ "async-trait", "atty", "axum", - "base16ct", "bollard", "camino", "directories-next", @@ -986,7 +639,6 @@ dependencies = [ "hyper", "hyper-reverse-proxy", "hyper-util", - "indicatif", "itertools", "local-ip-address", "maplit", @@ -994,21 +646,17 @@ dependencies = [ "opener", "owo-colors", "petname", - "rayon", "reqwest", "serde", "serde_json", - "sha2 0.11.0-rc.5", "shell-words", "strum", "tar", "termion", "tokio", - "tokio-stream", "toml", "tracing", "tracing-subscriber", - "zip", ] [[package]] @@ -1038,15 +686,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - [[package]] name = "http" version = "1.2.0" @@ -1093,32 +732,22 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hybrid-array" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" -dependencies = [ - "typenum", -] - [[package]] name = "hyper" -version = "1.8.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ - "atomic-waker", "bytes", "futures-channel", - "futures-core", + "futures-util", + "h2", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -1142,47 +771,26 @@ dependencies = [ [[package]] name = "hyper-reverse-proxy" version = "0.5.2-dev" -source = "git+https://code.betamike.com/micropelago/hyper-reverse-proxy.git?rev=d5a6f799189360d9449ae47ab3cdde511f02cf39#d5a6f799189360d9449ae47ab3cdde511f02cf39" +source = "git+https://github.com/chpio/hyper-reverse-proxy?rev=6934877eb74465204f605cc1c05ca5a9772db7c0#6934877eb74465204f605cc1c05ca5a9772db7c0" dependencies = [ - "http-body-util", "hyper", "hyper-util", "tokio", "tracing", ] -[[package]] -name = "hyper-rustls" -version = "0.27.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" -dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - [[package]] name = "hyper-util" -version = "0.1.20" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ - "base64", "bytes", "futures-channel", "futures-util", "http", "http-body", "hyper", - "ipnet", - "libc", - "percent-encoding", "pin-project-lite", "socket2", "tokio", @@ -1205,6 +813,29 @@ dependencies = [ "tower-service", ] +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "icu_collections" version = "1.5.0" @@ -1320,21 +951,9 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "1.0.3" @@ -1358,36 +977,24 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.15.2", "serde", - "serde_core", -] - -[[package]] -name = "indicatif" -version = "0.18.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" -dependencies = [ - "console", - "portable-atomic", - "unicode-width 0.2.0", - "unit-prefix", - "web-time", -] - -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", ] [[package]] @@ -1396,16 +1003,6 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" -[[package]] -name = "iri-string" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is-terminal" version = "0.4.16" @@ -1444,28 +1041,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - [[package]] name = "jobserver" version = "0.1.32" @@ -1491,29 +1066,27 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - -[[package]] -name = "libbz2-rs-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" - [[package]] name = "libc" -version = "0.2.182" +version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" + +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "cc", + "pkg-config", +] [[package]] name = "libgit2-sys" -version = "0.18.5+1.9.4" +version = "0.18.0+1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005d6ae6eac1912906073e069f7db60b1fa98e052a68227824afe3e3a1c59ca2" +checksum = "e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec" dependencies = [ "cc", "libc", @@ -1558,44 +1131,21 @@ checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "local-ip-address" -version = "0.6.10" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ef8c257c92ade496781a32a581d43e3d512cf8ce714ecf04ea80f93ed0ff4a" +checksum = "656b3b27f8893f7bbf9485148ff9a65f019e3f33bd5cdc87c83cab16b3fd9ec8" dependencies = [ "libc", "neli", - "windows-sys 0.61.2", -] - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", + "thiserror 2.0.12", + "windows-sys 0.59.0", ] [[package]] name = "log" -version = "0.4.29" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - -[[package]] -name = "lzma-rust2" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47bb1e988e6fb779cf720ad431242d3f03167c1b3f2b1aae7f1a94b2495b36ae" -dependencies = [ - "sha2 0.10.9", -] +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "maplit" @@ -1617,9 +1167,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miette" -version = "7.6.0" +version = "7.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484" dependencies = [ "backtrace", "backtrace-ext", @@ -1631,18 +1181,19 @@ dependencies = [ "supports-unicode", "terminal_size", "textwrap", + "thiserror 1.0.69", "unicode-width 0.1.14", ] [[package]] name = "miette-derive" -version = "7.6.0" +version = "7.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -1658,7 +1209,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", - "simd-adler32", ] [[package]] @@ -1674,31 +1224,27 @@ dependencies = [ [[package]] name = "neli" -version = "0.7.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f9786d56d972959e1408b6a93be6af13b9c1392036c5c1fafa08a1b0c6ee87" +checksum = "93062a0dce6da2517ea35f301dfc88184ce18d3601ec786a727a87bf535deca9" dependencies = [ - "bitflags", "byteorder", - "derive_builder", - "getset", "libc", "log", "neli-proc-macros", - "parking_lot", ] [[package]] name = "neli-proc-macros" -version = "0.2.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d8d08c6e98f20a62417478ebf7be8e1425ec9acecc6f63e22da633f6b71609" +checksum = "0c8034b7fbb6f9455b2a96c19e6edf8dc9fc34c70449938d8ee3b4df363f61fe" dependencies = [ "either", "proc-macro2", "quote", "serde", - "syn", + "syn 1.0.109", ] [[package]] @@ -1712,18 +1258,28 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.3" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "windows-sys 0.61.2", + "overload", + "winapi", ] [[package]] name = "num-conv" -version = "0.2.0" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] [[package]] name = "numtoa" @@ -1748,64 +1304,32 @@ checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "opener" -version = "0.8.4" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2fa337e0cf13357c13ef1dc108df1333eb192f75fc170bea03fcf1fd404c2ee" +checksum = "d0812e5e4df08da354c851a3376fead46db31c2214f849d3de356d774d057681" dependencies = [ "bstr", + "dbus", "normpath", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] -name = "openssl-probe" -version = "0.2.1" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owo-colors" -version = "4.3.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" +checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" dependencies = [ "supports-color 2.1.0", "supports-color 3.0.2", ] -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -1814,24 +1338,16 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petname" -version = "3.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce610bff48dd7b6a127e45631795fbb0b302b99a39bef7e6da3d297e8eb2b6b" +checksum = "9cd31dcfdbbd7431a807ef4df6edd6473228e94d5c805e8cf671227a21bad068" dependencies = [ + "anyhow", "clap", - "petname-macros", - "rand 0.10.1", -] - -[[package]] -name = "petname-macros" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324239bd00dcf61f1a0e301d4d8f6f8c080a755248fc3fdc817ee1fdbbc27b8b" -dependencies = [ + "itertools", "proc-macro2", "quote", - "syn", + "rand", ] [[package]] @@ -1852,24 +1368,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppmd-rust" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24" - [[package]] name = "ppv-lite86" version = "0.2.20" @@ -1879,38 +1383,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "proc-macro2" version = "1.0.94" @@ -1920,62 +1392,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror 2.0.12", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" -dependencies = [ - "aws-lc-rs", - "bytes", - "getrandom 0.3.4", - "lru-slab", - "rand 0.9.2", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.12", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.60.2", -] - [[package]] name = "quote" version = "1.0.39" @@ -1985,76 +1401,34 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - [[package]] name = "rand" -version = "0.9.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", "rand_chacha", - "rand_core 0.9.5", -] - -[[package]] -name = "rand" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" -dependencies = [ - "chacha20", - "getrandom 0.4.1", - "rand_core 0.10.1", + "rand_core", ] [[package]] name = "rand_chacha" -version = "0.9.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.9.5", + "rand_core", ] [[package]] name = "rand_core" -version = "0.9.5" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.3.4", -] - -[[package]] -name = "rand_core" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" - -[[package]] -name = "rayon" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", + "getrandom", ] [[package]] @@ -2066,13 +1440,19 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_termios" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" + [[package]] name = "redox_users" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom", "libredox", "thiserror 1.0.69", ] @@ -2085,51 +1465,38 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" [[package]] name = "reqwest" -version = "0.13.2" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64", "bytes", "futures-core", + "futures-util", "http", "http-body", "http-body-util", "hyper", - "hyper-rustls", "hyper-util", + "ipnet", "js-sys", "log", + "mime", + "once_cell", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls", "tower", - "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "untrusted", - "windows-sys 0.52.0", + "windows-registry", ] [[package]] @@ -2138,12 +1505,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustix" version = "0.38.44" @@ -2157,81 +1518,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustls" -version = "0.23.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" -dependencies = [ - "aws-lc-rs", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pki-types" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-platform-verifier" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" - -[[package]] -name = "rustls-webpki" -version = "0.103.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustversion" version = "1.0.20" @@ -2244,100 +1530,36 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "3.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" - [[package]] name = "serde" -version = "1.0.228" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", + "ryu", "serde", - "serde_core", - "zmij", ] [[package]] @@ -2358,16 +1580,16 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] name = "serde_spanned" -version = "1.0.4" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ - "serde_core", + "serde", ] [[package]] @@ -2383,36 +1605,20 @@ dependencies = [ ] [[package]] -name = "sha1" -version = "0.10.6" +name = "serde_with" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.11.0-rc.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f3b1e2dc8aad28310d8410bd4d7e180eca65fca176c52ab00d364475d0024" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.11.1", + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.7.1", + "serde", + "serde_derive", + "serde_json", + "time", ] [[package]] @@ -2426,9 +1632,9 @@ dependencies = [ [[package]] name = "shell-words" -version = "1.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" @@ -2445,12 +1651,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - [[package]] name = "slab" version = "0.4.9" @@ -2468,12 +1668,12 @@ checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "socket2" -version = "0.6.2" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -2490,31 +1690,25 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.28.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.28.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "supports-color" version = "2.1.0" @@ -2548,9 +1742,20 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" [[package]] name = "syn" -version = "2.0.117" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" dependencies = [ "proc-macro2", "quote", @@ -2574,7 +1779,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -2600,12 +1805,14 @@ dependencies = [ [[package]] name = "termion" -version = "4.0.6" +version = "4.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44138a9ae08f0f502f24104d82517ef4da7330c35acd638f1f29d3cd5475ecb" +checksum = "6f359c854fbecc1ea65bc3683f1dcb2dce78b174a1ca7fda37acd1fff81df6ff" dependencies = [ "libc", + "libredox", "numtoa", + "redox_termios", ] [[package]] @@ -2644,7 +1851,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -2655,7 +1862,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -2670,23 +1877,34 @@ dependencies = [ [[package]] name = "time" -version = "0.3.47" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", - "js-sys", + "itoa", "num-conv", "powerfmt", - "serde_core", + "serde", "time-core", + "time-macros", ] [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] [[package]] name = "tinystr" @@ -2698,27 +1916,13 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinyvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.49.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ + "backtrace", "bytes", "libc", "mio", @@ -2726,39 +1930,18 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", + "syn 2.0.99", ] [[package]] @@ -2776,43 +1959,38 @@ dependencies = [ [[package]] name = "toml" -version = "1.0.3+spec-1.1.0" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7614eaf19ad818347db24addfa201729cf2a9b6fdfd9eb0ab870fcacc606c0c" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ - "indexmap", - "serde_core", + "serde", "serde_spanned", "toml_datetime", - "toml_parser", - "toml_writer", - "winnow", + "toml_edit", ] [[package]] name = "toml_datetime" -version = "1.0.0+spec-1.1.0" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ - "serde_core", + "serde", ] [[package]] -name = "toml_parser" -version = "1.0.9+spec-1.1.0" +name = "toml_edit" +version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ + "indexmap 2.7.1", + "serde", + "serde_spanned", + "toml_datetime", "winnow", ] -[[package]] -name = "toml_writer" -version = "1.0.6+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" - [[package]] name = "tower" version = "0.5.2" @@ -2829,24 +2007,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower-http" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" -dependencies = [ - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - [[package]] name = "tower-layer" version = "0.3.3" @@ -2861,9 +2021,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.44" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -2873,20 +2033,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.31" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] name = "tracing-core" -version = "0.1.36" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -2905,9 +2065,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "nu-ansi-term", "sharded-slab", @@ -2923,18 +2083,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "typed-path" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" - -[[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - [[package]] name = "unicode-ident" version = "1.0.18" @@ -2959,24 +2107,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "unit-prefix" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" version = "2.5.4" @@ -3018,22 +2148,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "want" version = "0.3.1" @@ -3049,24 +2163,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasip2" -version = "1.0.2+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -3089,7 +2185,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.99", "wasm-bindgen-shared", ] @@ -3124,7 +2220,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3138,40 +2234,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags", - "hashbrown 0.15.2", - "indexmap", - "semver", -] - [[package]] name = "web-sys" version = "0.3.77" @@ -3182,25 +2244,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-root-certs" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "winapi" version = "0.3.9" @@ -3217,15 +2260,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3233,18 +2267,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-link" -version = "0.2.1" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] [[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows-link" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-targets 0.42.2", + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", ] [[package]] @@ -3253,7 +2317,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -3262,40 +2326,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] @@ -3304,263 +2335,71 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "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", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[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_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" - -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", + "memchr", ] [[package]] @@ -3606,7 +2445,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", "synstructure", ] @@ -3628,7 +2467,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", ] [[package]] @@ -3648,30 +2487,10 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.99", "synstructure", ] -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zerovec" version = "0.10.4" @@ -3691,84 +2510,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "zip" -version = "8.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e499faf5c6b97a0d086f4a8733de6d47aee2252b8127962439d8d4311a73f72" -dependencies = [ - "aes", - "bzip2", - "constant_time_eq", - "crc32fast", - "deflate64", - "flate2", - "getrandom 0.4.1", - "hmac", - "indexmap", - "lzma-rust2", - "memchr", - "pbkdf2", - "ppmd-rust", - "sha1", - "time", - "typed-path", - "zeroize", - "zopfli", - "zstd", -] - -[[package]] -name = "zlib-rs" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c745c48e1007337ed136dc99df34128b9faa6ed542d80a1c673cf55a6d7236c8" - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - -[[package]] -name = "zopfli" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" -dependencies = [ - "bumpalo", - "crc32fast", - "log", - "simd-adler32", -] - -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" -dependencies = [ - "cc", - "pkg-config", + "syn 2.0.99", ] diff --git a/Cargo.toml b/Cargo.toml index 631f10f..9ac03ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "haze" -version = "2.3.0" +version = "2.1.5" authors = ["Robin Appelman "] edition = "2021" repository = "https://codeberg.org/icewind/haze" @@ -8,44 +8,38 @@ license = "MIT" description = "Easy setup and management of Nextcloud test instances using docker" [dependencies] -bollard = "0.21.0" +bollard = "0.18.1" maplit = "1.0.2" -camino = { version = "1.2.2", features = ["serde1"] } -tokio = { version = "1.49.0", features = ["fs", "macros", "signal", "rt-multi-thread"] } -tokio-stream = { version = "0.1.18", features = ["net"] } -futures-util = "0.3.32" -termion = "4.0.6" -opener = "0.8.4" -toml = "1.0.3" +camino = { version = "1.1.7", features = ["serde1"] } +tokio = { version = "1.38.0", features = ["fs", "macros", "signal", "rt-multi-thread"] } +futures-util = "0.3.30" +termion = "4.0.1" +opener = "0.7.1" +toml = "0.8.14" directories-next = "2.0.0" -serde = "1.0.228" -serde_json = "1.0.149" -petname = "3.0.0" -reqwest = { version = "0.13.2", default-features = false, features = ["rustls"] } -tar = "0.4.44" -flate2 = "1.1.9" -async-trait = "0.1.89" +serde = "1.0.203" +serde_json = "1.0.117" +petname = "2.0.2" +reqwest = { version = "0.12.4", default-features = false } +tar = "0.4.41" +flate2 = "1.0.30" +async-trait = "0.1.80" enum_dispatch = "0.3.13" -miette = { version = "7.6.0", features = ["fancy"] } -shell-words = "1.1.1" -tracing = "0.1.44" -tracing-subscriber = "0.3.22" +miette = { version = "7.2.0", features = ["fancy"] } +shell-words = "1.1.0" +tracing = "0.1.40" +tracing-subscriber = "0.3.18" atty = "0.2.14" -git2 = { version = "0.21.0", default-features = false } +git2 = { version = "0.20.0", default-features = false } itertools = { version = "0.14.0", features = ["use_alloc"] } -local-ip-address = "0.6.10" -strum = { version = "0.28.0", features = ["derive"] } -owo-colors = { version = "4.3.0", features = ["supports-colors"] } -zip = "8.1.0" -sha2 = "0.11.0-rc.5" -base16ct = { version = "1.0.0", features = ["alloc"] } -indicatif = "0.18.4" -rayon = "1.12.0" +local-ip-address = "0.6.5" +strum = { version = "0.27.2", features = ["derive"] } +owo-colors = { version = "4.2.2", features = ["supports-colors"] } -hyper-reverse-proxy = { version = "0.5.2-dev", git = "https://code.betamike.com/micropelago/hyper-reverse-proxy.git", rev = "d5a6f799189360d9449ae47ab3cdde511f02cf39" } -hyper = "1.8.1" -hyper-util = "0.1.20" -axum = { version = "0.8.8", features = ["tokio", "macros"] } +hyper-reverse-proxy = { version = "0.5.2-dev", git = "https://github.com/chpio/hyper-reverse-proxy", rev = "6934877eb74465204f605cc1c05ca5a9772db7c0" } +hyper = "1.6.0" +hyper-util = "0.1.10" +axum = { version = "0.8.1", features = ["tokio"] } [profile.release] lto = true diff --git a/README.md b/README.md index aa538d2..2a12c61 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Easy setup and management of Nextcloud test instances using docker ## What -`haze` provides an easy way to set up Nextcloud test instances with a choice of +`haze` provides an easy way to setup Nextcloud test instances with a choice of php version, database server, optional s3 or ldap setup and more. ## Setup @@ -56,52 +56,47 @@ See the [configuration section](#configuration) for more options. #### Start an instance ```bash -haze start [database] [php-version] [services] [vX.Y.Z] +haze start [database] [php-version] [services] ``` Where `database` is one of `sqlite`, `mysql`, `mariadb`, `pgsql` or `oracle` with an optional version (e.g. `pgsql:12`), defaults to `sqlite`. And -`php-version` is one of `8.0`, `8.1`, `8.2`, `8.3`, `8.4` or `8.5`, defaults to -the maximum version support by the current Nextcloud version. +`php-version` is one of `8.2`, `8.3` or `8.4`, defaults to the maximum version +support by the current Nextcloud version. `7.3` till `8.1` are still supported +but the docker images for those versions aren't being updated anymore so they +might be missing some newer features. -You can specify a version number (e.g. `v32.0.2`) to use the sources from a -release instead of using the local sources. +Each php version also comes with a `-dbg` variant that has php compiled in debug +mode and can be used for debugging php itself with gdb. Additionally, you can use the following options when starting an instance: -- `s3`: set up an S3 server and configure to Nextcloud to use it as primary +- `s3`: setup an S3 server and configure to Nextcloud to use it as primary storage. - - `s3s`: enable TLS for the S3 setup. - - `s3mb`: enable multi-bucket S3 setup. - - `s3m`: enable multi-instance S3 setup. -- `ldap`: set up an LDAP server. -- `office`: set up a Nextcloud Office server. -- `onlyoffice` setup an onlyoffice document server. -- `push` set up [client push](https://github.com/nextcloud/notify_push). -- `smb`: set up a samba server for external storage use. -- `dav`: set up a WebDAV server for external storage use. -- `sftp`: set up a SFTP server for external storage use. -- `sftp-key`: set up a SFTP server for external storage use with public key - authentication. -- `kaspersky`: set up a kaspersky scan engine server in http mode. ( Requires - [manually setting up the image](https://github.com/icewind1991/kaspersky-docker)) -- `kaspersky-icap`: setup a kaspersky scan engine server in ICAP mode. -- `clamav`: set up a local clam av scanner in executable mode. -- `clamav-socket`: set up a clam av scanner in socket mode. -- `clamav-icap`: set up a clam av scanner in ICAP mode. -- `clamav-icap-tls`: set up a clam av scanner in ICAP mode with TLS encryption. -- `oc`: start an ownCloud instance in the same network. -- `imaginary`: start an Imaginary service and configure it for preview - generation. -- `mail`: start a [smtp4dev](https://github.com/rnwood/smtp4dev) server and - configure it the mail server. -- `webhook` start a - [webhook tester](https://github.com/tarampampam/webhook-tester) -- `redis`: start a separate container for redis. -- `redis-tls`: connect to redis over TLS. - ``: by specifying the path to an app package this package will be extracted into the apps. directory of the new instance (overwriting any existing app code). This can be used to quickly test a packaged app. +- `ldap`: setup an LDAP server. +- `office`: setup a Nextcloud Office server. +- `onlyoffice` setup an onlyoffice document server. +- `push` setup [client push](https://github.com/nextcloud/notify_push). +- `smb`: setup a samba server for external storage use. +- `dav`: setup a WebDAV server for external storage use. +- `sftp`: setup a SFTP server for external storage use. +- `kaspersky`: setup a kaspersky scan engine server in http mode. ( Requires + [manually setting up the image](https://github.com/icewind1991/kaspersky-docker)) +- `kaspersky-icap`: setup a kaspersky scan engine server in ICAP mode. +- `clamav`: setup a local clam av scanner in executable mode. +- `clamav-socket`: setup a clam av scanner in socket mode. +- `clamav-icap`: setup a clam av scanner in ICAP mode. +- `clamav-icap-tls`: setup a clam av scanner in ICAP mode with TLS encryption. +- `oc`: start an ownCloud instance in the same network. +- `imaginary`: start an Imaginary service and configure it for preview + generation. +- `mail`: start an [smtp4dev](https://github.com/rnwood/smtp4dev) server and + configure it the mail server. +- `redis`: start a separate container for redis. +- `redis-tls`: connect to redis over TLS. - The name of any configured preset. #### Run tests in a new instance @@ -110,7 +105,7 @@ Additionally, you can use the following options when starting an instance: haze test [database] [php-version] [path] ``` -Where `path` is a file or folder to run PHPUnit in, relative to the sources +Where `path` is a file or folder to run phpunit in, relative to the sources root. ### List running instances @@ -134,7 +129,7 @@ haze clean ## Controlling running instances The following commands run against the most recently started instance and allow -optionally providing a `match` to select a specific instance by its name. +optionally providing a `match` to select a specific instance by it's name. #### Open an instance @@ -151,14 +146,11 @@ haze [match] db #### Execute a command on an instance ```bash -haze [match] [service] [cmd] +haze [match] exec [cmd] ``` If no `cmd` is specified it will launch `bash` -If a service name or `db` is provided, the command will be in the container of -the service or database. - #### Create a new instance and run a command ```bash @@ -214,7 +206,7 @@ haze [match] env [args] Runs the provided command with `NEXTCLOUD_URL`, `DATABASE_URL` and `REDIS_URL` environment variables set for the matched instance. -This is intended to run a local +This is intented to run a local [push daemon](https://github.com/nextcloud/notify_push) against an instance. #### Update the container images @@ -235,7 +227,7 @@ haze [match] edit haze [match] reload ``` -The php configuration can edit changed with `haze edit /config/php.ini` +The php configuration can edit changed with `haze edit /php.ini` #### Checkout a branch for all local apps @@ -262,30 +254,29 @@ Performs a pull in all git repositories within the apps folder. Multiple instances can reach each other by using their instance name as domain name to allow for testing federation between instances. Alternatively, you can -set up the haze proxy and the proxied domains to get https support between +setup the haze proxy and the proxied domains to get https support between instances. ## Proxy By default, instances can be accessed by their IP. In order to get more -memorable URLs and allow supporting https, haze comes with a builtin reverse +memorable urls and allow supporting https, haze comes with a builtin reverse proxy to allow using a wildcard domain. ### Requirements - A domain name you can set wildcard DNS records for -- A reverse proxy like nginx or Apache +- A reverse proxy like nginx or apache - (optionally) a wildcard ssl certificate (can be acquiring using letsencrypt and dns verification) ### Setup - Set a DNS record for `*.haze.exmaple.com` and `haze.example.com` pointing to - your development machine. -- Set the `proxy` configuration with your domain and desired listen endpoint. -- Set up a service to run `haze proxy` in the background as your own user. A - systemd user service is recommended (see [haze.service](./haze.service) for an - example). + your development machine. (127.0.0.1 will not work) +- Set the `proxy` configuration with your domain and desired listen endpoint +- Setup a service to run `haze proxy` in the background as your own user. A + systemd user service is recommended. - Configure your reverse proxy of choice to proxy `*.haze.example.com` and `haze.example.com` to the proxy's listen endpoint - (optional) acquire a wildcard ssl certificate for your domain and set your @@ -295,17 +286,11 @@ proxy to allow using a wildcard domain. ### Usage -When the proxy is configured, generated URLs for the instances will use a +When the proxy is configured, generated urls for the instances will use a subdomain of the configured domain, e.g. the `rolling-bees` instance will be available at `rolling-bees.haze.example.com`. Additionally, `haze.example.com` will automatically point to the last created instance. -Additionally, the proxy allows access to the server containers trough either -`-.haze.example.com` for a specific instance, or -`.haze.example.com` for the last created instance. For example -`rolling-bees-mail.haze.example.com` will give access to the smtp4dev web -interface of the `rolling-bees` instance. - ## Configuration Configuration is loaded from `~/.config/haze/haze.toml` and has the following @@ -313,7 +298,6 @@ options ```toml sources_root = "/path/to/sources" # path of the nextcloud sources. required -app_directories = ["/path/to/sources/more_app"] # paths to additional app directories. work_dir = "/path/to/temp/dir" # path to temporary directory. optional, defaults to "/tmp/haze" [auto_setup] # optional @@ -325,7 +309,6 @@ disable_apps = ["contacts"] # apps to disable after setup, defaults to [] post_setup = [# commands to execute after setup, defaults to [] "occ group:add test", ] -config = { "foo" = "bar" } # configuration options to set before install [[volume]] # optional source = "/tmp/haze-shared" @@ -339,7 +322,7 @@ read_only = true [proxy] # optional address = "haze.example.com" # base domain -https = true # Is the proxy behind a https terminating proxy +https = true # Is the proxy behind an https terminating proxy listen = "/run/haze/haze.sock" # either a unix socket path #listen = "127.0.0.1:8080" # or a socket address diff --git a/certificates/s3/private.key b/certificates/s3/private.key deleted file mode 100644 index 939d93e..0000000 --- a/certificates/s3/private.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCQuTk+irdXRGbY -JUu+AFmMM4/CCtBIBBgGIG18tesgQUeHEPdRHbBypvFKhpXvlKQbVbiaZxFjtlvn -L2ReN7gYwjiTjLWuaDgOzGQyObwSJpedlcd5Q957WNlc5OjpoK8zZq9EGnmvjIqe -5VVBne85RZVw6+i4ljEiWoXCiy0iOPIL4jKO8kfO8EmTTh6ge2sLCT5jFT/V63/B -hjEobA7+vPbAmEo+Qs4adnBSrlX9nLtL1j4gqawAQMmGl/Ti75T0uQvNxdq2gddc -n0wyWhyERnZNeMv5sfkwCOTuetNNtGLf/lTkXNdaOCRvW5jJ0EjYYdpQG5R0do1U -XFLH1cZZAgMBAAECggEAR0xpTk2Ku5yASlY9dXK4qyCv3znymLgjmckaB4mcN7zR -X1JVdYn55tImJ8AcV/bTzn+xvaevYn9x0XiAqwYqVVBCDTcSPsUrcObzKedVp1+J -7GHg7vYnwn7oPyKrOIYoKluZVyTv9DN6C4QSN4x2UbHdSM+ATIf51uHf6hMk/ilv -4uw3csxSCpLOqqsYCQarES7SypcETjFpNnIfTPt7q2Y2DbIDttTTjzrm0/GBP0WE -OYNvzZZPZRPJfy3et3r9vJbqWzGHvOttzQ+EFHjwPTMfW4tsHcCsEKSGWwLpG4bN -FPNx0+QCqDiChesdiCHFNSk+u7pRZrHdjuDJEuKSzQKBgQDMDgdCGBQfgaNnkRz/ -aiv3V200/vXegnc0Jz49Dye5AxEVu0X1m2xZpJv+qEwbOx5B+1PV3gfVP/iRf+FK -MAwFbmb7hGcDE8AGNsSpQydjwzKoi/M67YXv7T8dgWKnwz0eyU4K2IOGInGxuFty -Ik7+DTqz+Ikh1RiAoGbKfw9yhwKBgQC1kKhjxB7r/uSLcfOSg1mLcR5lTrNDQAPQ -GnsIje0nD5Tv52/k6U4tk15vjL4t6KZUFo9SJ4O1kM1veyuOJuol2AfPXS+H/Izo -5BjmoZ0jOONOZZiRIB1moQSy1qhTAeZB9S1ORxQ3dIBPqm+oyADPTTsNV67Cwnt4 -woeZRUPYHwKBgQDE0AcKJcVK+jQMUXfBlrsfTvDjO8MTwYyN/gfWxsZOeXnCFyYM -FcO01sMrJVJ6tVOi2nFrB0NQ2Om8FLbMYnlFx82GbJca7bK5i5u1kjLs0zoKPSn1 -vWEBIDhPEhuAqhxKlGk0ps580r4MZz+0XwkHmuTy7xX9TtbaQVvDljflAwKBgDKy -3hJdpTTIzBCUFSuIOezR/WbUfwH8UhQ+ELTmzJ3nn/MNcRU+gHIBgJEtf71aBXfd -hM+v8Ps2H+dNQXBENYWzuRqSLr+OKdquNrXP0w0OyYoOnHeJvCv4MlOt1Pq4wQ8R -40DEYETL5zhXoy5CCtfX/PFQ1p/Tpp6l0y9dRACJAoGALwUbyyDy85b2xRQB6RtU -I+5Vz5cd/1eQdCkoU9mX4qWA/hWpgc7Z2Jd67LW/WWtVjlF9hva/WNDSfGsXo2ew -C8OofvlfIuFDOCXrodYdHE1Q4g5TZdESr0XAqopq+QzBs89qbIy05kM9iuE4yFUo -xeimCY9oDWTeGw/XrLdHZF4= ------END PRIVATE KEY----- diff --git a/certificates/s3/public.crt b/certificates/s3/public.crt deleted file mode 100644 index f31f379..0000000 --- a/certificates/s3/public.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDXTCCAkWgAwIBAgIULiChaTwmVx6nRTHohmPuf55/4jUwDQYJKoZIhvcNAQEL -BQAwPjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDTALBgNVBAoM -BEhhemUxCzAJBgNVBAMMAnMzMB4XDTI2MDMwOTE3NTgwOVoXDTI3MDMwOTE3NTgw -OVowPjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxDTALBgNVBAoM -BEhhemUxCzAJBgNVBAMMAnMzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAkLk5Poq3V0Rm2CVLvgBZjDOPwgrQSAQYBiBtfLXrIEFHhxD3UR2wcqbxSoaV -75SkG1W4mmcRY7Zb5y9kXje4GMI4k4y1rmg4DsxkMjm8EiaXnZXHeUPee1jZXOTo -6aCvM2avRBp5r4yKnuVVQZ3vOUWVcOvouJYxIlqFwostIjjyC+IyjvJHzvBJk04e -oHtrCwk+YxU/1et/wYYxKGwO/rz2wJhKPkLOGnZwUq5V/Zy7S9Y+IKmsAEDJhpf0 -4u+U9LkLzcXatoHXXJ9MMlochEZ2TXjL+bH5MAjk7nrTTbRi3/5U5FzXWjgkb1uY -ydBI2GHaUBuUdHaNVFxSx9XGWQIDAQABo1MwUTAdBgNVHQ4EFgQUJJ8HiT2zmuF5 -6WHHFsTHgkrayxYwHwYDVR0jBBgwFoAUJJ8HiT2zmuF56WHHFsTHgkrayxYwDwYD -VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAUF0lB/qIrxkgZ4sqNrw4 -CInHCK29XVaMoqk1QZyS/KhWDM+zgbA92OxxuhCKw4iJEajZvgg0S9RtGkBNmquU -l0rf0JdALd0jPkWr7+3OeqlcgOs2EH7PTqrrbXTGsR12D+Ot+OerQeWXmO28Zrl8 -4O67TwQtslXwZzeCrtiwAA2DrIYpSLzh+qDtwbY5hMG5zmqqjBM20Ysgxszh4rhl -KR6skXwZwkVVhKpK76qwnU02PIMr8auL1csx8/uBTd/UzX2veqlkOP5V/Gg6eEbI -4fTOzq7k+FyuzSkrEX4Vc9GbWcRvoVZh+qAKUKstqlE2iCrqmZ+Wal6GA8JA5SZ+ -bQ== ------END CERTIFICATE----- diff --git a/certificates/sftp/id_rsa b/certificates/sftp/id_rsa deleted file mode 100644 index c8dcc4d..0000000 --- a/certificates/sftp/id_rsa +++ /dev/null @@ -1,38 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn -NhAAAAAwEAAQAAAYEA323aWqH6YwRLbCBO94UKOkfnJ2m6Zsic0dMt3TmDnjLU0JzpOt7w -t5+mMZrEKQTpefozyUHo3z+HkmllLAGOupNy3A+jG2O955UUgw0dGfu6j6OOb66Du9jpqt -8BQ6gr3cEYASplPI7B889/cVpJ5l1HiBUgyR7Z16v15qCDtmpFVIECAdICEmPosfmZutt3 -YYl9xLay5WCmUztWS/amPcGs0DOEGrWeCtdxGKWT3TywdBKyQ0PbdYMamgDIT7JV1ZSzZP -aly4sB7E+dpS5AgBFVXmZ61151KN1TJ8gyoUjFhY7ctYEIpncZmyT4PYvyIvxRsbJtvERi -eNH8DoX5DwtqcxbgHK0OwYtdl4ydRXToYo3l+qIidf+g8ADVea/mbkfTPegdToo3LOuThX -OwExDlukpM8obFDpz1Yl1L6rRJAVNO1KmHWhn6to23jtYjBhczA2nkemQXQbVSjc/hItjQ -DIFNMOsLW33P+Y2k9LkpI0TL09ogOxOFZzGZp2tNAAAFgIgMIZ+IDCGfAAAAB3NzaC1yc2 -EAAAGBAN9t2lqh+mMES2wgTveFCjpH5ydpumbInNHTLd05g54y1NCc6Tre8LefpjGaxCkE -6Xn6M8lB6N8/h5JpZSwBjrqTctwPoxtjveeVFIMNHRn7uo+jjm+ug7vY6arfAUOoK93BGA -EqZTyOwfPPf3FaSeZdR4gVIMke2der9eagg7ZqRVSBAgHSAhJj6LH5mbrbd2GJfcS2suVg -plM7Vkv2pj3BrNAzhBq1ngrXcRilk908sHQSskND23WDGpoAyE+yVdWUs2T2pcuLAexPna -UuQIARVV5metdedSjdUyfIMqFIxYWO3LWBCKZ3GZsk+D2L8iL8UbGybbxEYnjR/A6F+Q8L -anMW4BytDsGLXZeMnUV06GKN5fqiInX/oPAA1Xmv5m5H0z3oHU6KNyzrk4VzsBMQ5bpKTP -KGxQ6c9WJdS+q0SQFTTtSph1oZ+raNt47WIwYXMwNp5HpkF0G1Uo3P4SLY0AyBTTDrC1t9 -z/mNpPS5KSNEy9PaIDsThWcxmadrTQAAAAMBAAEAAAGAWCkM/TEnztU9e3M+JX253OhNRe -h6lB75ffOxh7avgAc3oP8hKkkYu6PDnJQgbb0R8T7wGywmGp0DPhrXQGd27ZjLvBhxeBfB -sbTJ7LIKdxu0cAQN6nR2Z3M+NF2dLpiXgn80HRWg76W20yDffRcuzLamyIPptWI2e9rPAw -r4HczOAXuMErLOfXotsbg22BvL/dEWLr4WVdruli32LbArxXd73IVPTYi3TTjYV+zRrPzK -9WoBK/iFClfKcdT4NTY82llQesuUNu640lEJtT2G3Iba8UZnohyzm/S+UbeU65z8DKD5co -P7+QehxQSV+kj2BZnTi0WEwsD+GTznJYR5rvUsJCCAzoISsWrncSSgOQhF2XeW/T4ewvH+ -njLZViEhdG8R3kkdDjJG91OrSgrEqlk6Qhz1xEsv1rCOR69En7EJP3TNNrymPXPASrAnuE -HQkrVgGUfGqyD1sw1e6nBfNWisuw+g99CieIB8EI9WwpxQdKqWNU9Hjx+SAdC3NrPjAAAA -wQCo0hUGjSf6xhcgeaNa0gWSKEVuFhxR/FaCPTKadV7Md0APW4toeQZDujzDFlCZbQTZjC -0723B4lKugDzXfsOgvOTKp4vEjZOu0YGruS00LFWM7Sutdzx68b/ZMFALzITt/myKVMdpv -WpaO+3+PyEYIQH44QrSWw7cKLzNiZ8kt2drPkPktub4o2h5TdIBluEQLJDPMejy8IqQEU8 -aOyJOMvYxAbGAWY7Ck9DGlcJgaFdORROW8d8ZGrHQkyRl41JQAAADBAPeUMsrbI17wPP/s -Tsrkms5ws5yTz0xle2Wn6HwDSzQRSdn5abnIDYb3QSy0nRBvczef6ssH65dl50+2V4BV2L -MwHcmKD6/UoFsWwP/RMf1EoacPFiEAWJGxFbOthNX+rx5BpbUHNoQd8xby+88saDI0e8W6 -36HPBZrAZhQljkMa4OJqZDDCpOJvSndXwkZ789E96uprKopJZGwlLmfMtikQpNXT9R+I0b -SQCJj4yNakcdOE/7UifkOR02u+pgux3wAAAMEA5wdelKwGQ0EdkIF2TM844uLPszo3ZSH+ -Heff/Lbxs1Y+oL0NTJQicwMF0d9WEwBoTZJpuzsQEA1zkfmW0gi2womIRmiY0ZhpxbBuhO -6XePMIhUfQmWWjaUbAkrNB0eJkSTuUGzwxVkMXehrMuj4gYe8GMC8GgULbP0A8FjH01fKk -jFwgg4WAg6zUTpck12bh49NZRFyXIbXNk/jjxJtb0p//5TRTUQ6mR5IloaNTM23EiF6tle -Y6CAchnyhHO0BTAAAACWhhemVAaGF6ZQE= ------END OPENSSH PRIVATE KEY----- diff --git a/certificates/sftp/id_rsa.pub b/certificates/sftp/id_rsa.pub deleted file mode 100644 index 81a5db6..0000000 --- a/certificates/sftp/id_rsa.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfbdpaofpjBEtsIE73hQo6R+cnabpmyJzR0y3dOYOeMtTQnOk63vC3n6YxmsQpBOl5+jPJQejfP4eSaWUsAY66k3LcD6MbY73nlRSDDR0Z+7qPo45vroO72Omq3wFDqCvdwRgBKmU8jsHzz39xWknmXUeIFSDJHtnXq/XmoIO2akVUgQIB0gISY+ix+Zm623dhiX3EtrLlYKZTO1ZL9qY9wazQM4QatZ4K13EYpZPdPLB0ErJDQ9t1gxqaAMhPslXVlLNk9qXLiwHsT52lLkCAEVVeZnrXXnUo3VMnyDKhSMWFjty1gQimdxmbJPg9i/Ii/FGxsm28RGJ40fwOhfkPC2pzFuAcrQ7Bi12XjJ1FdOhijeX6oiJ1/6DwANV5r+ZuR9M96B1Oijcs65OFc7ATEOW6SkzyhsUOnPViXUvqtEkBU07UqYdaGfq2jbeO1iMGFzMDaeR6ZBdBtVKNz+Ei2NAMgU0w6wtbfc/5jaT0uSkjRMvT2iA7E4VnMZmna00= haze@haze diff --git a/flake.lock b/flake.lock index a7766b8..81e86a7 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "crane": { "locked": { - "lastModified": 1763938834, - "narHash": "sha256-j8iB0Yr4zAvQLueCZ5abxfk6fnG/SJ5JnGUziETjwfg=", + "lastModified": 1760924934, + "narHash": "sha256-tuuqY5aU7cUkR71sO2TraVKK2boYrdW3gCSXUkF4i44=", "owner": "ipetkov", "repo": "crane", - "rev": "d9e753122e51cee64eb8d2dddfe11148f339f5a2", + "rev": "c6b4d5308293d0d04fcfeee92705017537cad02f", "type": "github" }, "original": { @@ -15,22 +15,6 @@ "type": "github" } }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1767039857, - "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", - "owner": "NixOS", - "repo": "flake-compat", - "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "flake-compat", - "type": "github" - } - }, "flakelight": { "inputs": { "nixpkgs": [ @@ -38,11 +22,11 @@ ] }, "locked": { - "lastModified": 1773062095, - "narHash": "sha256-u+cK9IoJokO4YzQwMc2s8Vti0RL/LVSrROOEn2opc5U=", + "lastModified": 1764593611, + "narHash": "sha256-6SdexcO69Dlu14YN2xuB1A6JHWSrcqMj7Na9oK7IT2M=", "owner": "nix-community", "repo": "flakelight", - "rev": "c99e4d5f40e578cb2d8f460ea2bbd5dc26316d24", + "rev": "0d63256401341f528dd628f1a8e96d3afecade7a", "type": "github" }, "original": { @@ -60,11 +44,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1772297202, - "narHash": "sha256-UEzHO/tCmhPhr8RpWtbm1MTa7ABobwt3nCjrcuDAPm0=", + "lastModified": 1763591898, + "narHash": "sha256-aHSMj7CIa9EJYxdf05wOWRGp0KRsT/TAox7uwVSdDb8=", "ref": "refs/heads/main", - "rev": "8690e1514863b934de12f2a503c9431d186ce30b", - "revCount": 68, + "rev": "2d9b2da2c9f384f93ef977c48f8ee35ce586529b", + "revCount": 66, "type": "git", "url": "https://codeberg.org/icewind/mill-scale.git" }, @@ -75,11 +59,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1772822230, - "narHash": "sha256-yf3iYLGbGVlIthlQIk5/4/EQDZNNEmuqKZkQssMljuw=", + "lastModified": 1764522689, + "narHash": "sha256-SqUuBFjhl/kpDiVaKLQBoD8TLD+/cTUzzgVFoaHrkqY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "71caefce12ba78d84fe618cf61644dce01cf3a96", + "rev": "8bb5646e0bed5dbd3ab08c7a7cc15b75ab4e1d0f", "type": "github" }, "original": { @@ -88,48 +72,11 @@ "type": "indirect" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 1772173633, - "narHash": "sha256-MOH58F4AIbCkh6qlQcwMycyk5SWvsqnS/TCfnqDlpj4=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c0f3d81a7ddbc2b1332be0d8481a672b4f6004d6", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "phps": { - "inputs": { - "flake-compat": "flake-compat", - "nixpkgs": "nixpkgs_2", - "utils": "utils" - }, - "locked": { - "lastModified": 1772365008, - "narHash": "sha256-/ynkWKeZ1dyRIUkQas0AB35semWAwCbTKXu+/q+8MGg=", - "owner": "fossar", - "repo": "nix-phps", - "rev": "f47eb877bf1c219809e4357eec2fdab8e3263b7b", - "type": "github" - }, - "original": { - "owner": "fossar", - "repo": "nix-phps", - "type": "github" - } - }, "root": { "inputs": { "flakelight": "flakelight", "mill-scale": "mill-scale", - "nixpkgs": "nixpkgs", - "phps": "phps" + "nixpkgs": "nixpkgs" } }, "rust-overlay": { @@ -141,11 +88,11 @@ ] }, "locked": { - "lastModified": 1764557621, - "narHash": "sha256-kX5PoY8hQZ80+amMQgOO9t8Tc1JZ70gYRnzaVD4AA+o=", + "lastModified": 1761964689, + "narHash": "sha256-Zo3LQQDz+64EQ9zor/WmeNTFLoZkjmhp0UY3G0D3seE=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "93316876c2229460a5d6f5f052766cc4cef538ce", + "rev": "63d22578600f70d293aede6bc737efef60ebd97f", "type": "github" }, "original": { @@ -153,39 +100,6 @@ "repo": "rust-overlay", "type": "github" } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 9934eb7..641c5fc 100644 --- a/flake.nix +++ b/flake.nix @@ -9,15 +9,8 @@ url = "git+https://codeberg.org/icewind/mill-scale.git"; inputs.flakelight.follows = "flakelight"; }; - phps = { - url = "github:fossar/nix-phps"; - }; }; - outputs = { - mill-scale, - phps, - ... - }: + outputs = {mill-scale, ...}: mill-scale ./. { crossTargets = [ "x86_64-unknown-linux-gnu" @@ -31,23 +24,17 @@ }; extraPaths = [ - ./certificates + ./redis-certificates ]; withOverlays = [ (import ./nix/overlay.nix) - (prev: final: { - inherit (phps.packages.${prev.system}) php81 php80; - }) ]; packages = { - "haze-image-php-8.5" = pkgs: pkgs.haze-image-php-85; "haze-image-php-8.4" = pkgs: pkgs.haze-image-php-84; "haze-image-php-8.3" = pkgs: pkgs.haze-image-php-83; "haze-image-php-8.2" = pkgs: pkgs.haze-image-php-82; - "haze-image-php-8.1" = pkgs: pkgs.haze-image-php-81; - "haze-image-php-8.0" = pkgs: pkgs.haze-image-php-80; }; tools = pkgs: with pkgs; [cargo-edit bacon skopeo]; diff --git a/haze.service b/haze.service deleted file mode 100644 index 4b0ff66..0000000 --- a/haze.service +++ /dev/null @@ -1,10 +0,0 @@ -[Install] -WantedBy=default.target - -[Service] -ExecStart=/usr/bin/haze proxy -Restart=on-failure -RestartSec=10 - -[Unit] -Description=Haze reverse proxy \ No newline at end of file diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 7fe684d..096d853 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -9,10 +9,9 @@ with lib; let format = pkgs.formats.toml {}; configFile = format.generate "haze.toml" ({ sources_root = cfg.sourcesRoot; - app_directories = cfg.appDirectories; work_dir = cfg.workDir; auto_setup = { - inherit (cfg.autoSetup) enable config; + enabled = cfg.autoSetup.enable; post_setup = cfg.autoSetup.postSetup; enable_apps = cfg.autoSetup.enableApps; disable_apps = cfg.autoSetup.disableApps; @@ -62,12 +61,6 @@ in { description = "Directory to store instance data"; }; - appDirectories = mkOption { - type = types.listOf types.str; - default = []; - description = "Paths to additional app directories"; - }; - autoSetup = mkOption { type = types.submodule { options = { @@ -91,13 +84,6 @@ in { default = []; description = "Commands to run post-setup"; }; - config = mkOption { - type = types.submodule { - freeformType = format.type; - }; - description = "Configuration options to set before install"; - default = {}; - }; }; }; }; diff --git a/nix/image/bootstrap b/nix/image/bootstrap deleted file mode 100755 index 2c9dcff..0000000 --- a/nix/image/bootstrap +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/nu - -touch /var/log/nginx/access.log -touch /var/log/nginx/error.log -touch /var/log/cron/owncloud.log - -mkdir /config -echo "# Options in here overwrite the builtin php.ini\n" | save /config/php.ini -echo "# xdebug.mode = debug\n" | save -a /config/php.ini -echo "# xdebug.start_with_request = yes\n\n" | save -a /config/php.ini -chmod 0777 /config/php.ini -let PHP_INI_DIR = php --ini | grep 'Scan' | cut -d ' ' -f7 | tr -d '"' -ln -s /config/php.ini $"($PHP_INI_DIR)/zz_extra.ini" - -let HAZE_UID = $env.HAZE_UID | default "1000" -let HAZE_GID = $env.HAZE_GID | default "1000" - -nc-auto-config -shadow-setup - -echo $"Running as ($HAZE_UID):($HAZE_GID)" - -mkdir /var/www/html/core/skeleton /var/www/html/build/integration/vendor /var/www/html/build/integration/output /var/www/html/build/integration/work /var/www/html/core/skeleton /var/www/.composer/cache /var/www/html/apps/spreed/tests/integration/vendor/composer -chown -R $"($HAZE_UID):($HAZE_GID)" /var/www/html/data /var/www/html/config -chown $"($HAZE_UID):($HAZE_GID)" /var/www/html/core/skeleton /var/www/html/build/integration/vendor /var/www/html/build/integration/composer.lock /var/www/html/build/integration/output /var/www/html/build/integration/work /var/www/html/core/skeleton /var/www/.composer/cache /var/www/html/apps/spreed/tests/integration/vendor/composer - -echo "{}\n" | save -f /var/www/html/build/integration/composer.lock - -echo $"Starting server using ($env.SQL) database…" - -chmod +sx /sbin/sudo - -mkdir /var/log/nginx /tmp /var/run/blackfire -touch /var/log/nginx/access.log -touch /var/log/nginx/error.log - -if ((getent group $HAZE_GID | length) > 0) { - groupadd haze - useradd -u $HAZE_UID -g $HAZE_GID -G haze haze -} else { - groupadd -g $HAZE_GID haze - useradd -u $HAZE_UID -g $HAZE_GID haze -} -chown -R $"haze:($HAZE_GID)" /home/haze -ls -af /etc/home | each {|file| ln -s $file.name $"/home/haze/($file.name | path basename)" } - -if ("/var/run/docker.sock" | path exists) { - let dockerGid = stat --format "%g" /var/run/docker.sock - groupadd docker -g $dockerGid - usermod -a -G docker haze -} - -if ("REDIS_TLS" in $env) { - cp /etc/supervisor/redis-tls.conf /etc/supervisor/enabled/ -} else { - cp /etc/supervisor/redis-plain.conf /etc/supervisor/enabled/ -} - -if ("BLACKFIRE_SERVER_ID" in $env) { - blackfire agent:config --server-id $env.BLACKFIRE_SERVER_ID --server-token $env.BLACKFIRE_SERVER_TOKEN - cp /etc/supervisor/blackfire.conf /etc/supervisor/enabled/ -} - -if ("PROXY_BASE" in $env) { - let UPSTREAM_DNS = cat /etc/resolv.conf | grep nameserver | cut -d' ' -f 2 - let RC = sed '/nameserver/d' /etc/resolv.conf - echo $RC | save -f /etc/resolv.conf - - echo "\nnameserver 127.0.0.22\n" | save -a /etc/resolv.conf - - echo $"s/UPSTREAM_DNS/($UPSTREAM_DNS)" - sed -i $"s/UPSTREAM_DNS/($UPSTREAM_DNS)/" /etc/dnsmasq.conf - echo $"s/PROXY_BASE/($env.PROXY_BASE)" - sed -i $"s/PROXY_BASE/($env.PROXY_BASE)/" /etc/dnsmasq.conf - echo $"s/HOST_IP/($env.HOST_IP)" - sed -i $"s/HOST_IP/($env.HOST_IP)/" /etc/dnsmasq.conf - - cp /etc/supervisor/dnsmasq.conf /etc/supervisor/enabled/ -} - -if ("FRANKENPHP" in $env) { - cp /etc/supervisor/frankenphp.conf /etc/supervisor/enabled/ -} else { - cp /etc/supervisor/php-fpm.conf /etc/supervisor/enabled/ - cp /etc/supervisor/nginx.conf /etc/supervisor/enabled/ -} - -exec supervisord -c /etc/supervisor/supervisord.conf diff --git a/nix/image/bootstrap.sh b/nix/image/bootstrap.sh new file mode 100755 index 0000000..141affa --- /dev/null +++ b/nix/image/bootstrap.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +touch /var/log/nginx/access.log +touch /var/log/nginx/error.log +touch /var/log/cron/owncloud.log + +echo "# Options in here overwrite the builtin php.ini" > /php.ini +chmod 0777 /php.ini +PHP_INI_DIR="$(php --ini | grep 'Scan' | cut -d ' ' -f7)" +ln -s /php.ini "$PHP_INI_DIR/zz_extra.ini" + +HAZE_UID=${HAZE_UID:-www-data} +HAZE_GID=${HAZE_GID:-www-data} + +nc-auto-config +shadow-setup + +echo "Running as $HAZE_UID:$HAZE_GID" + +mkdir -p /var/www/html/core/skeleton /var/www/html/build/integration/vendor /var/www/html/build/integration/output /var/www/html/build/integration/work /var/www/html/core/skeleton /var/www/.composer/cache /var/www/html/apps/spreed/tests/integration/vendor/composer +chown -R "$HAZE_UID":"$HAZE_GID" /var/www/html/data /var/www/html/config +chown "$HAZE_UID":"$HAZE_GID" /var/www/html/core/skeleton /var/www/html/build/integration/vendor /var/www/html/build/integration/composer.lock /var/www/html/build/integration/output /var/www/html/build/integration/work /var/www/html/core/skeleton /var/www/.composer/cache /var/www/html/apps/spreed/tests/integration/vendor/composer + +echo "{}" > /var/www/html/build/integration/composer.lock + +echo "Starting server using $SQL database…" + +# tail --follow --retry /var/log/nginx/*.log /var/log/cron/owncloud.log & + +chmod +sx /sbin/sudo + +mkdir -p /var/log/nginx /tmp /var/run/blackfire +touch /var/log/nginx/access.log +touch /var/log/nginx/error.log + +HAZE_UID=${HAZE_UID:-1000} +HAZE_GID=${HAZE_GID:-1000} + +if [ "$(getent group "$HAZE_GID")" ]; then + groupadd haze + EXTRA_GROUP=" -G haze" +else + groupadd -g "$HAZE_GID" haze + EXTRA_GROUP="" +fi + +useradd -u "$HAZE_UID" -g "$HAZE_GID""$EXTRA_GROUP" haze +chown -R haze:"$HAZE_GID" /home/haze + +if [ -f "/var/run/docker.sock" ]; then + groupadd docker -g "$(stat --format "%g" /var/run/docker.sock)" + usermod -a -G docker haze +fi + +if [ -n "${REDIS_TLS:-}" ] +then + redis-server --protected-mode no \ + --tls-port 6379 --port 0 \ + --tls-cert-file /redis-certificates/server.crt \ + --tls-key-file /redis-certificates/server.key \ + --tls-ca-cert-file /redis-certificates/ca.crt & +else + redis-server --protected-mode no & +fi + +if [ -n "${BLACKFIRE_SERVER_ID:-}" ] +then + sh -c ' + yes | blackfire agent:config --server-id=$BLACKFIRE_SERVER_ID --server-token=$BLACKFIRE_SERVER_TOKEN + BLACKFIRE_LOG_LEVEL=4 BLACKFIRE_LOG_FILE=/var/log/agent.log blackfire agent & + '& +fi + +php-fpm --fpm-config /etc/php-fpm.conf& + +nginx -c /etc/nginx.conf \ No newline at end of file diff --git a/nix/image/configs.nix b/nix/image/configs.nix index afa06c7..1b90bc8 100644 --- a/nix/image/configs.nix +++ b/nix/image/configs.nix @@ -1,7 +1,12 @@ {runCommand}: runCommand "configs" {} '' - mkdir -p $out - cp -r ${./configs} $out/etc - chmod -R +w $out/etc - mkdir $out/etc/supervisor/enabled/ + mkdir -p $out/etc + mkdir -p $out/etc/sudoers.d + mkdir -p $out/conf + cp ${./configs/cron.conf} $out/etc/oc-cron.conf + cp ${./configs/nginx-app.conf} $out/conf/nginx-app.conf + cp ${./configs/sudoers} $out/etc/sudoers.d/haze + cp -r ${./configs/nc} $out/etc/nc + cp ${./php-fpm.conf} $out/etc/php-fpm.conf + cp ${./nginx.conf} $out/etc/nginx.conf '' diff --git a/nix/image/configs/oc-cron.conf b/nix/image/configs/cron.conf similarity index 100% rename from nix/image/configs/oc-cron.conf rename to nix/image/configs/cron.conf diff --git a/nix/image/configs/dnsmasq.conf b/nix/image/configs/dnsmasq.conf deleted file mode 100644 index 2b1afc5..0000000 --- a/nix/image/configs/dnsmasq.conf +++ /dev/null @@ -1,6 +0,0 @@ -listen-address=127.0.0.22 -no-resolv - -address=/PROXY_BASE/HOST_IP - -server=UPSTREAM_DNS \ No newline at end of file diff --git a/nix/image/configs/home/.sqliterc b/nix/image/configs/home/.sqliterc deleted file mode 100644 index 0d5fe04..0000000 --- a/nix/image/configs/home/.sqliterc +++ /dev/null @@ -1 +0,0 @@ -.mode table diff --git a/nix/image/configs/nc/config.php b/nix/image/configs/nc/config.php index 06de6db..e8dc0af 100644 --- a/nix/image/configs/nc/config.php +++ b/nix/image/configs/nc/config.php @@ -1,19 +1,12 @@ - true, + 'appstoreenabled' => false, 'memcache.local' => '\\OC\\Memcache\\APCu', - 'memcache.distributed' => '\\OC\\Memcache\\Redis', - 'memcache.locking' => '\\OC\\Memcache\\Redis', + 'memcache.distributed' => '\\OC\\Memcache\\APCu', + 'memcache.locking' => '\\OC\\Memcache\\APCu', 'allow_local_remote_servers' => true, 'trusted_domains' => ['cloud'], 'profiling.secret' => 'haze', 'profiling.path' => '/tmp/profiling', //PLACEHOLDER -]); +]; diff --git a/nix/image/configs/nc/redis-default.php b/nix/image/configs/nc/redis-default.php index 71b18a8..2ba24aa 100644 --- a/nix/image/configs/nc/redis-default.php +++ b/nix/image/configs/nc/redis-default.php @@ -1 +1,2 @@ 'redis' => ['host' => 'localhost'], +//PLACEHOLDER diff --git a/nix/image/configs/nc/redis-tls.php b/nix/image/configs/nc/redis-tls.php index c3b9abe..fecc760 100644 --- a/nix/image/configs/nc/redis-tls.php +++ b/nix/image/configs/nc/redis-tls.php @@ -2,9 +2,10 @@ 'host' => 'tls://127.0.0.1', 'port' => 6379, 'ssl_context' => [ - 'local_cert' => '/certificates/redis/client.crt', - 'local_pk' => '/certificates/redis/client.key', - 'cafile' => '/certificates/redis/ca.crt', + 'local_cert' => '/redis-certificates/client.crt', + 'local_pk' => '/redis-certificates/client.key', + 'cafile' => '/redis-certificates/ca.crt', 'verify_peer_name' => false, ], ], +//PLACEHOLDER diff --git a/nix/image/configs/nc/s3s.php b/nix/image/configs/nc/s3s.php deleted file mode 100644 index cfbf186..0000000 --- a/nix/image/configs/nc/s3s.php +++ /dev/null @@ -1,15 +0,0 @@ - 'objectstore' => [ - 'class' => 'OC\Files\ObjectStore\S3', - 'arguments' => [ - 'bucket' => 'nextcloud', - 'autocreate' => true, - 'key' => 'minio', - 'secret' => 'minio123', - 'hostname' => 's3', - 'port' => 9000, - 'use_ssl' => true, - 'use_path_style' => true, - 'uploadPartSize' => 52428800, - 'use_nextcloud_bundle' => true, - ], - ], diff --git a/nix/image/configs/sudoers.d/haze b/nix/image/configs/sudoers similarity index 100% rename from nix/image/configs/sudoers.d/haze rename to nix/image/configs/sudoers diff --git a/nix/image/configs/supervisor/blackfire.conf b/nix/image/configs/supervisor/blackfire.conf deleted file mode 100644 index ca6cd89..0000000 --- a/nix/image/configs/supervisor/blackfire.conf +++ /dev/null @@ -1,2 +0,0 @@ -[program:blackfire] -command = blackfire agent \ No newline at end of file diff --git a/nix/image/configs/supervisor/dnsmasq.conf b/nix/image/configs/supervisor/dnsmasq.conf deleted file mode 100644 index d57ed09..0000000 --- a/nix/image/configs/supervisor/dnsmasq.conf +++ /dev/null @@ -1,2 +0,0 @@ -[program:dnsmasq] -command = /bin/dnsmasq --keep-in-foreground -u root \ No newline at end of file diff --git a/nix/image/configs/supervisor/frankenphp.conf b/nix/image/configs/supervisor/frankenphp.conf deleted file mode 100644 index 8c1b1e5..0000000 --- a/nix/image/configs/supervisor/frankenphp.conf +++ /dev/null @@ -1,3 +0,0 @@ -[program:frankenphp] -command = /bin/frankenphp php-server -directory = /var/www/html \ No newline at end of file diff --git a/nix/image/configs/supervisor/nginx.conf b/nix/image/configs/supervisor/nginx.conf deleted file mode 100644 index 957e4b3..0000000 --- a/nix/image/configs/supervisor/nginx.conf +++ /dev/null @@ -1,2 +0,0 @@ -[program:nginx] -command = /bin/nginx -c /etc/nginx.conf diff --git a/nix/image/configs/supervisor/php-fpm.conf b/nix/image/configs/supervisor/php-fpm.conf deleted file mode 100644 index 69418c7..0000000 --- a/nix/image/configs/supervisor/php-fpm.conf +++ /dev/null @@ -1,2 +0,0 @@ -[program:php-fpm] -command = /bin/php-fpm --fpm-config /etc/php-fpm.conf diff --git a/nix/image/configs/supervisor/redis-plain.conf b/nix/image/configs/supervisor/redis-plain.conf deleted file mode 100644 index e9284cc..0000000 --- a/nix/image/configs/supervisor/redis-plain.conf +++ /dev/null @@ -1,2 +0,0 @@ -[program:redis] -command = /bin/redis-server --protected-mode no \ No newline at end of file diff --git a/nix/image/configs/supervisor/redis-tls.conf b/nix/image/configs/supervisor/redis-tls.conf deleted file mode 100644 index d9f86bd..0000000 --- a/nix/image/configs/supervisor/redis-tls.conf +++ /dev/null @@ -1,2 +0,0 @@ -[program:redis-tls] -command = /bin/redis-server --protected-mode no --tls-port 6379 --port 0 --tls-cert-file /certificates/redis/server.crt --tls-key-file /certificates/redis/server.key --tls-ca-cert-file /certificates/redis/ca.crt \ No newline at end of file diff --git a/nix/image/configs/supervisor/supervisord.conf b/nix/image/configs/supervisor/supervisord.conf deleted file mode 100644 index bed7885..0000000 --- a/nix/image/configs/supervisor/supervisord.conf +++ /dev/null @@ -1,19 +0,0 @@ -[supervisord] -logfile = /dev/stdout -logfile_maxbytes = 0 -nodaemon = true -pidfile = /var/run/supervisord.pid -user = root - -[unix_http_server] -file = /var/run/supervisor.sock -chmod = 0777 - -[rpcinterface:supervisor] -supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface - -[supervisorctl] -serverurl = unix:///var/run/supervisor.sock - -[include] -files = enabled/* diff --git a/nix/image/haze.nix b/nix/image/haze.nix index 5ce1051..38bc8f9 100644 --- a/nix/image/haze.nix +++ b/nix/image/haze.nix @@ -7,9 +7,10 @@ blackfire, coreutils, getent, - writers, shadow, + buildEnv, runCommand, + cacert, callPackage, cronie, redis, @@ -32,20 +33,18 @@ writeShellApplication, vim, helix, - python3Packages, - dnsmasq, - frankenphp, - nushell, }: let - inherit (builtins) toString compareVersions; - inherit (lib) readFile getExe concatStringsSep splitString take optionals; - - version = (fromTOML (readFile ../../Cargo.toml)).package.version; + inherit (builtins) toString; + inherit (lib) readFile getExe concatStringsSep splitString take; phpVersion = concatStringsSep "." (take 2 (splitString "." php.version)); phpEnv = callPackage ./php.nix {inherit debug php;}; - bootstrap = writers.writeNuBin "bootstrap" (readFile ./bootstrap); + bootstrap = writeShellApplication { + name = "bootstrap"; + runtimeInputs = [getent]; + text = readFile ./bootstrap.sh; + }; shadowSetupScript = writeShellApplication { name = "shadow-setup"; text = dockerTools.shadowSetup; @@ -71,6 +70,14 @@ php = phpEnv; }; + phpunitWrapped = majorVersion: + writeShellApplication { + name = "phpunit${toString majorVersion}"; + text = '' + ${phpunitUnwrapped (toString majorVersion)}/bin/phpunit "$@" + ''; + }; + phpunit = writeShellApplication { name = "phpunit"; runtimeInputs = [jq]; @@ -97,9 +104,9 @@ ''; }; - certificates = runCommand "scripts" {} '' + redis-certificates = runCommand "scripts" {} '' mkdir -p $out - cp -r ${../../certificates} $out/certificates + cp -r ${../../redis-certificates} $out/redis-certificates ''; clamav-data = runCommand "scripts" {} '' mkdir -p $out/etc @@ -138,10 +145,6 @@ oracle-instantclient vim helix - python3Packages.supervisor - dnsmasq - nushell - getent ]; }; @@ -150,20 +153,11 @@ tag = phpVersion; fromImage = baseImage; - copyToRoot = - [ - phpEnv - phpEnv.packages.composer - phpunit - ] - ++ optionals ((compareVersions phpVersion "8.2") == 1) [ - (frankenphp.override { - php = php.withExtensions (import ./php-ext.nix { - inherit lib php; - enableBlackfire = false; - }); - }) - ]; + copyToRoot = [ + phpEnv + phpEnv.packages.composer + phpunit + ]; }; in dockerTools.buildLayeredImage { @@ -176,7 +170,7 @@ in bootstrap configs scripts - certificates + redis-certificates clamav-data shadowSetupScript ]; @@ -191,14 +185,7 @@ in ''; config = { Cmd = [(getExe bootstrap)]; - Env = [ - "EDITOR=hx" - "WEBROOT=/var/www/html" - "HAZE_IMAGE_VERSION=${toString version}" - ]; + Env = ["EDITOR=hx" "WEBROOT=/var/www/html"]; WorkingDir = "/var/www/html"; - Labels = { - "nl.icewind.haze.version" = toString version; - }; }; } diff --git a/nix/image/configs/nginx.conf b/nix/image/nginx.conf similarity index 76% rename from nix/image/configs/nginx.conf rename to nix/image/nginx.conf index 15a57c3..3de81ca 100644 --- a/nix/image/configs/nginx.conf +++ b/nix/image/nginx.conf @@ -69,17 +69,7 @@ http { access_log off; } - location ^~ /store_apps { - root /var/www; - try_files $uri /index.php$request_uri; - access_log off; # Optional: Don't log access to assets - - location ~ \.wasm$ { - default_type application/wasm; - } - } - - include /etc/nginx-app.conf; + include /conf/nginx-app.conf; location ~ \.php(?:$|/) { rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; @@ -109,16 +99,5 @@ http { expires 7d; # Cache-Control policy borrowed from `.htaccess` access_log off; # Optional: Don't log access to assets } - - location /fpm-status { - include /conf/fastcgi_params; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_pass php-handler; - fastcgi_read_timeout 3600; - proxy_request_buffering off; - fastcgi_request_buffering off; - fastcgi_buffering off; - } } } diff --git a/nix/image/php-ext.nix b/nix/image/php-ext.nix deleted file mode 100644 index 0a7e53e..0000000 --- a/nix/image/php-ext.nix +++ /dev/null @@ -1,45 +0,0 @@ -{ - lib, - php, - debug ? false, - enableBlackfire ? true, -}: let - inherit (builtins) compareVersions; - inherit (lib) optionals; - withBlackfire = enableBlackfire && !debug && ((compareVersions php.version "8.1.0") == 1); -in - { - enabled, - all, - }: - enabled - ++ (with all; - [ - xdebug - excimer - inotify - redis - oci8 - zip - pdo - pdo_pgsql - pdo_sqlite - pdo_mysql - pgsql - intl - curl - mbstring - pcntl - ldap - exif - gmp - apcu - ffi - imagick - ] - ++ optionals (!debug) [ - # smbclient # this breaks the build for no apparent reason - ] - ++ optionals withBlackfire [ - blackfire - ]) diff --git a/nix/image/configs/php-fpm.conf b/nix/image/php-fpm.conf similarity index 77% rename from nix/image/configs/php-fpm.conf rename to nix/image/php-fpm.conf index 89379d8..e6292fb 100644 --- a/nix/image/configs/php-fpm.conf +++ b/nix/image/php-fpm.conf @@ -1,11 +1,11 @@ [global] -error_log = /var/log/php-fpm-error.log +error_log = /proc/self/fd/2 daemonize = no [www] -access.log =/var/log/php-fpm-access.log +access.log = /proc/self/fd/2 user = haze group = haze @@ -21,7 +21,6 @@ pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 -pm.status_path = /fpm-status clear_env = no diff --git a/nix/image/php.nix b/nix/image/php.nix index 8ef3d31..852b478 100644 --- a/nix/image/php.nix +++ b/nix/image/php.nix @@ -2,23 +2,56 @@ lib, php, debug ? false, -}: -php.buildEnv { - extensions = import ./php-ext.nix {inherit lib php debug;}; - extraConfig = '' - xdebug.mode=debug,trace,profile - xdebug.start_with_request=trigger - xdebug.discover_client_host=false - xdebug.client_host=hazehost - xdebug.log_level=0 - xdebug.output_dir=/tmp/xdebug +}: let + inherit (lib) optionals; +in + php.buildEnv { + extensions = { + enabled, + all, + }: + enabled + ++ (with all; + [ + xdebug + excimer + inotify + redis + oci8 + zip + pdo + pdo_pgsql + pdo_sqlite + pdo_mysql + pgsql + intl + curl + mbstring + pcntl + ldap + exif + gmp + apcu + ffi + ] + ++ optionals (!debug) [ + smbclient # this breaks the build for no apparent reason + blackfire + ]); + extraConfig = '' + xdebug.mode=debug,trace,profile + xdebug.start_with_request=trigger + xdebug.discover_client_host=false + xdebug.client_host=hazehost + xdebug.log_level=0 + xdebug.output_dir=/tmp/xdebug - memory_limit=512M + memory_limit=512M - post_max_size 10G - upload_max_filesize 10G + post_max_size 10G + upload_max_filesize 10G - apc.enable_cli=1 - opcache.enable_cli=1 - ''; -} + apc.enable_cli=1 + opcache.enable_cli=1 + ''; + } diff --git a/nix/image/scripts/install b/nix/image/scripts/install index 35d3f00..d216118 100755 --- a/nix/image/scripts/install +++ b/nix/image/scripts/install @@ -1,22 +1,20 @@ -#!/bin/nu +#!/bin/sh -def main [username: string, password: string] { - cd $env.WEBROOT; - let sql = match $env.SQL { - "oracle" => "oci" - "mariadb" => "mysql" - _ => $env.SQL - } - let dbName = match $env.SQL { - "oracle" => "xe" - _ => "haze" - } - let dbUser = match $env.SQL { - "oracle" => "system" - _ => "haze" - } - let dbPass = "haze" - let dbHost = $env.SQL +USER=$1 +PASSWORD=$2 - occ maintenance:install --admin-user $username --admin-pass $password --database $sql --database-name $dbName --database-host $dbHost --database-user $dbUser --database-pass $dbPass -} +if [ -z "$USER" ] || [ -z "$PASSWORD" ]; then + echo "Usage: install \$USER \$PASSWORD" + exit; +fi + +cd $WEBROOT + +if [ "$SQL" = "oci" ]; then + # oracle is a special snowflake + occ maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database=$SQL --database-name=xe --database-host=$SQL --database-user=system --database-pass=haze +elif [ "$SQL" = "mariadb" ]; then + occ maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database=mysql --database-name=haze --database-host=$SQL --database-user=haze --database-pass=haze +else + occ maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database=$SQL --database-name=haze --database-host=$SQL --database-user=haze --database-pass=haze +fi; diff --git a/nix/image/scripts/integration b/nix/image/scripts/integration index d8187d9..4f73aef 100755 --- a/nix/image/scripts/integration +++ b/nix/image/scripts/integration @@ -1,22 +1,4 @@ -#!/bin/nu +#!/bin/sh -def --wrapped main [feature: path, ...rest] { - mut feature = $feature; - mut workdir = $"($env.WEBROOT)/build/integration" - if ($feature | str starts-with "apps/") { - let parts = $feature | split row '/' - occ app:enable $parts.1 - let parts = $feature | split row -n 2 '/features/' - $workdir = $parts.0 - $feature = $"features/($parts.1)" - } else if ($feature | str starts-with "build/integration/") { - $feature = $feature | str replace "build/integration/" "" - } - - # don't use the proxy urls for generated urls - occ config:system:delete overwritehost - occ config:system:delete overwriteprotocol - - cd $workdir - bash run.sh $feature ...$rest -} +cd $WEBROOT/build/integration +./run.sh "$@" diff --git a/nix/image/scripts/nc-auto-config b/nix/image/scripts/nc-auto-config index b7a2c07..6a803d9 100755 --- a/nix/image/scripts/nc-auto-config +++ b/nix/image/scripts/nc-auto-config @@ -1,4 +1,4 @@ -#!/bin/nu +#!/usr/bin/env bash touch /var/log/nginx/access.log touch /var/log/nginx/error.log @@ -7,30 +7,59 @@ touch /var/log/cron/owncloud.log cp /etc/nc/config.php /var/www/html/config/config.php chmod 0755 /var/www/html/config/config.php -let configName = match $env.SQL { - "oracle" => "oci" - _ => $env.SQL +if [ "$SQL" = "mysql" ] +then + cp /etc/nc/autoconfig_mysql.php /var/www/html/config/autoconfig.php +fi -} -let configPath = $"/etc/nc/autoconfig_($configName).php" +if [ "$SQL" = "mariadb" ] +then + cp /etc/nc/autoconfig_mariadb.php /var/www/html/config/autoconfig.php +fi -if ($configPath | path exists) { - cp $configPath /var/www/html/config/autoconfig.php -} +if [ "$SQL" = "pgsql" ] +then + cp /etc/nc/autoconfig_pgsql.php /var/www/html/config/autoconfig.php +fi -def loadExtraConfig [name: string] { - sed -i $'/\/\/PLACEHOLDER/ r /etc/nc/($name).php' /var/www/html/config/config.php -} +if [ "$SQL" = "oci" ] +then + cp /etc/nc/autoconfig_oci.php /var/www/html/config/autoconfig.php +fi -let extraConfigs = ["S3", "S3S", "S3MB", "S3M", "SWIFT", "SWIFTV3", "AZURE"]; -$extraConfigs | each { - if ($in in $env) { - loadExtraConfig ($in | str downcase) - } -} +if [ -n "${S3:-}" ] +then + sed -i '/\/\/PLACEHOLDER/ r /etc/nc/s3.php' /var/www/html/config/config.php +fi -if ("REDIS_TLS" in $env) { - loadExtraConfig "redis-tls" -} else { - loadExtraConfig "redis-default" -} +if [ -n "${S3MB:-}" ] +then + sed -i '/\/\/PLACEHOLDER/ r /etc/nc/s3mb.php' /var/www/html/config/config.php +fi + +if [ -n "${S3M:-}" ] +then + sed -i '/\/\/PLACEHOLDER/ r /etc/nc/s3m.php' /var/www/html/config/config.php +fi + +if [ -n "${SWIFT:-}" ] +then + sed -i '/\/\/PLACEHOLDER/ r /etc/nc/swift.php' /var/www/html/config/config.php +fi + +if [ -n "${SWIFTV3:-}" ] +then + sed -i '/\/\/PLACEHOLDER/ r /etc/nc/swiftv3.php' /var/www/html/config/config.php +fi + +if [ -n "${AZURE:-}" ] +then + sed -i '/\/\/PLACEHOLDER/ r /etc/nc/azure.php' /var/www/html/config/config.php +fi + +if [ -n "${REDIS_TLS:-}" ] +then + sed -i '/\/\/PLACEHOLDER/ r /etc/nc/redis-tls.php' /var/www/html/config/config.php +else + sed -i '/\/\/PLACEHOLDER/ r /etc/nc/redis-default.php' /var/www/html/config/config.php +fi diff --git a/nix/image/scripts/occ b/nix/image/scripts/occ index 07a443b..cf7d6fa 100755 --- a/nix/image/scripts/occ +++ b/nix/image/scripts/occ @@ -1,5 +1,5 @@ -#!/bin/nu +#!/bin/sh -def --wrapped main [...rest] { - XDEBUG_SESSION=haze php $"($env.WEBROOT)/occ" ...$rest -} +export XDEBUG_SESSION=haze + +php $WEBROOT/occ "$@" diff --git a/nix/image/scripts/tests b/nix/image/scripts/tests index 868f225..70691c0 100755 --- a/nix/image/scripts/tests +++ b/nix/image/scripts/tests @@ -1,7 +1,7 @@ -#!/bin/nu +#!/bin/sh -def --wrapped main [...rest] { - cd $env.WEBROOT +cd $WEBROOT - XDEBUG_SESSION=haze phpunit --configuration $"($env.WEBROOT)/tests/phpunit-autotest.xml" ...$rest -} +export XDEBUG_SESSION=haze + +phpunit --configuration $WEBROOT/tests/phpunit-autotest.xml $@ diff --git a/nix/overlay.nix b/nix/overlay.nix index 276b70e..b08daca 100644 --- a/nix/overlay.nix +++ b/nix/overlay.nix @@ -1,9 +1,7 @@ final: prev: { haze = final.callPackage ./package.nix {}; - haze-image-php-85 = final.callPackage ./image/haze.nix {php = final.php85;}; haze-image-php-84 = final.callPackage ./image/haze.nix {php = final.php84;}; haze-image-php-83 = final.callPackage ./image/haze.nix {php = final.php83;}; haze-image-php-82 = final.callPackage ./image/haze.nix {php = final.php82;}; haze-image-php-81 = final.callPackage ./image/haze.nix {php = final.php81;}; - haze-image-php-80 = final.callPackage ./image/haze.nix {php = final.php80;}; } diff --git a/nix/package.nix b/nix/package.nix index c6166f0..d79a216 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -1,15 +1,16 @@ { rustPlatform, + pkg-config, lib, git, }: let inherit (lib) getExe; inherit (lib.sources) sourceByRegex; inherit (builtins) fromTOML readFile; - src = sourceByRegex ../. ["Cargo.*" "(src|certificates)(/.*)?"]; + src = sourceByRegex ../. ["Cargo.*" "(src|redis-certificates)(/.*)?"]; version = (fromTOML (readFile ../Cargo.toml)).package.version; in - rustPlatform.buildRustPackage { + rustPlatform.buildRustPackage rec { pname = "haze"; inherit src version; @@ -19,7 +20,7 @@ in cargoLock = { lockFile = ../Cargo.lock; outputHashes = { - "hyper-reverse-proxy-0.5.2-dev" = "sha256-awmj5aLFTea+kj81cwmfP1HWlWezwEKfyQSUJWjtamk="; + "hyper-reverse-proxy-0.5.2-dev" = "sha256-+ebi4FVVkiOpf75e8K5oGkHJBYQjLNJhUPNj+78zd7Q="; }; }; } diff --git a/certificates/redis/ca.crt b/redis-certificates/ca.crt similarity index 100% rename from certificates/redis/ca.crt rename to redis-certificates/ca.crt diff --git a/certificates/redis/ca.key b/redis-certificates/ca.key similarity index 100% rename from certificates/redis/ca.key rename to redis-certificates/ca.key diff --git a/certificates/redis/ca.txt b/redis-certificates/ca.txt similarity index 100% rename from certificates/redis/ca.txt rename to redis-certificates/ca.txt diff --git a/certificates/redis/client.crt b/redis-certificates/client.crt similarity index 100% rename from certificates/redis/client.crt rename to redis-certificates/client.crt diff --git a/certificates/redis/client.key b/redis-certificates/client.key similarity index 100% rename from certificates/redis/client.key rename to redis-certificates/client.key diff --git a/certificates/redis/openssl.cnf b/redis-certificates/openssl.cnf similarity index 100% rename from certificates/redis/openssl.cnf rename to redis-certificates/openssl.cnf diff --git a/certificates/redis/redis.crt b/redis-certificates/redis.crt similarity index 100% rename from certificates/redis/redis.crt rename to redis-certificates/redis.crt diff --git a/certificates/redis/redis.dh b/redis-certificates/redis.dh similarity index 100% rename from certificates/redis/redis.dh rename to redis-certificates/redis.dh diff --git a/certificates/redis/redis.key b/redis-certificates/redis.key similarity index 100% rename from certificates/redis/redis.key rename to redis-certificates/redis.key diff --git a/certificates/redis/server.crt b/redis-certificates/server.crt similarity index 100% rename from certificates/redis/server.crt rename to redis-certificates/server.crt diff --git a/certificates/redis/server.key b/redis-certificates/server.key similarity index 100% rename from certificates/redis/server.key rename to redis-certificates/server.key diff --git a/src/args.rs b/src/args.rs index 59bca87..bcf9365 100644 --- a/src/args.rs +++ b/src/args.rs @@ -124,12 +124,9 @@ pub enum GitOperation { /// /// "main" and "master" can be used interchangeably. #[strum(props( - Args = "[branch] branch to checkout, defaults to the branch matching the current server version [-v] verbose" + Args = "[branch] branch to checkout, defaults to the branch matching the current server version" ))] - Checkout { - branch: Option, - verbose: bool, - }, + Checkout { branch: Option }, } impl SubCommand for GitOperation { @@ -165,7 +162,6 @@ impl LogService { #[derive(Debug, Clone, Eq, PartialEq)] pub enum ExecService { Db, - Service(Service), } impl HazeArgs { @@ -233,14 +229,6 @@ impl HazeArgs { args.next(); Some(ExecService::Db) } - Some(arg) => Service::from_type(&[], arg.as_ref()) - .into_iter() - .filter_map(|services| services.into_iter().next()) - .next() - .map(|service| { - args.next(); - ExecService::Service(service) - }), _ => None, }; @@ -332,24 +320,18 @@ impl HazeArgs { HazeCommand::Checkout => { let branch = args.next().map(S::into); Ok(HazeArgs::Git { - operation: GitOperation::Checkout { - branch, - verbose: false, - }, + operation: GitOperation::Checkout { branch }, }) } HazeCommand::Git => { - let mut args = args.peekable(); let operation = args .next() .ok_or_else(|| Report::msg("No git operation provided"))?; match operation.as_ref() { "checkout" => { - let verbose = args.next_if(|arg| arg.as_ref() == "-v").is_some(); let branch = args.next().map(S::into); - let verbose = verbose | args.next_if(|arg| arg.as_ref() == "-v").is_some(); Ok(HazeArgs::Git { - operation: GitOperation::Checkout { branch, verbose }, + operation: GitOperation::Checkout { branch }, }) } "pull" => Ok(HazeArgs::Git { @@ -487,7 +469,7 @@ pub enum HazeCommand { Edit, /// Reload the php configuration in the instance #[strum(props( - Details = "note: you can overwrite php.ini settings with haze [filter] edit /config/php.ini" + Details = "note: you can overwrite php.ini settings with haze [filter] edit /php.ini" ))] Reload, } @@ -523,7 +505,6 @@ impl SubCommand for HazeCommand { fn test_arg_parse() { let config = HazeConfig { sources_root: Default::default(), - app_directories: Default::default(), work_dir: Default::default(), auto_setup: Default::default(), volume: vec![], diff --git a/src/cloud.rs b/src/cloud.rs index afa01cf..70ee931 100644 --- a/src/cloud.rs +++ b/src/cloud.rs @@ -1,14 +1,13 @@ use crate::config::{HazeConfig, HazeVolumeConfig}; use crate::database::Database; use crate::exec::{exec, exec_io, exec_tty, ExitCode}; -use crate::mapping::{for_config, Mapping}; +use crate::mapping::{default_mappings, Mapping}; use crate::php::{PhpVersion, PHP_MEMORY_LIMIT}; use crate::service::Service; use crate::service::ServiceTrait; -use crate::sources::download_nc; -use bollard::config::NetworkCreateRequest; -use bollard::models::{ContainerState, ContainerUpdateBody}; -use bollard::query_parameters::{ListContainersOptions, RemoveContainerOptions}; +use bollard::container::{ListContainersOptions, RemoveContainerOptions, UpdateContainerOptions}; +use bollard::models::ContainerState; +use bollard::network::CreateNetworkOptions; use bollard::Docker; use camino::{Utf8Path, Utf8PathBuf}; use flate2::read::GzDecoder; @@ -20,9 +19,9 @@ use std::borrow::Cow; use std::collections::HashMap; use std::fmt::Display; use std::fs; -use std::fs::{read_to_string, write}; +use std::fs::read_to_string; use std::io::{stdout, Cursor, Read, Stdout, Write}; -use std::iter::{once, Peekable}; +use std::iter::Peekable; use std::net::IpAddr; use std::os::unix::fs::MetadataExt; use std::str::FromStr; @@ -58,7 +57,6 @@ pub struct CloudOptions { pub php: PhpVersion, pub services: Vec, pub app_packages: Vec, - pub version: Option, } impl CloudOptions { @@ -71,7 +69,6 @@ impl CloudOptions { db: Database::default(), services: vec![], app_packages: vec![], - version: None, } } @@ -85,7 +82,6 @@ impl CloudOptions { let mut name = None; let mut services = Vec::new(); let mut app_package = Vec::new(); - let mut version = None; while let Some(option) = args.peek() { if let Ok(db_option) = Database::from_str(option.as_ref()) { @@ -100,9 +96,6 @@ impl CloudOptions { } else if option.as_ref().ends_with(".tar.gz") { app_package.push(option.to_string().into()); let _ = args.next(); - } else if let Some(v) = option.as_ref().strip_prefix("v") { - version = Some(v.into()); - let _ = args.next(); } else if option.as_ref() == "--name" { let _ = args.next(); name = args.next().map(|s| s.into()); @@ -119,7 +112,6 @@ impl CloudOptions { .unwrap_or_default(), services, app_packages: app_package, - version, }) } } @@ -152,44 +144,44 @@ fn test_option_parse() { ..Default::default() } ); - let mut args = vec!["8"].into_iter().peekable(); + let mut args = vec!["7"].into_iter().peekable(); assert_eq!( CloudOptions::parse(&config, &mut args).unwrap(), CloudOptions { - php: PhpVersion::Php80, + php: PhpVersion::Php74, ..Default::default() } ); - let mut args = vec!["8.1", "pgsql", "rest"].into_iter().peekable(); + let mut args = vec!["7", "pgsql", "rest"].into_iter().peekable(); assert_eq!( CloudOptions::parse(&config, &mut args).unwrap(), CloudOptions { - php: PhpVersion::Php81, + php: PhpVersion::Php74, db: Database::Postgres, ..Default::default() } ); - let mut args = vec!["8", "ldap", "pgsql"].into_iter().peekable(); + let mut args = vec!["7", "ldap", "pgsql"].into_iter().peekable(); assert_eq!( CloudOptions::parse(&config, &mut args).unwrap(), CloudOptions { - php: PhpVersion::Php80, + php: PhpVersion::Php74, db: Database::Postgres, services: vec![Service::Ldap(Ldap), Service::LdapAdmin(LdapAdmin)], ..Default::default() } ); - let mut args = vec!["8", "pgsql", "ldap"].into_iter().peekable(); + let mut args = vec!["7", "pgsql", "ldap"].into_iter().peekable(); assert_eq!( CloudOptions::parse(&config, &mut args).unwrap(), CloudOptions { - php: PhpVersion::Php80, + php: PhpVersion::Php74, db: Database::Postgres, services: vec![Service::Ldap(Ldap), Service::LdapAdmin(LdapAdmin)], ..Default::default() } ); - let mut args = vec!["8", "pgsql", "ldap", "mypreset"] + let mut args = vec!["7", "pgsql", "ldap", "mypreset"] .into_iter() .peekable(); @@ -206,7 +198,7 @@ fn test_option_parse() { assert_eq!( CloudOptions::parse(&config, &mut args).unwrap(), CloudOptions { - php: PhpVersion::Php80, + php: PhpVersion::Php74, db: Database::Postgres, services: vec![ Service::Ldap(Ldap), @@ -218,7 +210,7 @@ fn test_option_parse() { ); } -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Cloud { pub id: String, pub network: String, @@ -253,12 +245,6 @@ impl Cloud { .wrap_err("Failed to create directory for app packages")?; } - let source_root = if let Some(version) = options.version.as_deref() { - download_nc(config, version).await? - } else { - config.sources_root.clone() - }; - let app_volumes = options .app_packages .iter() @@ -286,8 +272,11 @@ impl Cloud { }) }) .collect::>>()?; - - let mappings = for_config(config) + let mappings = config + .volume + .iter() + .map(Mapping::from) + .chain(default_mappings()) .chain(app_volumes.iter().map(Mapping::from)) .collect::>(); for mapping in &mappings { @@ -297,56 +286,9 @@ impl Cloud { .wrap_err_with(|| format!("Failed to setup work directory {}", mapping.source))?; } - let mut nc_config = Value::Object( - config - .auto_setup - .config - .clone() - .into_iter() - .map(|(key, value)| (key, serde_json::to_value(value).unwrap())) - .collect(), - ); - nc_config["apps_paths"] = Value::Array( - once("apps") - .chain( - config - .app_directories - .iter() - .filter_map(|dir| dir.file_name()), - ) - .map(|name| { - [ - ( - String::from("path"), - Value::from(format!("/var/www/html/{}", name)), - ), - (String::from("url"), Value::from(format!("/{}", name))), - (String::from("writable"), Value::from(false)), - ] - .into_iter() - .collect() - }) - .chain(once( - [ - (String::from("path"), Value::from("/var/www/store_apps")), - (String::from("url"), Value::from("/store_apps")), - (String::from("writable"), Value::from(true)), - ] - .into_iter() - .collect(), - )) - .collect(), - ); - write( - workdir.join("config/nextcloud.json"), - serde_json::to_string_pretty(&nc_config).unwrap(), - ) - .into_diagnostic() - .wrap_err("Failed to write config json")?; - let network = docker - .create_network(NetworkCreateRequest { - name: id.clone(), + .create_network(CreateNetworkOptions { + name: id.as_str(), ..Default::default() }) .await @@ -354,7 +296,7 @@ impl Cloud { .id; let network_info = docker - .inspect_network(&network, None) + .inspect_network::(&network, None) .await .into_diagnostic()?; let gateway = network_info @@ -385,7 +327,7 @@ impl Cloud { ]; let volumes: Vec = mappings .into_iter() - .filter_map(|mapping| mapping.get_volume_arg(&id, config, &source_root)) + .filter_map(|mapping| mapping.get_volume_arg(&id, config)) .collect(); if let Some(db_name) = options @@ -440,7 +382,6 @@ impl Cloud { gateway, &options.services, &config.proxy, - options.version.as_deref(), ) .await .wrap_err("Failed to start php container") @@ -498,26 +439,9 @@ impl Cloud { } }; - for pre_setup in options - .services - .iter() - .flat_map(|service| service.pre_setup(docker, &id, config).into_iter().flatten()) - { - exec( - docker, - &container, - &uid.to_string(), - pre_setup, - vec!["NC_IS_CONFIG_READ_ONLY=1"], - Some(stdout()), - ) - .await?; - } - containers.push(container); let options_clone = options.clone(); - let proxy_config = config.proxy.clone(); let cloud_id = id.clone(); let docker_clone = docker.clone(); spawn(async move { @@ -531,10 +455,7 @@ impl Cloud { return; } for service in options_clone.services { - match service - .start_message(&docker_clone, &cloud_id, &proxy_config) - .await - { + match service.start_message(&docker_clone, &cloud_id).await { Ok(Some(msg)) => { println!("{}", msg); } @@ -563,9 +484,6 @@ impl Cloud { pub async fn destroy(self, docker: &Docker) -> Result<()> { for container in self.containers { - let _ = docker - .kill_container(container.trim_start_matches('/'), None) - .await; docker .remove_container( container.trim_start_matches('/'), @@ -665,7 +583,7 @@ impl Cloud { config: &HazeConfig, ) -> Result> { let containers = docker - .list_containers(Some(ListContainersOptions { + .list_containers::(Some(ListContainersOptions { all: true, ..Default::default() })) @@ -702,7 +620,6 @@ impl Cloud { let labels = cloud.labels?; let db = labels.get("haze-db")?.parse().ok()?; let php = labels.get("haze-php")?.parse().ok()?; - let version = labels.get("haze-version").cloned(); let found_services = labels .get("haze-services")? @@ -748,7 +665,6 @@ impl Cloud { db, services: found_services, app_packages: vec![], - version, }, pinned, address, @@ -819,9 +735,9 @@ impl Cloud { docker .update_container( &self.id, - ContainerUpdateBody { + UpdateContainerOptions:: { memory: Some(PHP_MEMORY_LIMIT + 1), - ..ContainerUpdateBody::default() + ..UpdateContainerOptions::default() }, ) .await @@ -833,9 +749,9 @@ impl Cloud { docker .update_container( &self.id, - ContainerUpdateBody { + UpdateContainerOptions:: { memory: Some(PHP_MEMORY_LIMIT), - ..ContainerUpdateBody::default() + ..UpdateContainerOptions::default() }, ) .await @@ -861,25 +777,20 @@ impl Cloud { format!("/var/www/html/{path}").into() }; - let mut mappings = for_config(config).collect::>(); + let mut mappings = config + .volume + .iter() + .map(Mapping::from) + .chain(default_mappings()) + .collect::>(); mappings.sort_by_key(|mapping| usize::MAX - mapping.target.as_str().len()); for mapping in mappings { if let Some(rel_path) = path.strip_prefix(mapping.target.as_str()) { let rel_path = rel_path.trim_matches('/'); - return Some( - mapping - .source(&self.id, config, &config.sources_root) - .join(rel_path), - ); + return Some(mapping.source(&self.id, config).join(rel_path)); } } None } } - -impl PartialEq for Cloud { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} diff --git a/src/config.rs b/src/config.rs index 9e4548f..07cfcef 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,17 +4,15 @@ use miette::{IntoDiagnostic, Report, Result, WrapErr}; use serde::Deserialize; use std::collections::HashMap; use std::convert::TryFrom; -use std::env::home_dir; +use std::env::var; use std::fs::read_to_string; use std::net::IpAddr; -use toml::map::Map; use toml::Value; #[derive(Debug, Deserialize, Default)] #[serde(from = "RawHazeConfig")] pub struct HazeConfig { pub sources_root: Utf8PathBuf, - pub app_directories: Vec, pub work_dir: Utf8PathBuf, pub auto_setup: HazeAutoSetupConfig, pub volume: Vec, @@ -29,8 +27,6 @@ pub struct RawHazeConfig { #[serde(default = "default_work_dir")] pub work_dir: Utf8PathBuf, #[serde(default)] - pub app_directories: Vec, - #[serde(default)] pub auto_setup: HazeAutoSetupConfig, #[serde(default)] pub volume: Vec, @@ -46,11 +42,7 @@ impl From for HazeConfig { fn from(raw: RawHazeConfig) -> Self { fn normalize_path(path: Utf8PathBuf) -> Utf8PathBuf { if path.starts_with("~") { - let home = home_dir().expect("can't detect home directory"); - let home = home - .into_os_string() - .into_string() - .expect("non-utf8 home directory"); + let home = var("HOME").expect("HOME not set"); format!("{}{}", home, &path.as_str()[1..]).into() } else { path @@ -59,11 +51,6 @@ impl From for HazeConfig { HazeConfig { sources_root: normalize_path(raw.sources_root), - app_directories: raw - .app_directories - .into_iter() - .map(normalize_path) - .collect(), work_dir: normalize_path(raw.work_dir), auto_setup: raw.auto_setup, volume: raw.volume, @@ -88,8 +75,6 @@ pub struct HazeAutoSetupConfig { pub disable_apps: Vec, #[serde(default)] pub post_setup: Vec, - #[serde(default)] - pub config: Map, } impl Default for HazeAutoSetupConfig { @@ -101,7 +86,6 @@ impl Default for HazeAutoSetupConfig { enable_apps: Vec::default(), disable_apps: Vec::default(), post_setup: Vec::default(), - config: Map::default(), } } } @@ -185,7 +169,7 @@ fn load_secret(name: &str, path: Option, raw: Option) -> Result< } } -#[derive(Default, Deserialize, Debug, Clone)] +#[derive(Default, Deserialize, Debug)] pub struct ProxyConfig { pub listen: String, #[serde(default)] diff --git a/src/database.rs b/src/database.rs index 0bc31d7..d621e84 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,8 +1,7 @@ use crate::exec::{exec, exec_tty, ExitCode}; use crate::image::pull_image; -use bollard::config::ContainerCreateBody; -use bollard::models::{EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::{IntoDiagnostic, Report, Result, WrapErr}; @@ -194,31 +193,39 @@ impl Database { .wrap_err("Failed to pull database image")?; } let options = Some(CreateContainerOptions { - name: Some(format!("{}-db{}", cloud_id, postfix)), + name: format!("{}-db{}", cloud_id, postfix), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(self.image().into()), - env: Some(self.env().into_iter().map(String::from).collect()), + let config = Config { + image: Some(self.image()), + env: Some(self.env()), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => "db".into(), - "haze-cloud-id".into() => cloud_id.into() + "haze-type" => "db", + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - String::from(network) => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![ format!("{}{}", self.name(), postfix), format!("db{}", postfix), ]), ..Default::default() } - }), + }, }), + cmd: if self.image() == "mysql:8" { + Some(vec![ + "--default-authentication-plugin", + "mysql_native_password", + ]) + } else { + None + }, ..Default::default() }; let id = docker @@ -226,7 +233,10 @@ impl Database { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(Some(id)) } diff --git a/src/exec.rs b/src/exec.rs index 8d07508..ec67333 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -1,5 +1,5 @@ +use bollard::container::LogsOptions; use bollard::exec::{CreateExecOptions, ResizeExecOptions, StartExecResults}; -use bollard::query_parameters::LogsOptions; use bollard::Docker; use futures_util::StreamExt; use miette::{IntoDiagnostic, Report, Result, WrapErr}; @@ -189,7 +189,7 @@ pub async fn container_logs( count: usize, follow: bool, ) -> Result<()> { - let mut stream = docker.logs( + let mut stream = docker.logs::( container, Some(LogsOptions { stdout: true, diff --git a/src/git.rs b/src/git.rs index fc31255..d08f2f3 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,33 +1,22 @@ -use crate::config::HazeConfig; use crate::Result; use git2::build::CheckoutBuilder; use git2::{Branch, BranchType, Repository, RepositoryState}; -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use miette::{Context, IntoDiagnostic}; -use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; -use rayon::ThreadPoolBuilder; use std::fs::read_dir; -use std::iter::once; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; -use std::time::Duration; -fn find_app_repos(config: &HazeConfig) -> Result> { - let apps_dirs = once(config.sources_root.as_path().join("apps")) - .chain(config.app_directories.iter().cloned()); - let dir_handles = apps_dirs - .map(|dir| read_dir(dir).into_diagnostic()) - .collect::>>()?; - Ok(dir_handles - .into_iter() - .flatten() +fn find_app_repos(root: impl AsRef) -> Result> { + let apps_dir = root.as_ref().join("apps"); + Ok(read_dir(apps_dir) + .into_diagnostic()? .flatten() .filter(|app| app.path().join(".git").is_dir()) .map(|app| app.path())) } -fn longest_app_branch(config: &HazeConfig) -> Result<(usize, usize)> { - Ok(find_app_repos(config)? +fn longest_app_branch(root: impl AsRef) -> Result<(usize, usize)> { + Ok(find_app_repos(root)? .filter_map(|app_dir| { let app_name = app_dir.file_name()?.to_str()?; let repo = Repository::init(&app_dir).ok()?; @@ -38,32 +27,27 @@ fn longest_app_branch(config: &HazeConfig) -> Result<(usize, usize)> { .unwrap_or_default()) } -pub fn checkout_all(config: &HazeConfig, mut name: &str, verbose: bool) -> Result<()> { +pub fn checkout_all>(sources_root: P, mut name: &str) -> Result<()> { // "main" and "master" are interchangeable if name == "main" { name = "master"; } - for app_dir in find_app_repos(config)? { + for app_dir in find_app_repos(sources_root)? { let repo = Repository::init(&app_dir) .into_diagnostic() .wrap_err_with(|| format!("Failed to open repository {}", app_dir.display()))?; - let app_name = app_dir.file_name().unwrap().to_string_lossy(); if let Some(branch) = get_branch(&repo, name)? { if !branch.is_head() { let is_remote = branch.get().is_remote(); - print!("{app_name}"); + print!("{}", app_dir.file_name().unwrap().to_string_lossy()); if let Err(e) = checkout(&repo, &branch, is_remote.then_some(name)) { println!(": {:#} ❌", e); } else { println!(" ✓"); } - } else if verbose { - println!("{app_name} -"); } - } else if verbose { - println!("{app_name} 🛇 Branch not found"); }; } Ok(()) @@ -84,69 +68,42 @@ const GIT_BINARY: &str = match option_env!("GIT_BINARY") { None => "git", }; -pub fn pull_all(config: &HazeConfig) -> Result<()> { - let (max_app, max_branch) = longest_app_branch(config)?; +pub fn pull_all>(sources_root: P) -> Result<()> { + let sources_root = sources_root.as_ref(); + let (max_app, max_branch) = longest_app_branch(sources_root)?; - let progress = MultiProgress::new(); - let pull_style = ProgressStyle::with_template("{spinner:.green} {msg}").unwrap(); + for app_dir in find_app_repos(sources_root)? { + let app_name = app_dir.file_name().unwrap().to_string_lossy(); + let repo = Repository::init(&app_dir) + .into_diagnostic() + .wrap_err_with(|| format!("Failed to open repository {}", app_dir.display()))?; + let branch_name = current_branch_name(&repo).unwrap_or("unknown".into()); - let pool = ThreadPoolBuilder::new() - .num_threads(8) - .build() - .into_diagnostic()?; - let repos = find_app_repos(config)?.collect::>(); + print!( + "{app_name: output, - Err(error) => { - bar.set_message(msg(&format!(" ⨯ {error}"))); - return; - } - }; - - if output.status.success() { - bar.set_message(msg(" ✓")); - } else { - let err = String::from_utf8_lossy(&output.stderr); - let err_line = err.lines().next().unwrap(); - bar.set_message(msg(&format!(" ⨯ {err_line}"))); - } - bar.finish(); - }); - }); + let output = Command::new(GIT_BINARY) + .arg("pull") + .current_dir(&app_dir) + .output() + .into_diagnostic() + .wrap_err_with(|| format!("Failed to run git pull for {}", app_dir.display()))?; + if output.status.success() { + println!(" ✓"); + } else { + println!(" ❌"); + eprintln!("{}", String::from_utf8_lossy(&output.stderr)) + } + } Ok(()) } diff --git a/src/help.rs b/src/help.rs index 97af8c8..f868bd6 100644 --- a/src/help.rs +++ b/src/help.rs @@ -88,7 +88,6 @@ fn subcommand_help(command: &dyn SubCommand) { print!(" {}", "[php version]".green()); print!(" {}", "[database type]".green()); print!(" {}", "[services]".green()); - print!(" {}", "[vX.Y.Z]".green()); } let args = if let Some(args) = command.get_str("Args") { diff --git a/src/image.rs b/src/image.rs index e24abfd..2ea9b7d 100644 --- a/src/image.rs +++ b/src/image.rs @@ -1,52 +1,17 @@ +use bollard::image::CreateImageOptions; use bollard::models::CreateImageInfo; -use bollard::query_parameters::CreateImageOptions; use bollard::Docker; use futures_util::StreamExt; -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use miette::{IntoDiagnostic, Result, WrapErr}; use std::collections::HashMap; -use std::fmt::{Display, Formatter}; -use std::str::FromStr; - -#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)] -pub struct ImageVersion { - pub major: u8, - pub minor: u8, - pub patch: u8, -} - -impl FromStr for ImageVersion { - type Err = (); - - fn from_str(s: &str) -> std::result::Result { - let mut parts = s.split('.'); - let major = parts.next().ok_or(())?.parse().map_err(|_| ())?; - let minor = parts.next().ok_or(())?.parse().map_err(|_| ())?; - let patch = parts.next().ok_or(())?.parse().map_err(|_| ())?; - Ok(ImageVersion { - major, - minor, - patch, - }) - } -} - -impl Display for ImageVersion { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}.{}.{}", self.major, self.minor, self.patch) - } -} +use std::io::stdout; +use std::io::Write; +use termion::cursor; pub async fn image_exists(docker: &Docker, image: &str) -> bool { docker.inspect_image(image).await.is_ok() } -pub async fn image_version(docker: &Docker, image: &str) -> Option { - let labels = docker.inspect_image(image).await.ok()?.config?.labels?; - let label = labels.get("nl.icewind.haze.version")?; - ImageVersion::from_str(label).ok() -} - pub async fn update_image(docker: &Docker, image: &str) -> Result<()> { if image_exists(docker, image).await { force_pull_image(docker, image).await?; @@ -67,9 +32,9 @@ pub async fn force_pull_image(docker: &Docker, image: &str) -> Result<()> { let mut info_stream = docker.create_image( Some(CreateImageOptions { from_image: if image.contains(':') { - Some(image.to_string()) + image.to_string() } else { - Some(format!("{}:latest", image)) + format!("{}:latest", image) }, ..Default::default() }), @@ -77,33 +42,35 @@ pub async fn force_pull_image(docker: &Docker, image: &str) -> Result<()> { None, ); - let bar_style = ProgressStyle::with_template( - "{spinner:.green} {msg} [{elapsed_precise}] [{bar:.cyan/blue}] {bytes:>12}/{total_bytes}", - ) - .unwrap(); - let mut bars: HashMap = HashMap::new(); - let mp = MultiProgress::new(); + let mut bars: HashMap = HashMap::new(); + let mut stdout = stdout(); while let Some(info) = info_stream.next().await { let info: CreateImageInfo = info .into_diagnostic() .wrap_err_with(|| format!("Error while pulling image {}", image))?; - if let (Some(id), Some(status), Some(progress)) = - (info.id, info.status, info.progress_detail) - { - let bar = bars.entry(id.clone()).or_insert_with(|| { - let bar = ProgressBar::new(progress.total.unwrap_or_default() as u64) - .with_style(bar_style.clone()) - .with_message(format!("{id:20} - {status:10}")); - mp.add(bar) - }); - bar.set_message(format!("{id:10} - {status:20}")); - if let Some(total) = progress.total { - bar.set_length(total as u64); - } - if let Some(current) = progress.current { - bar.set_position(current as u64); + if let (Some(id), Some(status), Some(progress)) = (info.id, info.status, info.progress) { + match bars.get(&id) { + Some(pos) => { + let offset = bars.len() as u16 - pos; + write!( + stdout, + "{}{}{} - {:12} {}{}", + cursor::Save, + cursor::Up(offset), + id, + status, + progress, + cursor::Restore + ) + .into_diagnostic()?; + } + None => { + writeln!(stdout, "{} - {:12} {}", id, status, progress).into_diagnostic()?; + bars.insert(id, bars.len() as u16); + } } + stdout.flush().into_diagnostic()?; } } Ok(()) diff --git a/src/main.rs b/src/main.rs index d999b7c..091afd0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -103,18 +103,13 @@ async fn main() -> Result { services.push(cloud.db().name()); let services = services.join(", "); let pin = if cloud.pinned { "*" } else { "" }; - let version = match cloud.options.version.as_ref() { - Some(version) => format!(", v{version}"), - None => String::new(), - }; println!( - "Cloud {}{}, {}, {}{}, running on {}", + "Cloud {}{}, {}, {}, running on {}", cloud.id, pin, cloud.php().name(), services, - version, - cloud.address, + cloud.address ); } } @@ -148,9 +143,6 @@ async fn main() -> Result { root, } => { let cloud = Cloud::get_by_filter(&docker, filter, &config).await?; - let env = get_forward_env(); - let tty = atty::is(atty::Stream::Stdout); - match service { None => { let command = if command.is_empty() { @@ -158,7 +150,8 @@ async fn main() -> Result { } else { command }; - + let env = get_forward_env(); + let tty = atty::is(atty::Stream::Stdout); let user = if root { "root" } else { "haze" }; if tty { exec_tty(&docker, &cloud.id, user, command, env).await?; @@ -167,42 +160,19 @@ async fn main() -> Result { } } Some(ExecService::Db) => { - let command = if command.is_empty() { - vec!["bash".to_string()] - } else { - command - }; - - cloud.db().exec_sh(&docker, &cloud.id, command, tty).await?; - } - Some(ExecService::Service(service)) => { - let Some(container) = service.container_name(&cloud.id) else { - eprintln!( - "Service {} can't be exec'ed as it has no associated container", - service.name() - ); - return Ok(ExitCode::FAILURE); - }; - if service.exec_shell() == "" && command.is_empty() { - eprintln!( - "Service {} can't be exec'ed as it has no shell", - service.name() - ); - return Ok(ExitCode::FAILURE); - } - - let command = if command.is_empty() { - vec![service.exec_shell().to_string()] - } else { - command - }; - - let user = if root { "root" } else { service.exec_user() }; - if tty { - exec_tty(&docker, &container, user, command, env).await?; - } else { - exec(&docker, &container, user, command, env, Some(stdout())).await?; - } + cloud + .db() + .exec_sh( + &docker, + &cloud.id, + if command.is_empty() { + vec!["bash".to_string()] + } else { + command + }, + atty::is(atty::Stream::Stdout), + ) + .await?; } } } @@ -299,8 +269,26 @@ async fn main() -> Result { return Ok(result.into()); } HazeArgs::Integration { options, mut args } => { - let cloud = setup(&docker, options, &config).await?; - + let cloud = Cloud::create(&docker, options, &config).await?; + println!("Waiting for servers to start"); + cloud.wait_for_start(&docker).await?; + println!("Installing"); + if let Err(e) = cloud + .exec( + &docker, + vec![ + "install", + &config.auto_setup.username, + &config.auto_setup.password, + ], + false, + Vec::::default(), + ) + .await + { + cloud.destroy(&docker).await?; + return Err(e); + } args.insert(0, "integration".to_string()); cloud.exec(&docker, args, false, get_forward_env()).await?; cloud.destroy(&docker).await?; @@ -398,16 +386,15 @@ async fn main() -> Result { proxy(docker, config).await?; } HazeArgs::Git { operation } => match operation { - GitOperation::Checkout { branch, verbose } => { + GitOperation::Checkout { branch } => { let sources = Sources::new(&config.sources_root)?; checkout_all( - &config, + &config.sources_root, &branch.unwrap_or_else(|| sources.get_server_version_branch()), - verbose, )?; } GitOperation::Pull => { - pull_all(&config)?; + pull_all(&config.sources_root)?; } }, HazeArgs::Env { @@ -446,16 +433,16 @@ async fn main() -> Result { ); if cloud.services().contains(&Service::RedisTls(RedisTls)) { - create_dir_all(config.work_dir.join("certificates/redis")) + create_dir_all(config.work_dir.join("redis_certificates")) .into_diagnostic() .wrap_err("Failed to create redis certificate directory")?; - let redis_cert_path = config.work_dir.join("certificates/redis/client.cert"); - let redis_key_path = config.work_dir.join("certificates/redis/client.key"); - let redis_ca_path = config.work_dir.join("certificates/redis/ca.cert"); + let redis_cert_path = config.work_dir.join("redis_certificates/client.cert"); + let redis_key_path = config.work_dir.join("redis_certificates/client.key"); + let redis_ca_path = config.work_dir.join("redis_certificates/ca.cert"); if !redis_cert_path.exists() { write( &redis_cert_path, - include_bytes!("../certificates/redis/client.crt"), + include_bytes!("../redis-certificates/client.crt"), ) .into_diagnostic() .wrap_err("Failed to write redis client certificate")?; @@ -463,7 +450,7 @@ async fn main() -> Result { if !redis_key_path.exists() { write( &redis_key_path, - include_bytes!("../certificates/redis/client.key"), + include_bytes!("../redis-certificates/client.key"), ) .into_diagnostic() .wrap_err("Failed to write redis client key")?; @@ -471,7 +458,7 @@ async fn main() -> Result { if !redis_ca_path.exists() { write( &redis_ca_path, - include_bytes!("../certificates/redis/ca.crt"), + include_bytes!("../redis-certificates/ca.crt"), ) .into_diagnostic() .wrap_err("Failed to write redis ca certificate")?; @@ -658,7 +645,12 @@ async fn setup(docker: &Docker, options: CloudOptions, config: &HazeConfig) -> R for service in cloud.services() { for cmd in service.post_setup(docker, &cloud.id, config).await? { cloud - .exec(docker, cmd, false, Vec::::default()) + .exec( + docker, + shell_words::split(&cmd).into_diagnostic()?, + false, + Vec::::default(), + ) .await?; } } diff --git a/src/mapping.rs b/src/mapping.rs index 9c01da0..f2a93a3 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -1,14 +1,13 @@ use crate::config::{HazeConfig, HazeVolumeConfig}; use camino::{Utf8Path, Utf8PathBuf}; use miette::{IntoDiagnostic, Result}; -use std::borrow::Cow; use tokio::fs::{create_dir_all, write}; #[derive(Debug)] pub struct Mapping<'a> { source_type: MappingSourceType, - pub source: Cow<'a, Utf8Path>, - pub target: Cow<'a, Utf8Path>, + pub source: &'a Utf8Path, + pub target: &'a Utf8Path, mapping_type: MappingType, read_only: bool, map: bool, @@ -24,26 +23,6 @@ impl<'a> Mapping<'a> { where Target: Into<&'a Utf8Path>, Source: Into<&'a Utf8Path>, - { - Mapping { - source_type, - source: Cow::Borrowed(source.into()), - target: Cow::Borrowed(target.into()), - mapping_type: MappingType::Folder, - read_only: false, - map: true, - create: true, - } - } - - pub fn owned( - source_type: MappingSourceType, - source: Source, - target: Target, - ) -> Self - where - Target: Into>, - Source: Into>, { Mapping { source_type, @@ -86,10 +65,10 @@ impl<'a> Mapping<'a> { return Ok(()); } let source = match self.source_type { - MappingSourceType::WorkDir => config.work_dir.join(id).join(self.source.as_ref()), - MappingSourceType::GlobalWorkDir => config.work_dir.join(self.source.as_ref()), + MappingSourceType::WorkDir => config.work_dir.join(id).join(self.source), + MappingSourceType::GlobalWorkDir => config.work_dir.join(self.source), MappingSourceType::Sources => return Ok(()), - MappingSourceType::Absolute => self.source.as_ref().into(), + MappingSourceType::Absolute => self.source.into(), }; match self.mapping_type { MappingType::Folder => create_dir_all(source).await.into_diagnostic()?, @@ -99,25 +78,20 @@ impl<'a> Mapping<'a> { Ok(()) } - pub fn source(&self, id: &str, config: &HazeConfig, source_root: &Utf8Path) -> Utf8PathBuf { + pub fn source(&self, id: &str, config: &HazeConfig) -> Utf8PathBuf { match self.source_type { - MappingSourceType::WorkDir => config.work_dir.join(id).join(self.source.as_ref()), - MappingSourceType::GlobalWorkDir => config.work_dir.join(self.source.as_ref()), - MappingSourceType::Sources => source_root.join(self.source.as_ref()), - MappingSourceType::Absolute => self.source.as_ref().into(), + MappingSourceType::WorkDir => config.work_dir.join(id).join(self.source), + MappingSourceType::GlobalWorkDir => config.work_dir.join(self.source), + MappingSourceType::Sources => config.sources_root.join(self.source), + MappingSourceType::Absolute => self.source.into(), } } - pub fn get_volume_arg( - &self, - id: &str, - config: &HazeConfig, - source_root: &Utf8Path, - ) -> Option { + pub fn get_volume_arg(&self, id: &str, config: &HazeConfig) -> Option { if !self.map { return None; } - let source = self.source(id, config, source_root); + let source = self.source(id, config); Some(if self.read_only { format!("{}:{}:ro", source, self.target) } else { @@ -133,7 +107,6 @@ pub fn default_mappings<'a>() -> impl IntoIterator> { Mapping::new(Sources, "", "/var/www/html"), Mapping::new(WorkDir, "data", "/var/www/html/data"), Mapping::new(WorkDir, "config", "/var/www/html/config"), - Mapping::new(WorkDir, "store_apps", "/var/www/store_apps"), Mapping::new(WorkDir, "data-autotest", "/var/www/html/data-autotest"), Mapping::new(WorkDir, "skeleton", "/var/www/html/core/skeleton"), Mapping::new( @@ -188,32 +161,11 @@ pub fn default_mappings<'a>() -> impl IntoIterator> { .dont_create(), Mapping::new(WorkDir, "xdebug", "/tmp/xdebug"), Mapping::new(WorkDir, "profiling", "/tmp/profiling"), - Mapping::new(WorkDir, "php-config", "/config"), + Mapping::new(WorkDir, "php.ini", "/php.ini").file(), ]; - IntoIterator::into_iter(mappings) } -pub fn for_config<'a>(config: &'a HazeConfig) -> impl Iterator> { - let app_dir_mappings = config.app_directories.iter().map(|dir| { - Mapping::owned( - MappingSourceType::Absolute, - dir.as_path(), - Cow::Owned(Utf8PathBuf::from(format!( - "/var/www/html/{}", - dir.file_name().unwrap() - ))), - ) - }); - - config - .volume - .iter() - .map(Mapping::from) - .chain(app_dir_mappings) - .chain(default_mappings()) -} - #[derive(Debug, Copy, Clone)] pub enum MappingSourceType { Sources, @@ -237,8 +189,8 @@ impl<'a> From<&'a HazeVolumeConfig> for Mapping<'a> { }; Mapping { source_type: MappingSourceType::Absolute, - source: Cow::Borrowed(config.source.as_path()), - target: Cow::Borrowed(config.target.as_path()), + source: config.source.as_path(), + target: config.target.as_path(), mapping_type: ty, read_only: config.read_only, map: true, diff --git a/src/network.rs b/src/network.rs index 0b25f2c..ea589ec 100644 --- a/src/network.rs +++ b/src/network.rs @@ -1,11 +1,11 @@ use crate::cloud::Cloud; -use bollard::config::NetworkCreateRequest; +use bollard::network::CreateNetworkOptions; use bollard::Docker; use miette::{IntoDiagnostic, Result, WrapErr}; pub async fn clear_networks(docker: &Docker, instances: &[Cloud]) -> Result<()> { let networks = docker - .list_networks(None) + .list_networks::<&str>(None) .await .into_diagnostic() .wrap_err("Failed to list docker networks")?; @@ -23,7 +23,7 @@ pub async fn clear_networks(docker: &Docker, instances: &[Cloud]) -> Result<()> async fn get_network_id(docker: &Docker, name: &str) -> Result> { let networks = docker - .list_networks(None) + .list_networks::<&str>(None) .await .into_diagnostic() .wrap_err("Failed to list docker networks")?; @@ -41,8 +41,9 @@ pub async fn ensure_network_exists(docker: &Docker, name: &str) -> Result Result { match s { - "8" => Ok(PhpVersion::Php80), + "7" => Ok(PhpVersion::Php74), + "7.3" => Ok(PhpVersion::Php73), + "7.4" => Ok(PhpVersion::Php74), + "8" => Ok(PhpVersion::Php81), "8.0" => Ok(PhpVersion::Php80), "8.1" => Ok(PhpVersion::Php81), "8.2" => Ok(PhpVersion::Php82), "8.3" => Ok(PhpVersion::Php83), "8.4" => Ok(PhpVersion::Php84), - "8.5" => Ok(PhpVersion::Php85), + "7-dbg" => Ok(PhpVersion::Php74Dbg), + "7.3-dbg" => Ok(PhpVersion::Php73Dbg), + "7.4-dbg" => Ok(PhpVersion::Php74Dbg), + "8-dbg" => Ok(PhpVersion::Php80Dbg), + "8.0-dbg" => Ok(PhpVersion::Php80Dbg), + "8.1-dbg" => Ok(PhpVersion::Php81Dbg), + "8.2-dbg" => Ok(PhpVersion::Php82Dbg), + "8.3-dbg" => Ok(PhpVersion::Php83Dbg), + "8.4-dbg" => Ok(PhpVersion::Php84Dbg), _ => Err(()), } } @@ -55,35 +73,53 @@ impl PhpVersion { } pub fn image(&self) -> &'static str { + // for now only 7.4 match self { + PhpVersion::Php73 => "icewind1991/haze:7.3", + PhpVersion::Php74 => "icewind1991/haze:7.4", PhpVersion::Php80 => "icewind1991/haze:8.0", PhpVersion::Php81 => "icewind1991/haze:8.1", PhpVersion::Php82 => "icewind1991/haze:8.2", PhpVersion::Php83 => "icewind1991/haze:8.3", PhpVersion::Php84 => "icewind1991/haze:8.4", - PhpVersion::Php85 => "icewind1991/haze:8.5", + PhpVersion::Php73Dbg => "icewind1991/haze:7.3-dbg", + PhpVersion::Php74Dbg => "icewind1991/haze:7.4-dbg", + PhpVersion::Php80Dbg => "icewind1991/haze:8.0-dbg", + PhpVersion::Php81Dbg => "icewind1991/haze:8.1-dbg", + PhpVersion::Php82Dbg => "icewind1991/haze:8.2-dbg", + PhpVersion::Php83Dbg => "icewind1991/haze:8.3-dbg", + PhpVersion::Php84Dbg => "icewind1991/haze:8.4-dbg", } } pub fn name(&self) -> &'static str { match self { + PhpVersion::Php73 => "7.3", + PhpVersion::Php74 => "7.4", PhpVersion::Php80 => "8.0", PhpVersion::Php81 => "8.1", PhpVersion::Php82 => "8.2", PhpVersion::Php83 => "8.3", PhpVersion::Php84 => "8.4", - PhpVersion::Php85 => "8.4", + PhpVersion::Php73Dbg => "7.3-dbg", + PhpVersion::Php74Dbg => "7.4-dbg", + PhpVersion::Php80Dbg => "8.0-dbg", + PhpVersion::Php81Dbg => "8.1-dbg", + PhpVersion::Php82Dbg => "8.2-dbg", + PhpVersion::Php83Dbg => "8.3-dbg", + PhpVersion::Php84Dbg => "8.4-dbg", } } pub fn from_number(major: u8, minor: u8) -> Option { match (major, minor) { + (7, 3) => Some(PhpVersion::Php73), + (7, 4) => Some(PhpVersion::Php74), (8, 0) => Some(PhpVersion::Php80), (8, 1) => Some(PhpVersion::Php81), (8, 2) => Some(PhpVersion::Php82), (8, 3) => Some(PhpVersion::Php83), (8, 4) => Some(PhpVersion::Php84), - (8, 5) => Some(PhpVersion::Php85), _ => None, } } @@ -91,19 +127,27 @@ impl PhpVersion { pub fn max_minor(major: u8) -> u8 { match major { 7 => 4, - 8 => 5, + 8 => 4, _ => 0, } } pub fn all() -> impl Iterator { [ + PhpVersion::Php73, + PhpVersion::Php74, PhpVersion::Php80, PhpVersion::Php81, PhpVersion::Php82, PhpVersion::Php83, PhpVersion::Php84, - PhpVersion::Php85, + PhpVersion::Php73Dbg, + PhpVersion::Php74Dbg, + PhpVersion::Php80Dbg, + PhpVersion::Php81Dbg, + PhpVersion::Php82Dbg, + PhpVersion::Php83Dbg, + PhpVersion::Php84Dbg, ] .into_iter() } @@ -120,23 +164,11 @@ impl PhpVersion { host: &str, services: &[Service], proxy_config: &ProxyConfig, - version: Option<&str>, ) -> Result { ensure_network_exists(docker, "haze").await?; pull_image(docker, self.image()).await?; - - let image_version = image_version(docker, self.image()).await; - let haze_version = ImageVersion::from_str(env!("CARGO_PKG_VERSION")); - if let (Some(image_version), Ok(haze_version)) = (image_version, haze_version) { - if image_version < haze_version { - eprintln!("{}: image version is out of date, run {} to update.", "Warning".red(), "haze update".blue()); - eprintln!(" Haze version: {}", haze_version.bright_yellow()); - eprintln!(" Image version: {}", image_version.bright_yellow()); - } - } - let options = Some(CreateContainerOptions { - name: Some(id.to_string()), + name: id.to_string(), ..CreateContainerOptions::default() }); let clean_id = id.strip_prefix("haze-").unwrap_or(id); @@ -160,23 +192,7 @@ impl PhpVersion { proxy_config.addr(id, IpAddr::V4(Ipv4Addr::LOCALHOST)) )); - env.push(format!("HOST_IP={host}")); - if !proxy_config.address.is_empty() { - env.push(format!("PROXY_BASE={}", proxy_config.address)); - } - - let mut labels = hashmap! { - "haze-type".to_string() => "cloud".to_string(), - "haze-db".to_string() => db.name().to_string(), - "haze-php".to_string() => self.name().to_string(), - "haze-cloud-id".to_string() => id.to_string(), - "haze-services".to_string() => services.iter().map(|s| s.name()).join(","), - }; - if let Some(version) = version { - labels.insert("haze-version".to_string(), version.to_string()); - } - - let config = ContainerCreateBody { + let config = Config { image: Some(self.image().to_string()), env: Some(env), host_config: Some(HostConfig { @@ -188,14 +204,20 @@ impl PhpVersion { ..Default::default() }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { + endpoints_config: hashmap! { network.to_string() => EndpointSettings { aliases: Some(vec!["cloud".to_string()]), ..Default::default() } - }), + }, + }), + labels: Some(hashmap! { + "haze-type".to_string() => "cloud".to_string(), + "haze-db".to_string() => db.name().to_string(), + "haze-php".to_string() => self.name().to_string(), + "haze-cloud-id".to_string() => id.to_string(), + "haze-services".to_string() => services.iter().map(|s| s.name()).join(","), }), - labels: Some(labels), ..Default::default() }; @@ -205,7 +227,11 @@ impl PhpVersion { .into_diagnostic()? .id; - if let Err(e) = docker.start_container(&id, None).await.into_diagnostic() { + if let Err(e) = docker + .start_container::(&id, None) + .await + .into_diagnostic() + { docker.remove_container(&id, None).await.ok(); return Err(e); } @@ -213,12 +239,12 @@ impl PhpVersion { if let Err(e) = docker .connect_network( "haze", - NetworkConnectRequest { - container: id.to_string(), - endpoint_config: Some(EndpointSettings { + ConnectNetworkOptions { + container: id.as_str(), + endpoint_config: EndpointSettings { aliases: Some(vec![id.to_string()]), ..Default::default() - }), + }, }, ) .await diff --git a/src/proxy.rs b/src/proxy.rs index 4784a18..ee867c9 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -1,43 +1,34 @@ -use crate::service::{ServiceTrait, ServiceType}; +use crate::service::ServiceTrait; use crate::Result; use crate::{Cloud, HazeConfig}; use axum::http::header::HOST; use axum::http::HeaderValue; use axum::{ body::Body, - extract::Request, + extract::{Request, State}, response::{IntoResponse, Response}, + Router, }; use bollard::Docker; -use futures_util::StreamExt; -use hyper::body::Incoming; -use hyper::server::conn::http1; -use hyper::service::service_fn; use hyper::StatusCode; -use hyper_util::rt::TokioIo; use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor}; use miette::{miette, IntoDiagnostic}; use std::collections::HashMap; -use std::convert::Infallible; use std::fs::{create_dir_all, set_permissions}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; -use std::pin::pin; -use std::str::FromStr; use std::sync::{Arc, Mutex}; use std::time::Duration; -use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::UnixListener; use tokio::signal::ctrl_c; use tokio::spawn; use tokio::time::sleep; -use tokio_stream::wrappers::{TcpListenerStream, UnixListenerStream}; use tracing::{debug, error, info}; struct ActiveInstances { known: Mutex>, - last: Mutex>, + last: Mutex>, docker: Docker, config: HazeConfig, } @@ -57,9 +48,15 @@ impl ActiveInstances { return Some(ip); } - let addr = if ServiceType::from_str(name).is_ok() { - let cloud = self.last()?; - let service = cloud.services().find(|service| service.name() == name)?; + // service proxy + let addr = if name.matches('-').count() == 2 { + let (name, service_name) = name.rsplit_once('-').unwrap(); + let cloud = Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config) + .await + .ok()?; + let service = cloud + .services() + .find(|service| service.name() == service_name)?; let ip = service .get_ips(&self.docker, &cloud.id) .await @@ -67,34 +64,13 @@ impl ActiveInstances { .next()?; SocketAddr::new(ip, service.proxy_port()) } else { - match name.matches('-').count() { - // instance - 1 => SocketAddr::new( - Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config) - .await - .ok()? - .ip?, - 80, - ), - // service with instance - 2.. => { - let service_name = name.splitn(3, '-').last()?; - let name = &name[0..(name.len() - service_name.len() - 1)]; - let cloud = Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config) - .await - .ok()?; - let service = cloud - .services() - .find(|service| service.name() == service_name)?; - let ip = service - .get_ips(&self.docker, &cloud.id) - .await - .ok()? - .next()?; - SocketAddr::new(ip, service.proxy_port()) - } - _ => return None, - } + SocketAddr::new( + Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config) + .await + .ok()? + .ip?, + 80, + ) }; println!("{name} => {addr}"); @@ -103,31 +79,18 @@ impl ActiveInstances { Some(addr) } - pub fn last_addr(&self) -> Option { - self.last - .lock() - .unwrap() - .as_ref() - .and_then(|cloud| Some(SocketAddr::new(cloud.ip?, 80))) - } - - pub fn last(&self) -> Option { - self.last.lock().unwrap().clone() + pub fn last(&self) -> Option { + *self.last.lock().unwrap() } async fn update_last(&self) { let last = Cloud::get_by_filter(&self.docker, None, &self.config) .await - .ok(); + .ok() + .and_then(|cloud| Some(SocketAddr::new(cloud.ip?, 80))); let mut old = self.last.lock().unwrap(); if old.as_ref() != last.as_ref() { info!(instance = ?last, "Found new instance"); - - // remove cached base-service mappings - self.known - .lock() - .unwrap() - .retain(|key, _| ServiceType::from_str(key).is_err()); *old = last; } } @@ -171,26 +134,20 @@ async fn serve(instances: ActiveInstances, listen: String, base_address: String) ctrl_c().await.ok(); }; - let state = AppState { + let app = Router::new().fallback(handler).with_state(AppState { instances: instances.clone(), base_address: base_address.clone(), proxy_client: Arc::new(proxy_client), - }; + }); if !listen.starts_with('/') { let addr: SocketAddr = listen.parse().into_diagnostic()?; let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); println!("listening on {}", listener.local_addr().unwrap()); - let mut connections = pin!(TcpListenerStream::new(listener).take_until(cancel)); - - while let Some(stream) = connections.next().await { - match stream { - Ok(stream) => handle_connection(state.clone(), stream), - Err(error) => { - error!(%error, "connection failed"); - } - } - } + axum::serve(listener, app) + .with_graceful_shutdown(cancel) + .await + .unwrap(); } else { let listen: PathBuf = listen.into(); if let Some(parent) = listen.parent() { @@ -201,42 +158,18 @@ async fn serve(instances: ActiveInstances, listen: String, base_address: String) } let _ = tokio::fs::remove_file(&listen).await; - let listener = UnixListener::bind(&listen).unwrap(); - println!("listening on {}", listen.display()); + let uds = UnixListener::bind(&listen).unwrap(); set_permissions(&listen, PermissionsExt::from_mode(0o666)).into_diagnostic()?; - let mut connections = pin!(UnixListenerStream::new(listener).take_until(cancel)); - - while let Some(stream) = connections.next().await { - match stream { - Ok(stream) => handle_connection(state.clone(), stream), - Err(error) => { - error!(%error, "connection failed"); - } - } - } + axum::serve(uds, app) + .with_graceful_shutdown(cancel) + .await + .unwrap(); } Ok(()) } -fn handle_connection( - state: AppState, - stream: I, -) { - let io = TokioIo::new(stream); - // Spawn a tokio task to serve multiple connections concurrently - tokio::task::spawn(async move { - if let Err(err) = http1::Builder::new() - .serve_connection(io, service_fn(move |req| handler(state.clone(), req))) - .with_upgrades() - .await - { - eprintln!("Error serving connection: {:?}", err); - } - }); -} - async fn get_remote( host: Option<&HeaderValue>, instances: &ActiveInstances, @@ -248,7 +181,7 @@ async fn get_remote( }; let ip = if host == base_address { instances - .last_addr() + .last() .ok_or_else(|| String::from("No running instance known")) } else { let requested_instance = host.split('.').next().unwrap(); @@ -270,9 +203,9 @@ async fn get_remote( } } -type Client = hyper_util::client::legacy::Client; +type Client = hyper_util::client::legacy::Client; -async fn handler(state: AppState, mut req: Request) -> Result { +async fn handler(State(state): State, mut req: Request) -> Result { let host = req.headers().get(HOST).cloned(); let remote = match get_remote(host.as_ref(), &state.instances, &state.base_address).await { Ok(remote) => remote, @@ -297,13 +230,13 @@ async fn handler(state: AppState, mut req: Request) -> Result Ok(response.map(Body::new)), Err(error) => { - error!(?error, "error while proxying request"); + error!(%error, "error while proxying request"); Ok(StatusCode::BAD_REQUEST.into_response()) } } diff --git a/src/service.rs b/src/service.rs index c514449..62b84d4 100644 --- a/src/service.rs +++ b/src/service.rs @@ -14,10 +14,9 @@ mod sftp; mod redis; mod sharded; mod smb; -mod webhook; use crate::cloud::CloudOptions; -use crate::config::{HazeConfig, Preset, ProxyConfig}; +use crate::config::{HazeConfig, Preset}; pub use crate::service::clam::{Clam, ClamIcap, ClamIcapTls, ClamSocket}; use crate::service::dav::Dav; use crate::service::imaginary::Imaginary; @@ -30,10 +29,9 @@ pub use crate::service::office::Office; pub use crate::service::onlyoffice::OnlyOffice; pub use crate::service::push::NotifyPush; use crate::service::redis::Redis; -use crate::service::sftp::{Sftp, SftpKey}; +use crate::service::sftp::Sftp; use crate::service::sharded::{Sharding, ShardingMigrate, ShardingMigrateUnset, SingleShard}; use crate::service::smb::Smb; -use crate::service::webhook::Webhook; use bollard::models::ContainerState; use bollard::Docker; use enum_dispatch::enum_dispatch; @@ -80,12 +78,7 @@ pub trait ServiceTrait { None } - async fn start_message( - &self, - _docker: &Docker, - _cloud_id: &str, - _proxy: &ProxyConfig, - ) -> Result> { + async fn start_message(&self, _docker: &Docker, _cloud_id: &str) -> Result> { Ok(None) } @@ -102,21 +95,12 @@ pub trait ServiceTrait { Ok(HashMap::default()) } - fn pre_setup( - &self, - _docker: &Docker, - _cloud_id: &str, - _config: &HazeConfig, - ) -> Result>> { - Ok(Vec::new()) - } - async fn post_setup( &self, _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(Vec::new()) } @@ -158,7 +142,7 @@ pub trait ServiceTrait { return Ok(Box::new(empty())); }; docker - .start_container(&container, None) + .start_container::(&container, None) .await .into_diagnostic()?; self.wait_for_running(docker, cloud_id).await?; @@ -194,14 +178,6 @@ pub trait ServiceTrait { fn proxy_port(&self) -> u16 { 80 } - - fn exec_user(&self) -> &'static str { - "root" - } - - fn exec_shell(&self) -> &'static str { - "bash" - } } #[derive(Clone, Eq, PartialEq, Debug)] @@ -217,19 +193,6 @@ impl ServiceTrait for RedisTls { } } -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct FrankenPhp; - -impl ServiceTrait for FrankenPhp { - fn name(&self) -> &str { - "franken-php" - } - - fn env(&self) -> &[&str] { - &["FRANKENPHP=1"] - } -} - #[derive( Copy, Clone, Debug, PartialEq, EnumString, EnumMessage, EnumIter, IntoStaticStr, Display, )] @@ -237,8 +200,6 @@ impl ServiceTrait for FrankenPhp { pub enum ServiceType { /// S3 Primary storage and external storage S3, - /// S3 Primary storage with TLS - S3s, /// S3 multi-object store Primary storage and external storage S3m, /// S3 multi-bucket Primary storage and external storage @@ -247,10 +208,7 @@ pub enum ServiceType { Azure, /// Ldap user backend Ldap, - /// Ldap admin interface - LdapAdmin, /// OnlyOffice - #[strum(serialize = "onlyoffice", serialize = "only-office")] OnlyOffice, /// Libre office online Office, @@ -276,8 +234,6 @@ pub enum ServiceType { Dav, /// Sftp external storage Sftp, - /// Sftp external storage with public key authentication - SftpKey, /// ownCloud instance for migration Oc, /// Imaginary for preview generation @@ -307,10 +263,6 @@ pub enum ServiceType { Redis, /// External redis instance with TLS RedisTls, - /// Use FrankenPHP instead of PHP-FPM - FrankenPhp, - /// Webhook test listener - Webhook, } #[enum_dispatch] @@ -329,7 +281,6 @@ pub enum Service { ShardingMigrate(ShardingMigrate), ShardingMigrateUnset(ShardingMigrateUnset), Sftp(Sftp), - SftpKey(SftpKey), Kaspersky(Kaspersky), KasperskyIcap(KasperskyIcap), Clam(Clam), @@ -341,8 +292,6 @@ pub enum Service { Mail(Mail), Redis(Redis), RedisTls(RedisTls), - FrankenPhp(FrankenPhp), - Webhook(Webhook), Preset(PresetService), } @@ -351,14 +300,10 @@ impl Service { if let Ok(ty) = ServiceType::from_str(ty) { match ty { ServiceType::S3 => Some(vec![Service::ObjectStore(ObjectStore::S3)]), - ServiceType::S3s => Some(vec![Service::ObjectStore(ObjectStore::S3s)]), ServiceType::S3m => Some(vec![Service::ObjectStore(ObjectStore::S3m)]), ServiceType::S3mb => Some(vec![Service::ObjectStore(ObjectStore::S3mb)]), ServiceType::Azure => Some(vec![Service::ObjectStore(ObjectStore::Azure)]), ServiceType::Ldap => Some(vec![Service::Ldap(Ldap), Service::LdapAdmin(LdapAdmin)]), - ServiceType::LdapAdmin => { - Some(vec![Service::Ldap(Ldap), Service::LdapAdmin(LdapAdmin)]) - } ServiceType::OnlyOffice => Some(vec![Service::OnlyOffice(OnlyOffice)]), ServiceType::Office => Some(vec![Service::Office(Office)]), ServiceType::Push => Some(vec![Service::Push(NotifyPush)]), @@ -373,7 +318,6 @@ impl Service { } ServiceType::Dav => Some(vec![Service::Dav(Dav)]), ServiceType::Sftp => Some(vec![Service::Sftp(Sftp)]), - ServiceType::SftpKey => Some(vec![Service::SftpKey(SftpKey)]), ServiceType::Oc => Some(vec![Service::Oc(Oc)]), ServiceType::Imaginary => Some(vec![Service::Imaginary(Imaginary)]), ServiceType::Kaspersky => Some(vec![Service::Kaspersky(Kaspersky)]), @@ -386,8 +330,6 @@ impl Service { ServiceType::Mail => Some(vec![Service::Mail(Mail)]), ServiceType::Redis => Some(vec![Service::Redis(Redis)]), ServiceType::RedisTls => Some(vec![Service::RedisTls(RedisTls)]), - ServiceType::FrankenPhp => Some(vec![Service::FrankenPhp(FrankenPhp)]), - ServiceType::Webhook => Some(vec![Service::Webhook(Webhook)]), } } else { presets @@ -450,29 +392,15 @@ impl ServiceTrait for PresetService { _docker: &Docker, _cloud_id: &str, config: &HazeConfig, - ) -> Result>> { + ) -> Result> { let preset = get_preset(&config.preset, &self.0).ok_or_else(|| Report::msg("invalid preset"))?; let mut commands: Vec<_> = preset .apps .iter() - .map(|app| { - vec![ - "occ".into(), - "app:enable".into(), - app.clone(), - "--force".into(), - ] - }) + .map(|app| format!("occ app:enable {app} --force")) .collect(); - for cmnd in &preset.commands { - commands.push(shell_words::split(cmnd).into_diagnostic()?); - } - + commands.extend_from_slice(&preset.commands); Ok(commands) } } - -fn split_cmnd(s: &str) -> Vec { - s.split(' ').map(String::from).collect() -} diff --git a/src/service/clam.rs b/src/service/clam.rs index 7221309..924abd6 100644 --- a/src/service/clam.rs +++ b/src/service/clam.rs @@ -2,10 +2,10 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::exec::exec; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::{IntoDiagnostic, WrapErr}; @@ -40,26 +40,26 @@ impl ServiceTrait for ClamIcap { let image = "ghcr.io/icewind1991/icap-clamav-service-tls"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into() + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -68,7 +68,10 @@ impl ServiceTrait for ClamIcap { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -85,13 +88,14 @@ impl ServiceTrait for ClamIcap { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd("occ config:app:set files_antivirus av_mode --value=icap"), - split_cmnd("occ config:app:set files_antivirus av_host --value=clamav-icap"), - split_cmnd("occ config:app:set files_antivirus av_port --value=1344"), - split_cmnd("occ config:app:set files_antivirus av_icap_request_service --value=avscan"), - split_cmnd("occ config:app:set files_antivirus av_icap_response_header --value=X-Infection-Found"), + "occ config:app:set files_antivirus av_mode --value=icap".into(), + "occ config:app:set files_antivirus av_host --value=clamav-icap".into(), + "occ config:app:set files_antivirus av_port --value=1344".into(), + "occ config:app:set files_antivirus av_icap_request_service --value=avscan".into(), + "occ config:app:set files_antivirus av_icap_response_header --value=X-Infection-Found" + .into(), ]) } } @@ -125,26 +129,26 @@ impl ServiceTrait for ClamIcapTls { let image = "ghcr.io/icewind1991/icap-clamav-service-tls"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into() + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -153,7 +157,10 @@ impl ServiceTrait for ClamIcapTls { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -170,7 +177,7 @@ impl ServiceTrait for ClamIcapTls { docker: &Docker, cloud_id: &str, config: &HazeConfig, - ) -> Result>> { + ) -> Result> { let mut cert = Vec::new(); exec( docker, @@ -190,13 +197,14 @@ impl ServiceTrait for ClamIcapTls { .wrap_err("Failed to write icap certificate")?; Ok(vec![ - split_cmnd("occ config:app:set files_antivirus av_mode --value=icap"), - split_cmnd("occ config:app:set files_antivirus av_icap_tls --value=1"), - split_cmnd("occ config:app:set files_antivirus av_host --value=clamav-icap-tls"), - split_cmnd("occ config:app:set files_antivirus av_port --value=1345"), - split_cmnd("occ config:app:set files_antivirus av_icap_request_service --value=avscan"), - split_cmnd("occ config:app:set files_antivirus av_icap_response_header --value=X-Infection-Found"), - split_cmnd("occ security:certificates:import data/icap-cert.pem"), + "occ config:app:set files_antivirus av_mode --value=icap".into(), + "occ config:app:set files_antivirus av_icap_tls --value=1".into(), + "occ config:app:set files_antivirus av_host --value=clamav-icap-tls".into(), + "occ config:app:set files_antivirus av_port --value=1345".into(), + "occ config:app:set files_antivirus av_icap_request_service --value=avscan".into(), + "occ config:app:set files_antivirus av_icap_response_header --value=X-Infection-Found" + .into(), + "occ security:certificates:import data/icap-cert.pem".into(), ]) } } @@ -219,10 +227,10 @@ impl ServiceTrait for Clam { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd("occ config:app:set files_antivirus av_mode --value=executable"), - split_cmnd("occ config:app:set files_antivirus av_path --value=/bin/clamscan"), + "occ config:app:set files_antivirus av_mode --value=executable".into(), + "occ config:app:set files_antivirus av_path --value=/bin/clamscan".into(), ]) } } @@ -247,26 +255,26 @@ impl ServiceTrait for ClamSocket { let image = "clamav/clamav"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into() + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -275,7 +283,10 @@ impl ServiceTrait for ClamSocket { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -292,12 +303,10 @@ impl ServiceTrait for ClamSocket { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd("occ config:app:set files_antivirus av_mode --value=socket"), - split_cmnd( - "occ config:app:set files_antivirus av_socket --value=tcp://clamav-socket:3310", - ), + "occ config:app:set files_antivirus av_mode --value=socket".into(), + "occ config:app:set files_antivirus av_socket --value=tcp://clamav-socket:3310".into(), ]) } } diff --git a/src/service/dav.rs b/src/service/dav.rs index e0b20f3..bfd4904 100644 --- a/src/service/dav.rs +++ b/src/service/dav.rs @@ -1,11 +1,10 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::config::ContainerCreateBody; -use bollard::models::{EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::IntoDiagnostic; @@ -30,27 +29,27 @@ impl ServiceTrait for Dav { let image = "ugeek/webdav:amd64"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), - env: Some(vec!["USERNAME=test".into(), "PASSWORD=test".into()]), + env: Some(vec!["USERNAME=test", "PASSWORD=test"]), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into() + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -59,7 +58,10 @@ impl ServiceTrait for Dav { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -76,12 +78,12 @@ impl ServiceTrait for Dav { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd("occ files_external:create dav dav password::password"), - split_cmnd("occ files_external:config 1 host dav"), - split_cmnd("occ files_external:config 1 user test"), - split_cmnd("occ files_external:config 1 password test"), + "occ files_external:create dav dav password::password".into(), + "occ files_external:config 1 host dav".into(), + "occ files_external:config 1 user test".into(), + "occ files_external:config 1 password test".into(), ]) } } diff --git a/src/service/imaginary.rs b/src/service/imaginary.rs index 4ec4d96..986b242 100644 --- a/src/service/imaginary.rs +++ b/src/service/imaginary.rs @@ -1,11 +1,10 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::config::NetworkingConfig; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::IntoDiagnostic; @@ -30,26 +29,26 @@ impl ServiceTrait for Imaginary { let image = "nextcloud/aio-imaginary:latest"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into() + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -58,7 +57,10 @@ impl ServiceTrait for Imaginary { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -71,14 +73,11 @@ impl ServiceTrait for Imaginary { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd( - "occ config:system:set enabledPreviewProviders 0 --value='OC\\Preview\\Imaginary'", - ), - split_cmnd( - "occ config:system:set preview_imaginary_url --value='http://imaginary:9000'", - ), + "occ config:system:set enabledPreviewProviders 0 --value='OC\\Preview\\Imaginary'" + .into(), + "occ config:system:set preview_imaginary_url --value='http://imaginary:9000'".into(), ]) } } diff --git a/src/service/kaspersky.rs b/src/service/kaspersky.rs index 1c0a67f..8199429 100644 --- a/src/service/kaspersky.rs +++ b/src/service/kaspersky.rs @@ -2,10 +2,10 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::exec::exec; use crate::image::{image_exists, pull_image}; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::{bail, IntoDiagnostic}; @@ -38,26 +38,26 @@ impl ServiceTrait for Kaspersky { } pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into() + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -66,7 +66,10 @@ impl ServiceTrait for Kaspersky { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -101,11 +104,11 @@ impl ServiceTrait for Kaspersky { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd("occ config:app:set files_antivirus av_mode --value=kaspersky"), - split_cmnd("occ config:app:set files_antivirus av_host --value=kaspersky"), - split_cmnd("occ config:app:set files_antivirus av_port --value=80"), + "occ config:app:set files_antivirus av_mode --value=kaspersky".into(), + "occ config:app:set files_antivirus av_host --value=kaspersky".into(), + "occ config:app:set files_antivirus av_port --value=80".into(), ]) } } @@ -142,26 +145,26 @@ impl ServiceTrait for KasperskyIcap { } pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -170,7 +173,10 @@ impl ServiceTrait for KasperskyIcap { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -187,15 +193,13 @@ impl ServiceTrait for KasperskyIcap { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd("occ config:app:set files_antivirus av_mode --value=icap"), - split_cmnd("occ config:app:set files_antivirus av_host --value=kaspersky-icap"), - split_cmnd("occ config:app:set files_antivirus av_port --value=1344"), - split_cmnd("occ config:app:set files_antivirus av_icap_request_service --value=req"), - split_cmnd( - "occ config:app:set files_antivirus av_icap_response_header --value=X-Virus-ID", - ), + "occ config:app:set files_antivirus av_mode --value=icap".into(), + "occ config:app:set files_antivirus av_host --value=kaspersky-icap".into(), + "occ config:app:set files_antivirus av_port --value=1344".into(), + "occ config:app:set files_antivirus av_icap_request_service --value=req".into(), + "occ config:app:set files_antivirus av_icap_response_header --value=X-Virus-ID".into(), ]) } } diff --git a/src/service/ldap.rs b/src/service/ldap.rs index 4f317e6..4868ffe 100644 --- a/src/service/ldap.rs +++ b/src/service/ldap.rs @@ -1,16 +1,13 @@ use crate::cloud::CloudOptions; -use crate::config::{HazeConfig, ProxyConfig}; +use crate::config::HazeConfig; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::config::NetworkingConfig; -use bollard::models::{ContainerCreateBody, ContainerState, EndpointSettings, HostConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{ContainerState, EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::{IntoDiagnostic, Report}; -use std::net::IpAddr; -use std::str::FromStr; #[derive(Debug, Clone, Eq, PartialEq)] pub struct Ldap; @@ -36,29 +33,29 @@ impl ServiceTrait for Ldap { let image = "icewind1991/haze-ldap"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), - env: Some(vec!["LDAP_ADMIN_PASSWORD=haze".into()]), + let config = Config { + image: Some(image), + env: Some(vec!["LDAP_ADMIN_PASSWORD=haze"]), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into() + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), - cmd: Some(vec!["--copy-service".into()]), + cmd: Some(vec!["--copy-service"]), ..Default::default() }; let id = docker @@ -66,7 +63,10 @@ impl ServiceTrait for Ldap { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -86,46 +86,6 @@ impl ServiceTrait for Ldap { ) -> Result { self.is_running(docker, cloud_id).await } - - async fn post_setup( - &self, - _docker: &Docker, - _cloud_id: &str, - _config: &HazeConfig, - ) -> Result>> { - Ok(vec![ - split_cmnd("occ ldap:create-empty-config"), - split_cmnd("occ ldap:set-config s01 ldapHost ldap://ldap"), - split_cmnd("occ ldap:set-config s01 ldapPort 389"), - split_cmnd("occ ldap:set-config s01 ldapAgentName cn=admin,dc=example,dc=org"), - split_cmnd("occ ldap:set-config s01 ldapAgentPassword haze"), - split_cmnd("occ ldap:set-config s01 ldapBase dc=example,dc=org"), - split_cmnd("occ ldap:set-config s01 ldapBaseUsers dc=example,dc=org"), - split_cmnd("occ ldap:set-config s01 ldapBaseGroups dc=example,dc=org"), - split_cmnd("occ ldap:set-config s01 ldapLoginFilter (&(&(objectclass=inetOrgPerson))(uid=%uid))"), - split_cmnd("occ ldap:set-config s01 ldapUserFilter ((objectclass=inetOrgPerson))"), - split_cmnd("occ ldap:set-config s01 ldapUserFilterMode 0"), - split_cmnd("occ ldap:set-config s01 ldapUserDisplayName sn"), - split_cmnd("occ ldap:set-config s01 ldapUserFilterObjectclass inetOrgPerson"), - split_cmnd("occ ldap:set-config s01 ldapGroupFilter (&(|(objectclass=posixGroup)))"), - split_cmnd("occ ldap:set-config s01 ldapGroupFilterObjectclass posixGroup"), - split_cmnd("occ ldap:set-config s01 ldapEmailAttribute email"), - split_cmnd("occ ldap:set-config s01 ldapUuidUserAttribute email"), - split_cmnd("occ ldap:set-config s01 ldapUuidUserAttribute auto"), - split_cmnd("occ ldap:set-config s01 ldapUuidGroupAttribute auto"), - split_cmnd("occ ldap:set-config s01 ldapLoginFilterUsername 1"), - split_cmnd("occ ldap:set-config s01 ldapConfigurationActive 1"), - ]) - } - - async fn start_message( - &self, - _docker: &Docker, - _cloud_id: &str, - _proxy: &ProxyConfig, - ) -> Result> { - Ok(Some("\nLdap users provisioned:\n\t'cn=admin,dc=example,dc=org' and password 'haze'\n\t'cn=ldaptest,dc=example,dc=org' and password 'test'\n\nldaptest is available for login\n".into())) - } } #[derive(Debug, Clone, Eq, PartialEq)] @@ -152,32 +112,29 @@ impl ServiceTrait for LdapAdmin { let image = "osixia/phpldapadmin"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), - env: Some(vec![ - "PHPLDAPADMIN_LDAP_HOSTS=ldap".into(), - "PHPLDAPADMIN_HTTPS=false".into(), - ]), + let config = Config { + image: Some(image), + env: Some(vec!["PHPLDAPADMIN_LDAP_HOSTS=ldap"]), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), - cmd: Some(vec!["--copy-service".into()]), + cmd: Some(vec!["--copy-service"]), ..Default::default() }; let id = docker @@ -185,7 +142,10 @@ impl ServiceTrait for LdapAdmin { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -193,15 +153,9 @@ impl ServiceTrait for LdapAdmin { Some(format!("{}-ldap-admin", cloud_id)) } - async fn start_message( - &self, - docker: &Docker, - cloud_id: &str, - proxy: &ProxyConfig, - ) -> Result> { - let id = self.container_name(cloud_id).unwrap(); + async fn start_message(&self, docker: &Docker, cloud_id: &str) -> Result> { let info = docker - .inspect_container(&id, None) + .inspect_container(&self.container_name(cloud_id).unwrap(), None) .await .into_diagnostic()?; let ip = if matches!( @@ -224,7 +178,9 @@ impl ServiceTrait for LdapAdmin { } else { return Err(Report::msg("ldap admin not started")); }; - let addr = proxy.addr(&id, IpAddr::from_str(&ip).unwrap()); - Ok(Some(format!("Ldap admin running at: {addr}"))) + Ok(Some(format!( + "Ldap admin running at: https://{} with 'cn=admin,dc=example,dc=org' and password 'haze'", + ip + ))) } } diff --git a/src/service/mail.rs b/src/service/mail.rs index ad40471..93a411d 100644 --- a/src/service/mail.rs +++ b/src/service/mail.rs @@ -1,10 +1,10 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::IntoDiagnostic; @@ -29,26 +29,26 @@ impl ServiceTrait for Mail { let image = "rnwood/smtp4dev"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -57,7 +57,10 @@ impl ServiceTrait for Mail { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -70,14 +73,14 @@ impl ServiceTrait for Mail { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd("occ config:system:set mail_smtpmode --value smtp"), - split_cmnd("occ config:system:set mail_sendmailmode --value smtp"), - split_cmnd("occ config:system:set mail_domain --value haze"), - split_cmnd("occ config:system:set mail_smtphost --value mail"), - split_cmnd("occ config:system:set mail_smtpport --value 25"), - split_cmnd("occ user:setting admin settings email admin@haze"), + "occ config:system:set mail_smtpmode --value smtp".into(), + "occ config:system:set mail_sendmailmode --value smtp".into(), + "occ config:system:set mail_domain --value haze".into(), + "occ config:system:set mail_smtphost --value mail".into(), + "occ config:system:set mail_smtpport --value 25".into(), + "occ user:setting admin settings email admin@haze".into(), ]) } } diff --git a/src/service/objectstore.rs b/src/service/objectstore.rs index 20e586c..6522207 100644 --- a/src/service/objectstore.rs +++ b/src/service/objectstore.rs @@ -2,23 +2,17 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::exec::exec; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ - ContainerCreateBody, ContainerState, EndpointSettings, HostConfig, NetworkingConfig, -}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{ContainerState, EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; -use miette::{IntoDiagnostic, WrapErr}; -use serde_json::Value; -use std::collections::HashMap; -use std::fs::{create_dir_all, write}; +use miette::IntoDiagnostic; #[derive(Debug, Clone, Eq, PartialEq)] pub enum ObjectStore { S3, - S3s, S3m, S3mb, Azure, @@ -27,7 +21,7 @@ pub enum ObjectStore { impl ObjectStore { fn image(&self) -> &str { match self { - ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb | ObjectStore::S3s => { + ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb => { "minio/minio:RELEASE.2024-07-16T23-46-41Z" } ObjectStore::Azure => "arafato/azurite:2.6.5", @@ -36,7 +30,7 @@ impl ObjectStore { fn self_env(&self) -> Vec<&str> { match self { - ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb | ObjectStore::S3s => { + ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb => { vec!["MINIO_ACCESS_KEY=minio", "MINIO_SECRET_KEY=minio123"] } ObjectStore::Azure => vec![], @@ -45,54 +39,17 @@ impl ObjectStore { fn host_name(&self) -> &str { match self { - ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb | ObjectStore::S3s => "s3", + ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb => "s3", ObjectStore::Azure => "azure", } } fn args(&self) -> &[&str] { match self { - ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb | ObjectStore::S3s => { - &["server", "/data"] - } + ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb => &["server", "/data"], _ => &[], } } - - fn volumes(&self, config: &HazeConfig) -> Option> { - match self { - ObjectStore::S3s => { - let cert_dir = config.work_dir.join("certificates/s3"); - create_dir_all(&cert_dir) - .into_diagnostic() - .wrap_err("Failed to create redis certificate directory") - .unwrap(); - let s3_cert_path = config.work_dir.join("certificates/s3/public.crt"); - let s3_key_path = config.work_dir.join("certificates/s3/private.key"); - if !s3_cert_path.exists() { - write( - &s3_cert_path, - include_bytes!("../../certificates/s3/public.crt"), - ) - .into_diagnostic() - .wrap_err("Failed to write s3 certificate") - .unwrap(); - } - if !s3_key_path.exists() { - write( - &s3_key_path, - include_bytes!("../../certificates/s3/private.key"), - ) - .into_diagnostic() - .wrap_err("Failed to write s3 key") - .unwrap(); - } - - Some(vec![format!("{cert_dir}:/root/.minio/certs:ro")]) - } - _ => None, - } - } } #[async_trait::async_trait] @@ -100,7 +57,6 @@ impl ServiceTrait for ObjectStore { fn name(&self) -> &str { match self { ObjectStore::S3 => "s3", - ObjectStore::S3s => "s3s", ObjectStore::S3m => "s3m", ObjectStore::S3mb => "s3mb", ObjectStore::Azure => "azure", @@ -110,9 +66,8 @@ impl ServiceTrait for ObjectStore { fn env(&self) -> &[&str] { match self { ObjectStore::S3 => &["S3=1"], - ObjectStore::S3s => &["S3S=1"], ObjectStore::S3m => &["S3M=1"], - ObjectStore::S3mb => &["S3MB =1"], + ObjectStore::S3mb => &["S3MB=1"], ObjectStore::Azure => &["AZURE=1"], } } @@ -122,34 +77,33 @@ impl ServiceTrait for ObjectStore { docker: &Docker, cloud_id: &str, network: &str, - config: &HazeConfig, + _config: &HazeConfig, _options: &CloudOptions, ) -> Result> { pull_image(docker, self.image()).await?; let options = Some(CreateContainerOptions { - name: Some(format!("{}-object", cloud_id)), + name: format!("{}-object", cloud_id), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(self.image().into()), - env: Some(self.self_env().into_iter().map(String::from).collect()), + let config = Config { + image: Some(self.image()), + env: Some(self.self_env()), host_config: Some(HostConfig { network_mode: Some(network.to_string()), - binds: self.volumes(config), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), - cmd: Some(self.args().iter().copied().map(String::from).collect()), + cmd: Some(self.args().into()), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.host_name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -158,7 +112,10 @@ impl ServiceTrait for ObjectStore { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -209,76 +166,26 @@ impl ServiceTrait for ObjectStore { &["files_external"] } - fn config( - &self, - _docker: &Docker, - _cloud_id: &str, - _config: &HazeConfig, - ) -> Result> { - match self { - ObjectStore::S3s => Ok(hashmap![ - "default_certificates_bundle_path".into() => Value::String("/var/www/html/data/ca-bundle.crt".into()), - ]), - _ => Ok(HashMap::default()), - } - } - - fn pre_setup( - &self, - _docker: &Docker, - _cloud_id: &str, - _config: &HazeConfig, - ) -> Result>> { - match self { - ObjectStore::S3s => Ok(vec![ - vec!["mkdir".into(), "-p".into(), "/var/www/html/data".into()], - vec![ - "sh".into(), - "-c".into(), - "cat /var/www/html/resources/config/ca-bundle.crt /certificates/s3/public.crt > /var/www/html/data/ca-bundle.crt".into(), - ], - ]), - _ => Ok(Vec::new()), - } - } - async fn post_setup( &self, _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { - match self { - ObjectStore::S3 => Ok(vec![ - split_cmnd("occ files_external:create s3 amazons3 amazons3::accesskey"), - split_cmnd("occ files_external:config 1 bucket ext"), - split_cmnd("occ files_external:config 1 hostname s3"), - split_cmnd("occ files_external:config 1 port 9000"), - split_cmnd("occ files_external:config 1 use_ssl false"), - split_cmnd("occ files_external:config 1 use_path_style true"), - split_cmnd("occ files_external:config 1 key minio"), - split_cmnd("occ files_external:config 1 secret minio123"), - split_cmnd("mc alias set s3 http://s3:9000 minio minio123"), - ]), - // ObjectStore::S3s => Ok(vec![ - // "occ files_external:create s3 amazons3 amazons3::accesskey".into(), - // "occ files_external:config 1 bucket ext".into(), - // "occ files_external:config 1 hostname s3".into(), - // "occ files_external:config 1 port 9000".into(), - // "occ files_external:config 1 use_ssl true".into(), - // "occ files_external:config 1 use_path_style true".into(), - // "occ files_external:config 1 key minio".into(), - // "occ files_external:config 1 secret minio123".into(), - // "mc alias set s3 https://s3:9000 minio minio123".into(), - // ]), - _ => Ok(Vec::new()), - } - } - - fn proxy_port(&self) -> u16 { - match self { - ObjectStore::S3 | ObjectStore::S3m | ObjectStore::S3mb | ObjectStore::S3s => 9000, - ObjectStore::Azure => 10000, + ) -> Result> { + if *self == ObjectStore::S3 { + Ok(vec![ + "occ files_external:create s3 amazons3 amazons3::accesskey".into(), + "occ files_external:config 1 bucket ext".into(), + "occ files_external:config 1 hostname s3".into(), + "occ files_external:config 1 port 9000".into(), + "occ files_external:config 1 use_ssl false".into(), + "occ files_external:config 1 use_path_style true".into(), + "occ files_external:config 1 key minio".into(), + "occ files_external:config 1 secret minio123".into(), + "mc alias set s3 http://s3:9000 minio minio123".into(), + ]) + } else { + Ok(Vec::new()) } } } diff --git a/src/service/oc.rs b/src/service/oc.rs index 296b2a5..fcff9e6 100644 --- a/src/service/oc.rs +++ b/src/service/oc.rs @@ -4,9 +4,8 @@ use crate::exec::exec; use crate::image::pull_image; use crate::service::ServiceTrait; use crate::Result; -use bollard::config::NetworkingConfig; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::IntoDiagnostic; @@ -34,7 +33,7 @@ impl ServiceTrait for Oc { let image = "owncloud/server:10.12.2"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); let addr = config.proxy.addr( @@ -44,24 +43,24 @@ impl ServiceTrait for Oc { let domain = addr.split_once("://").unwrap().1; let env_trusted_domain = format!("OWNCLOUD_TRUSTED_DOMAINS={domain}"); let env_domain = format!("OWNCLOUD_DOMAIN={domain}"); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), - env: Some(vec![env_trusted_domain, env_domain]), + env: Some(vec![&env_trusted_domain, &env_domain]), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -70,7 +69,10 @@ impl ServiceTrait for Oc { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -83,7 +85,7 @@ impl ServiceTrait for Oc { docker: &Docker, cloud_id: &str, config: &HazeConfig, - ) -> Result>> { + ) -> Result> { if let Some(ip) = self.get_ips(docker, cloud_id).await?.next() { let container = self.container_name(cloud_id).unwrap(); let addr = config.proxy.addr(&container, ip); diff --git a/src/service/office.rs b/src/service/office.rs index e7db10d..87266a6 100644 --- a/src/service/office.rs +++ b/src/service/office.rs @@ -3,10 +3,8 @@ use crate::config::HazeConfig; use crate::image::pull_image; use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ - ContainerCreateBody, ContainerState, EndpointSettings, HostConfig, NetworkingConfig, -}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{ContainerState, EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::{IntoDiagnostic, Report}; @@ -32,68 +30,48 @@ impl ServiceTrait for Office { config: &HazeConfig, _options: &CloudOptions, ) -> Result> { - let network_info = docker - .inspect_network(network, None) - .await - .into_diagnostic()?; - let gateway = network_info - .ipam - .as_ref() - .ok_or_else(|| Report::msg("Network has no ip info"))? - .config - .as_deref() - .ok_or_else(|| Report::msg("Network has no ip info"))? - .first() - .ok_or_else(|| Report::msg("Network has no ip info"))? - .gateway - .as_deref() - .ok_or_else(|| Report::msg("Network has no ip info"))?; - let image = "collabora/code"; pull_image(docker, image).await?; let container_id = self.container_name(cloud_id).unwrap(); let options = Some(CreateContainerOptions { - name: Some(container_id.clone()), + name: container_id.clone(), ..CreateContainerOptions::default() }); - let mut env = - vec![r#"extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:net.frame_ancestors=*"#.to_string()]; + let mut env = vec!["extra_params=--o:ssl.enable=false --o:ssl.termination=true"]; - let proxy_base = &config.proxy.address; let clean_id = container_id.strip_prefix("haze-").unwrap_or(&container_id); - if !proxy_base.is_empty() { - env.push(format!("server_name={clean_id}.{}", config.proxy.address)); - } - - let clean_cloud_id = cloud_id.strip_prefix("haze-").unwrap_or(cloud_id); - let hosts = if proxy_base.is_empty() { - vec![] - } else { - vec![ - format!("{proxy_base}:{gateway}"), - format!("{clean_cloud_id}.{proxy_base}:{gateway}"), - ] + let server_name_opt = match (&config.proxy.address, config.proxy.https) { + (public, true) if !public.is_empty() => { + format!("server_name={clean_id}.{public}") + } + (public, false) if !public.is_empty() => { + format!("server_name={clean_id}.{public}") + } + _ => "".to_string(), }; - let config = ContainerCreateBody { - image: Some(image.into()), + if !server_name_opt.is_empty() { + env.push(&server_name_opt); + } + + let config = Config { + image: Some(image), env: Some(env), host_config: Some(HostConfig { network_mode: Some(network.to_string()), - extra_hosts: Some(hosts), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -102,7 +80,10 @@ impl ServiceTrait for Office { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -119,7 +100,7 @@ impl ServiceTrait for Office { docker: &Docker, cloud_id: &str, config: &HazeConfig, - ) -> Result>> { + ) -> Result> { let container = &self.container_name(cloud_id).unwrap(); let info = docker .inspect_container(container, None) @@ -147,27 +128,19 @@ impl ServiceTrait for Office { } else { return Err(Report::msg("office not started")); }; - let public = config - .proxy - .addr_with_port(container, ip, self.proxy_port()); - Ok(vec![ - vec![ - "occ".into(), - "config:app:set".into(), - "richdocuments".into(), - "public_wopi_url".into(), - "--value".into(), - public, - ], - vec![ - "occ".into(), - "richdocuments:setup".into(), - "--wopi-url".into(), - "http://office:9980".into(), - "--callback-url".into(), - "http://cloud".into(), - ], + format!( + r#"occ config:app:set richdocuments wopi_url --value="http://{}:9980""#, + ip + ), + format!( + r#"occ config:app:set richdocuments public_wopi_url --value="{}""#, + config.proxy.addr_with_port(container, ip, 9980) + ), + format!( + r#"occ config:app:set richdocuments wopi_root --value="http://{}""#, + cloud_id + ), ]) } diff --git a/src/service/onlyoffice.rs b/src/service/onlyoffice.rs index fa12c2c..f262c8d 100644 --- a/src/service/onlyoffice.rs +++ b/src/service/onlyoffice.rs @@ -2,12 +2,10 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::exec::exec; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ - ContainerCreateBody, ContainerState, EndpointSettings, HostConfig, NetworkingConfig, -}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{ContainerState, EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::{IntoDiagnostic, Report}; @@ -37,26 +35,26 @@ impl ServiceTrait for OnlyOffice { let image = "onlyoffice/documentserver"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -65,7 +63,10 @@ impl ServiceTrait for OnlyOffice { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -82,7 +83,7 @@ impl ServiceTrait for OnlyOffice { docker: &Docker, cloud_id: &str, config: &HazeConfig, - ) -> Result>> { + ) -> Result> { let info = docker .inspect_container(&self.container_name(cloud_id).unwrap(), None) .await @@ -137,44 +138,16 @@ impl ServiceTrait for OnlyOffice { ); Ok(vec![ - vec![ - "occ".into(), - "config:app:set".into(), - "onlyoffice".into(), - "DocumentServerUrl".into(), - "--value".into(), - addr, - ], - vec![ - "occ".into(), - "config:app:set".into(), - "onlyoffice".into(), - "jwt_secret".into(), - "--value".into(), - secret.into(), - ], - split_cmnd("occ onlyoffice:documentserver --check"), + format!("occ config:app:set onlyoffice DocumentServerUrl --value {addr}/"), + format!("occ config:app:set onlyoffice jwt_secret --value {secret}"), + "occ onlyoffice:documentserver --check".into(), ]) } else { Ok(vec![ - vec![ - "occ".into(), - "config:app:set".into(), - "onlyoffice".into(), - "DocumentServerUrl".into(), - "--value".into(), - format!("https://{ip}/"), - ], - split_cmnd("occ config:app:set onlyoffice verify_peer_off --value true"), - vec![ - "occ".into(), - "config:app:set".into(), - "onlyoffice".into(), - "jwt_secret".into(), - "--value".into(), - secret.into(), - ], - split_cmnd("occ onlyoffice:documentserver --check"), + format!("occ config:app:set onlyoffice DocumentServerUrl --value https://{ip}/"), + "occ config:app:set onlyoffice verify_peer_off --value true".into(), + format!("occ config:app:set onlyoffice jwt_secret --value {secret}"), + "occ onlyoffice:documentserver --check".into(), ]) } } diff --git a/src/service/push.rs b/src/service/push.rs index b0bbab2..ed4bf57 100644 --- a/src/service/push.rs +++ b/src/service/push.rs @@ -2,8 +2,8 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::image::pull_image; use crate::service::ServiceTrait; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use local_ip_address::list_afinet_netifas; use maplit::hashmap; @@ -33,11 +33,11 @@ impl ServiceTrait for NotifyPush { let image = "icewind1991/notify_push"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), binds: Some(vec![ @@ -47,23 +47,23 @@ impl ServiceTrait for NotifyPush { ..Default::default() }), env: Some(vec![ - "NEXTCLOUD_URL=http://cloud/".into(), - "LOG=debug".into(), - "REDIS_URL=redis://cloud/".into(), + "NEXTCLOUD_URL=http://cloud/", + "LOG=debug", + "REDIS_URL=redis://cloud/", ]), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), - cmd: Some(vec!["/notify_push".into(), "/config/config.php".into()]), + cmd: Some(vec!["/notify_push", "/config/config.php"]), ..Default::default() }; let id = docker @@ -87,7 +87,7 @@ impl ServiceTrait for NotifyPush { docker: &Docker, cloud_id: &str, config: &HazeConfig, - ) -> Result>> { + ) -> Result> { let mut ips: Vec<_> = self.get_ips(docker, cloud_id).await?.collect(); if let Ok(local_interfaces) = list_afinet_netifas() { ips.extend(local_interfaces.into_iter().map(|(_, ip)| ip)); @@ -97,14 +97,10 @@ impl ServiceTrait for NotifyPush { .iter() .enumerate() .map(|(i, ip)| { - vec![ - "occ".into(), - "config:system:set".into(), - "trusted_proxies".into(), - (i + 1).to_string(), - "--value".into(), - ip.to_string(), - ] + format!( + "occ config:system:set trusted_proxies {} --value {ip}", + i + 1 + ) }) .collect(); @@ -112,7 +108,7 @@ impl ServiceTrait for NotifyPush { config .proxy .addr_with_port(&self.container_name(cloud_id).unwrap(), ips[0], 7867); - commands.push(vec!["occ".into(), "notify_push:setup".into(), addr]); + commands.push(format!("occ notify_push:setup {}", addr)); Ok(commands) } diff --git a/src/service/redis.rs b/src/service/redis.rs index 6d5d5e6..1712b9b 100644 --- a/src/service/redis.rs +++ b/src/service/redis.rs @@ -1,10 +1,10 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::IntoDiagnostic; @@ -29,26 +29,26 @@ impl ServiceTrait for Redis { let image = "redis:8-alpine"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -57,7 +57,10 @@ impl ServiceTrait for Redis { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -70,13 +73,7 @@ impl ServiceTrait for Redis { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { - Ok(vec![split_cmnd( - "occ config:system:set redis host --value redis", - )]) - } - - fn exec_shell(&self) -> &'static str { - "sh" + ) -> Result> { + Ok(vec!["occ config:system:set redis host --value redis".into()]) } } diff --git a/src/service/sftp.rs b/src/service/sftp.rs index 1f47a40..84502c1 100644 --- a/src/service/sftp.rs +++ b/src/service/sftp.rs @@ -1,14 +1,13 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; -use miette::{Context, IntoDiagnostic}; -use std::fs::{create_dir_all, write}; +use miette::IntoDiagnostic; #[derive(Debug, Clone, Eq, PartialEq)] pub struct Sftp; @@ -30,31 +29,28 @@ impl ServiceTrait for Sftp { let image = "atmoz/sftp:alpine"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), - cmd: Some(vec![ - "test:test:::data".into(), - "ldaptest:test:::data".into(), - ]), + cmd: Some(vec!["test:test:::data"]), ..Default::default() }; let id = docker @@ -62,7 +58,10 @@ impl ServiceTrait for Sftp { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -79,119 +78,13 @@ impl ServiceTrait for Sftp { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { - Ok(vec![ - split_cmnd("occ files_external:create sftp sftp password::password"), - split_cmnd("occ files_external:config 1 host sftp"), - split_cmnd("occ files_external:config 1 user test"), - split_cmnd("occ files_external:config 1 root data"), - split_cmnd("occ files_external:config 1 password test"), - ]) - } -} - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct SftpKey; - -#[async_trait::async_trait] -impl ServiceTrait for SftpKey { - fn name(&self) -> &str { - "sftp-key" - } - - async fn spawn( - &self, - docker: &Docker, - cloud_id: &str, - network: &str, - config: &HazeConfig, - _options: &CloudOptions, ) -> Result> { - let image = "atmoz/sftp:alpine"; - pull_image(docker, image).await?; - let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), - ..CreateContainerOptions::default() - }); - let key_dir = config.work_dir.join("certificates/sftp"); - create_dir_all(&key_dir) - .into_diagnostic() - .wrap_err("Failed to create sftp certificate directory")?; - let private_path = key_dir.join("id_rsa"); - let public_path = key_dir.join("id_rsa.pub"); - let private_key = include_str!("../../certificates/sftp/id_rsa"); - let public_key = include_str!("../../certificates/sftp/id_rsa.pub"); - if !private_path.exists() { - write(&private_path, private_key) - .into_diagnostic() - .wrap_err("Failed to write sftp client certificate")?; - } - if !public_path.exists() { - write(&public_path, public_key) - .into_diagnostic() - .wrap_err("Failed to write sftp client key")?; - } - - let volumes = vec![format!("{public_path}:/home/test/.ssh/keys/id_rsa:ro")]; - - let config = ContainerCreateBody { - image: Some(image.into()), - host_config: Some(HostConfig { - network_mode: Some(network.to_string()), - binds: Some(volumes), - ..Default::default() - }), - labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), - }), - networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { - aliases: Some(vec![self.name().to_string()]), - ..Default::default() - } - }), - }), - cmd: Some(vec!["test::::data".into()]), - ..Default::default() - }; - let id = docker - .create_container(options, config) - .await - .into_diagnostic()? - .id; - docker.start_container(&id, None).await.into_diagnostic()?; - Ok(vec![id]) - } - - fn container_name(&self, cloud_id: &str) -> Option { - Some(format!("{}-sftp-key", cloud_id)) - } - - fn apps(&self) -> &'static [&'static str] { - &["files_external"] - } - - async fn post_setup( - &self, - _docker: &Docker, - _cloud_id: &str, - _config: &HazeConfig, - ) -> Result>> { Ok(vec![ - split_cmnd("occ files_external:create sftp sftp publickey::rsa_private"), - split_cmnd("occ files_external:config 1 host sftp-key"), - split_cmnd("occ files_external:config 1 user test"), - split_cmnd("occ files_external:config 1 root data"), - vec![ - "occ".into(), - "files_external:config".into(), - "--value-from-file".into(), - "1".into(), - "private_key".into(), - "/certificates/sftp/id_rsa".into(), - ], + "occ files_external:create sftp sftp password::password".into(), + "occ files_external:config 1 host sftp".into(), + "occ files_external:config 1 user test".into(), + "occ files_external:config 1 root data".into(), + "occ files_external:config 1 password test".into(), ]) } } diff --git a/src/service/smb.rs b/src/service/smb.rs index 08f69bd..5f4dec9 100644 --- a/src/service/smb.rs +++ b/src/service/smb.rs @@ -1,10 +1,10 @@ use crate::cloud::CloudOptions; use crate::config::HazeConfig; use crate::image::pull_image; -use crate::service::{split_cmnd, ServiceTrait}; +use crate::service::ServiceTrait; use crate::Result; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; +use bollard::container::{Config, CreateContainerOptions, NetworkingConfig}; +use bollard::models::{EndpointSettings, HostConfig}; use bollard::Docker; use maplit::hashmap; use miette::IntoDiagnostic; @@ -29,33 +29,31 @@ impl ServiceTrait for Smb { let image = "ghcr.io/servercontainers/samba:smbd-only-a3.18.0-s4.18.2-r0"; pull_image(docker, image).await?; let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), + name: self.container_name(cloud_id).unwrap(), ..CreateContainerOptions::default() }); - let config = ContainerCreateBody { - image: Some(image.into()), + let config = Config { + image: Some(image), host_config: Some(HostConfig { network_mode: Some(network.to_string()), ..Default::default() }), env: Some(vec![ - "ACCOUNT_test=test".into(), - "ACCOUNT_ldaptest=test".into(), - "UID_test=1000".into(), - "SAMBA_VOLUME_CONFIG_test=[test]; path=/tmp; valid users = test; guest ok = no; read only = no; browseable = yes".into(), - "SAMBA_VOLUME_CONFIG_ldaptest=[ldaptest]; path=/tmp; valid users = ldaptest; guest ok = no; read only = no; browseable = yes".into(), + "ACCOUNT_test=test", + "UID_test=1000", + "SAMBA_VOLUME_CONFIG_test=[test]; path=/tmp; valid users = test; guest ok = no; read only = no; browseable = yes", ]), labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), + "haze-type" => self.name(), + "haze-cloud-id" => cloud_id }), networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { + endpoints_config: hashmap! { + network => EndpointSettings { aliases: Some(vec![self.name().to_string()]), ..Default::default() } - }), + }, }), ..Default::default() }; @@ -64,7 +62,10 @@ impl ServiceTrait for Smb { .await .into_diagnostic()? .id; - docker.start_container(&id, None).await.into_diagnostic()?; + docker + .start_container::(&id, None) + .await + .into_diagnostic()?; Ok(vec![id]) } @@ -81,17 +82,13 @@ impl ServiceTrait for Smb { _docker: &Docker, _cloud_id: &str, _config: &HazeConfig, - ) -> Result>> { + ) -> Result> { Ok(vec![ - split_cmnd("occ files_external:create smb smb password::password"), - split_cmnd("occ files_external:config 1 host smb"), - split_cmnd("occ files_external:config 1 user test"), - split_cmnd("occ files_external:config 1 password test"), - split_cmnd("occ files_external:config 1 share test"), + "occ files_external:create smb smb password::password".into(), + "occ files_external:config 1 host smb".into(), + "occ files_external:config 1 user test".into(), + "occ files_external:config 1 password test".into(), + "occ files_external:config 1 share test".into(), ]) } - - fn exec_shell(&self) -> &'static str { - "sh" - } } diff --git a/src/service/webhook.rs b/src/service/webhook.rs deleted file mode 100644 index e7ebae0..0000000 --- a/src/service/webhook.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::cloud::CloudOptions; -use crate::config::HazeConfig; -use crate::image::pull_image; -use crate::service::ServiceTrait; -use crate::Result; -use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig}; -use bollard::query_parameters::CreateContainerOptions; -use bollard::Docker; -use maplit::hashmap; -use miette::IntoDiagnostic; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct Webhook; - -#[async_trait::async_trait] -impl ServiceTrait for Webhook { - fn name(&self) -> &str { - "webhook" - } - - async fn spawn( - &self, - docker: &Docker, - cloud_id: &str, - network: &str, - _config: &HazeConfig, - _options: &CloudOptions, - ) -> Result> { - let image = "ghcr.io/tarampampam/webhook-tester"; - pull_image(docker, image).await?; - let options = Some(CreateContainerOptions { - name: self.container_name(cloud_id), - ..CreateContainerOptions::default() - }); - let config = ContainerCreateBody { - image: Some(image.into()), - host_config: Some(HostConfig { - network_mode: Some(network.to_string()), - ..Default::default() - }), - labels: Some(hashmap! { - "haze-type".into() => self.name().into(), - "haze-cloud-id".into() => cloud_id.into(), - }), - networking_config: Some(NetworkingConfig { - endpoints_config: Some(hashmap! { - network.into() => EndpointSettings { - aliases: Some(vec![self.name().to_string()]), - ..Default::default() - } - }), - }), - ..Default::default() - }; - let id = docker - .create_container(options, config) - .await - .into_diagnostic()? - .id; - docker.start_container(&id, None).await.into_diagnostic()?; - Ok(vec![id]) - } - - fn container_name(&self, cloud_id: &str) -> Option { - Some(format!("{}-webhook", cloud_id)) - } - - fn proxy_port(&self) -> u16 { - 8080 - } - - fn exec_shell(&self) -> &'static str { - "" - } -} diff --git a/src/sources.rs b/src/sources.rs index ccfe564..0a19e08 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -1,17 +1,6 @@ -use crate::config::HazeConfig; -use camino::Utf8PathBuf; -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use miette::{Context, IntoDiagnostic, Report, Result}; -use reqwest::header::HeaderName; -use reqwest::{Client, IntoUrl, Response}; -use sha2::{Digest, Sha512}; use std::fs::read_to_string; -use std::io::Cursor; use std::path::{Path, PathBuf}; -use std::time::Duration; -use tokio::fs::create_dir_all; -use zip::read::root_dir_common_filter; -use zip::ZipArchive; pub struct Sources { #[allow(dead_code)] @@ -60,116 +49,3 @@ impl Sources { } } } - -pub async fn download_nc(config: &HazeConfig, version: &str) -> Result { - if !version.chars().all(|c| c.is_ascii_digit() || c == '.') { - return Err(Report::msg(format!("Invalid version: {version}"))); - } - let root = config.work_dir.join("sources"); - create_dir_all(&root) - .await - .into_diagnostic() - .wrap_err("failed to create parent directory for sources")?; - let dest = root.join(version); - if !dest.exists() { - let progress = MultiProgress::new(); - let download_style = ProgressStyle::with_template("{spinner:.green} {msg} [{elapsed_precise}] [{bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})") - .unwrap(); - let download_bar = ProgressBar::new(0) - .with_message("Downloading") - .with_style(download_style.clone()); - let download_bar = progress.add(download_bar); - - let archive = download_url( - format!("https://download.nextcloud.com/server/releases/nextcloud-{version}.zip"), - |size| { - download_bar.set_length(size); - }, - |count| { - download_bar.inc(count); - }, - ) - .await - .wrap_err_with(|| format!("Failed to download archive for {}", version))?; - download_bar.finish(); - - let expected_hash = download_text(format!( - "https://download.nextcloud.com/server/releases/nextcloud-{version}.zip.sha512" - )) - .await - .wrap_err_with(|| format!("Failed to download hash for {}", version))?; - let expected_hash = expected_hash - .split_once(' ') - .map(|(hash, _)| hash) - .unwrap_or(expected_hash.trim()); - - let hash_bar = ProgressBar::new(download_bar.length().unwrap_or_default()) - .with_message("Validating") - .with_style(download_style.clone()); - let hash_bar = progress.add(hash_bar); - let mut hasher = Sha512::new(); - for chunk in archive.chunks(1014 * 1024) { - hash_bar.inc(chunk.len() as u64); - hasher.update(chunk); - } - let hash = hasher.finalize(); - - let hash = base16ct::lower::encode_string(&hash); - if expected_hash != hash { - return Err(Report::msg(format!( - "Invalid hash for downloaded: {version}, expected {expected_hash} but got {hash}" - ))); - } - hash_bar.finish(); - - let extract_bar = ProgressBar::new_spinner().with_message("Extracting"); - extract_bar.enable_steady_tick(Duration::from_millis(100)); - let extract_bar = progress.add(extract_bar); - let mut archive = ZipArchive::new(Cursor::new(archive)).into_diagnostic()?; - archive - .extract_unwrapped_root_dir(&dest, root_dir_common_filter) - .into_diagnostic() - .wrap_err("Failed to extract archive")?; - extract_bar.finish(); - } - Ok(dest) -} - -async fn download_url( - url: U, - size: SizeFN, - progress: ProgressFN, -) -> Result> { - let mut res = get_url(url).await?.error_for_status().into_diagnostic()?; - let mut buff = Vec::new(); - - size(res.content_length().unwrap_or_default()); - while let Some(chunk) = res.chunk().await.into_diagnostic()? { - progress(chunk.len() as u64); - buff.extend(chunk); - } - Ok(buff) -} -async fn download_text(url: U) -> Result { - get_url(url) - .await? - .error_for_status() - .into_diagnostic()? - .text() - .await - .into_diagnostic() -} - -async fn get_url(url: U) -> Result { - Client::builder() - .build() - .into_diagnostic()? - .get(url) - .header( - HeaderName::from_static("user-agent"), - format!("haze {}", env!("CARGO_PKG_VERSION")), - ) - .send() - .await - .into_diagnostic() -}