difftreelog
refactor temporarly break cross, but greatly cleanup data
in: trunk
16 files changed
Cargo.lockdiffbeforeafterboth117117118[[package]]118[[package]]119name = "aho-corasick"119name = "aho-corasick"120version = "1.1.1"120version = "1.1.2"121source = "registry+https://github.com/rust-lang/crates.io-index"121source = "registry+https://github.com/rust-lang/crates.io-index"122checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"122checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"123dependencies = [123dependencies = [124 "memchr",124 "memchr",125]125]170170171[[package]]171[[package]]172name = "anstream"172name = "anstream"173version = "0.6.4"173version = "0.6.5"174source = "registry+https://github.com/rust-lang/crates.io-index"174source = "registry+https://github.com/rust-lang/crates.io-index"175checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"175checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"176dependencies = [176dependencies = [177 "anstyle",177 "anstyle",178 "anstyle-parse",178 "anstyle-parse",190190191[[package]]191[[package]]192name = "anstyle-parse"192name = "anstyle-parse"193version = "0.2.2"193version = "0.2.3"194source = "registry+https://github.com/rust-lang/crates.io-index"194source = "registry+https://github.com/rust-lang/crates.io-index"195checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"195checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"196dependencies = [196dependencies = [197 "utf8parse",197 "utf8parse",198]198]199199200[[package]]200[[package]]201name = "anstyle-query"201name = "anstyle-query"202version = "1.0.0"202version = "1.0.2"203source = "registry+https://github.com/rust-lang/crates.io-index"203source = "registry+https://github.com/rust-lang/crates.io-index"204checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"204checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"205dependencies = [205dependencies = [206 "windows-sys 0.48.0",206 "windows-sys 0.52.0",207]207]208208209[[package]]209[[package]]210name = "anstyle-wincon"210name = "anstyle-wincon"211version = "3.0.1"211version = "3.0.2"212source = "registry+https://github.com/rust-lang/crates.io-index"212source = "registry+https://github.com/rust-lang/crates.io-index"213checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"213checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"214dependencies = [214dependencies = [215 "anstyle",215 "anstyle",216 "windows-sys 0.48.0",216 "windows-sys 0.52.0",217]217]218218219[[package]]219[[package]]220name = "anyhow"220name = "anyhow"221version = "1.0.75"221version = "1.0.77"222source = "registry+https://github.com/rust-lang/crates.io-index"222source = "registry+https://github.com/rust-lang/crates.io-index"223checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"223checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9"224224225[[package]]225[[package]]226name = "arc-swap"226name = "arc-swap"242242243[[package]]243[[package]]244name = "async-trait"244name = "async-trait"245version = "0.1.74"245version = "0.1.75"246source = "registry+https://github.com/rust-lang/crates.io-index"246source = "registry+https://github.com/rust-lang/crates.io-index"247checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"247checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98"248dependencies = [248dependencies = [249 "proc-macro2",249 "proc-macro2",250 "quote",250 "quote",251 "syn 2.0.38",251 "syn 2.0.43",252]252]253253254[[package]]254[[package]]387387388[[package]]388[[package]]389name = "byteorder"389name = "byteorder"390version = "1.4.3"390version = "1.5.0"391source = "registry+https://github.com/rust-lang/crates.io-index"391source = "registry+https://github.com/rust-lang/crates.io-index"392checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"392checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"393393394[[package]]394[[package]]395name = "bytes"395name = "bytes"482482483[[package]]483[[package]]484name = "clap"484name = "clap"485version = "4.4.7"485version = "4.4.12"486source = "registry+https://github.com/rust-lang/crates.io-index"486source = "registry+https://github.com/rust-lang/crates.io-index"487checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"487checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d"488dependencies = [488dependencies = [489 "clap_builder",489 "clap_builder",490 "clap_derive",490 "clap_derive",491]491]492492493[[package]]493[[package]]494name = "clap_builder"494name = "clap_builder"495version = "4.4.7"495version = "4.4.12"496source = "registry+https://github.com/rust-lang/crates.io-index"496source = "registry+https://github.com/rust-lang/crates.io-index"497checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"497checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"498dependencies = [498dependencies = [499 "anstream",499 "anstream",500 "anstyle",500 "anstyle",514 "heck",514 "heck",515 "proc-macro2",515 "proc-macro2",516 "quote",516 "quote",517 "syn 2.0.38",517 "syn 2.0.43",518]518]519519520[[package]]520[[package]]544544545[[package]]545[[package]]546name = "const-oid"546name = "const-oid"547version = "0.9.5"547version = "0.9.6"548source = "registry+https://github.com/rust-lang/crates.io-index"548source = "registry+https://github.com/rust-lang/crates.io-index"549checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"549checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"550550551[[package]]551[[package]]552name = "cookie-factory"552name = "cookie-factory"556556557[[package]]557[[package]]558name = "core-foundation-sys"558name = "core-foundation-sys"559version = "0.8.4"559version = "0.8.6"560source = "registry+https://github.com/rust-lang/crates.io-index"560source = "registry+https://github.com/rust-lang/crates.io-index"561checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"561checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"562562563[[package]]563[[package]]564name = "countme"564name = "countme"568568569[[package]]569[[package]]570name = "cpufeatures"570name = "cpufeatures"571version = "0.2.9"571version = "0.2.11"572source = "registry+https://github.com/rust-lang/crates.io-index"572source = "registry+https://github.com/rust-lang/crates.io-index"573checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"573checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"574dependencies = [574dependencies = [575 "libc",575 "libc",576]576]615checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"615checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"616dependencies = [616dependencies = [617 "cfg-if",617 "cfg-if",618 "hashbrown 0.14.1",618 "hashbrown 0.14.3",619 "lock_api",619 "lock_api",620 "once_cell",620 "once_cell",621 "parking_lot_core",621 "parking_lot_core",633633634[[package]]634[[package]]635name = "deranged"635name = "deranged"636version = "0.3.9"636version = "0.3.11"637source = "registry+https://github.com/rust-lang/crates.io-index"637source = "registry+https://github.com/rust-lang/crates.io-index"638checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"638checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"639dependencies = [639dependencies = [640 "powerfmt",640 "powerfmt",641 "serde",641 "serde",691dependencies = [691dependencies = [692 "proc-macro2",692 "proc-macro2",693 "quote",693 "quote",694 "syn 2.0.38",694 "syn 2.0.43",695]695]696696697[[package]]697[[package]]708708709[[package]]709[[package]]710name = "env_logger"710name = "env_logger"711version = "0.10.0"711version = "0.10.1"712source = "registry+https://github.com/rust-lang/crates.io-index"712source = "registry+https://github.com/rust-lang/crates.io-index"713checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"713checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"714dependencies = [714dependencies = [715 "humantime",715 "humantime",716 "is-terminal",716 "is-terminal",727727728[[package]]728[[package]]729name = "errno"729name = "errno"730version = "0.3.5"730version = "0.3.8"731source = "registry+https://github.com/rust-lang/crates.io-index"731source = "registry+https://github.com/rust-lang/crates.io-index"732checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"732checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"733dependencies = [733dependencies = [734 "libc",734 "libc",735 "windows-sys 0.48.0",735 "windows-sys 0.52.0",736]736]737737738[[package]]738[[package]]752752753[[package]]753[[package]]754name = "fleet"754name = "fleet"755version = "0.1.0"755version = "0.2.0"756dependencies = [756dependencies = [757 "abort-on-drop",757 "abort-on-drop",758 "age",758 "age",827 "intl-memoizer",827 "intl-memoizer",828 "intl_pluralrules",828 "intl_pluralrules",829 "rustc-hash",829 "rustc-hash",830 "self_cell",830 "self_cell 0.10.3",831 "smallvec",831 "smallvec",832 "unic-langid",832 "unic-langid",833]833]858858859[[package]]859[[package]]860name = "futures"860name = "futures"861version = "0.3.29"861version = "0.3.30"862source = "registry+https://github.com/rust-lang/crates.io-index"862source = "registry+https://github.com/rust-lang/crates.io-index"863checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"863checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"864dependencies = [864dependencies = [865 "futures-channel",865 "futures-channel",866 "futures-core",866 "futures-core",873873874[[package]]874[[package]]875name = "futures-channel"875name = "futures-channel"876version = "0.3.29"876version = "0.3.30"877source = "registry+https://github.com/rust-lang/crates.io-index"877source = "registry+https://github.com/rust-lang/crates.io-index"878checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"878checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"879dependencies = [879dependencies = [880 "futures-core",880 "futures-core",881 "futures-sink",881 "futures-sink",882]882]883883884[[package]]884[[package]]885name = "futures-core"885name = "futures-core"886version = "0.3.29"886version = "0.3.30"887source = "registry+https://github.com/rust-lang/crates.io-index"887source = "registry+https://github.com/rust-lang/crates.io-index"888checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"888checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"889889890[[package]]890[[package]]891name = "futures-executor"891name = "futures-executor"892version = "0.3.29"892version = "0.3.30"893source = "registry+https://github.com/rust-lang/crates.io-index"893source = "registry+https://github.com/rust-lang/crates.io-index"894checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"894checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"895dependencies = [895dependencies = [896 "futures-core",896 "futures-core",897 "futures-task",897 "futures-task",900900901[[package]]901[[package]]902name = "futures-io"902name = "futures-io"903version = "0.3.29"903version = "0.3.30"904source = "registry+https://github.com/rust-lang/crates.io-index"904source = "registry+https://github.com/rust-lang/crates.io-index"905checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"905checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"906906907[[package]]907[[package]]908name = "futures-macro"908name = "futures-macro"909version = "0.3.29"909version = "0.3.30"910source = "registry+https://github.com/rust-lang/crates.io-index"910source = "registry+https://github.com/rust-lang/crates.io-index"911checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"911checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"912dependencies = [912dependencies = [913 "proc-macro2",913 "proc-macro2",914 "quote",914 "quote",915 "syn 2.0.38",915 "syn 2.0.43",916]916]917917918[[package]]918[[package]]919name = "futures-sink"919name = "futures-sink"920version = "0.3.29"920version = "0.3.30"921source = "registry+https://github.com/rust-lang/crates.io-index"921source = "registry+https://github.com/rust-lang/crates.io-index"922checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"922checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"923923924[[package]]924[[package]]925name = "futures-task"925name = "futures-task"926version = "0.3.29"926version = "0.3.30"927source = "registry+https://github.com/rust-lang/crates.io-index"927source = "registry+https://github.com/rust-lang/crates.io-index"928checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"928checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"929929930[[package]]930[[package]]931name = "futures-util"931name = "futures-util"932version = "0.3.29"932version = "0.3.30"933source = "registry+https://github.com/rust-lang/crates.io-index"933source = "registry+https://github.com/rust-lang/crates.io-index"934checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"934checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"935dependencies = [935dependencies = [936 "futures-channel",936 "futures-channel",937 "futures-core",937 "futures-core",968968969[[package]]969[[package]]970name = "getrandom"970name = "getrandom"971version = "0.2.10"971version = "0.2.11"972source = "registry+https://github.com/rust-lang/crates.io-index"972source = "registry+https://github.com/rust-lang/crates.io-index"973checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"973checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"974dependencies = [974dependencies = [975 "cfg-if",975 "cfg-if",976 "libc",976 "libc",989989990[[package]]990[[package]]991name = "gimli"991name = "gimli"992version = "0.28.0"992version = "0.28.1"993source = "registry+https://github.com/rust-lang/crates.io-index"993source = "registry+https://github.com/rust-lang/crates.io-index"994checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"994checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"995995996[[package]]996[[package]]997name = "hashbrown"997name = "hashbrown"100110011002[[package]]1002[[package]]1003name = "hashbrown"1003name = "hashbrown"1004version = "0.14.1"1004version = "0.14.3"1005source = "registry+https://github.com/rust-lang/crates.io-index"1005source = "registry+https://github.com/rust-lang/crates.io-index"1006checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"1006checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"100710071008[[package]]1008[[package]]1009name = "heck"1009name = "heck"102810281029[[package]]1029[[package]]1030name = "hkdf"1030name = "hkdf"1031version = "0.12.3"1031version = "0.12.4"1032source = "registry+https://github.com/rust-lang/crates.io-index"1032source = "registry+https://github.com/rust-lang/crates.io-index"1033checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"1033checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"1034dependencies = [1034dependencies = [1035 "hmac",1035 "hmac",1036]1036]1077 "serde",1077 "serde",1078 "serde_derive",1078 "serde_derive",1079 "thiserror",1079 "thiserror",1080 "toml 0.8.0",1080 "toml 0.8.8",1081 "unic-langid",1081 "unic-langid",1082]1082]108310831119 "proc-macro2",1119 "proc-macro2",1120 "quote",1120 "quote",1121 "strsim",1121 "strsim",1122 "syn 2.0.38",1122 "syn 2.0.43",1123 "unic-langid",1123 "unic-langid",1124]1124]112511251126[[package]]1126[[package]]1127name = "i18n-embed-impl"1127name = "i18n-embed-impl"1128version = "0.8.2"1128version = "0.8.3"1129source = "registry+https://github.com/rust-lang/crates.io-index"1129source = "registry+https://github.com/rust-lang/crates.io-index"1130checksum = "a2a4d5bff745c9a6e1459c490059281b353a4ab0a4e1e58b3eeeaef71f97d07b"1130checksum = "81093c4701672f59416582fe3145676126fd23ba5db910acad0793c1108aaa58"1131dependencies = [1131dependencies = [1132 "find-crate",1132 "find-crate",1133 "i18n-config",1133 "i18n-config",1134 "proc-macro2",1134 "proc-macro2",1135 "quote",1135 "quote",1136 "syn 2.0.38",1136 "syn 2.0.43",1137]1137]113811381139[[package]]1139[[package]]1140name = "iana-time-zone"1140name = "iana-time-zone"1141version = "0.1.57"1141version = "0.1.59"1142source = "registry+https://github.com/rust-lang/crates.io-index"1142source = "registry+https://github.com/rust-lang/crates.io-index"1143checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"1143checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"1144dependencies = [1144dependencies = [1145 "android_system_properties",1145 "android_system_properties",1146 "core-foundation-sys",1146 "core-foundation-sys",1147 "iana-time-zone-haiku",1147 "iana-time-zone-haiku",1148 "js-sys",1148 "js-sys",1149 "wasm-bindgen",1149 "wasm-bindgen",1150 "windows",1150 "windows-core",1151]1151]115211521153[[package]]1153[[package]]116111611162[[package]]1162[[package]]1163name = "indexmap"1163name = "indexmap"1164version = "2.0.2"1164version = "2.1.0"1165source = "registry+https://github.com/rust-lang/crates.io-index"1165source = "registry+https://github.com/rust-lang/crates.io-index"1166checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"1166checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"1167dependencies = [1167dependencies = [1168 "equivalent",1168 "equivalent",1169 "hashbrown 0.14.1",1169 "hashbrown 0.14.3",1170]1170]117111711172[[package]]1172[[package]]122912291230[[package]]1230[[package]]1231name = "is-terminal"1231name = "is-terminal"1232version = "0.4.9"1232version = "0.4.10"1233source = "registry+https://github.com/rust-lang/crates.io-index"1233source = "registry+https://github.com/rust-lang/crates.io-index"1234checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"1234checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"1235dependencies = [1235dependencies = [1236 "hermit-abi 0.3.3",1236 "hermit-abi 0.3.3",1237 "rustix",1237 "rustix",1238 "windows-sys 0.48.0",1238 "windows-sys 0.52.0",1239]1239]124012401241[[package]]1241[[package]]125512551256[[package]]1256[[package]]1257name = "itoa"1257name = "itoa"1258version = "1.0.9"1258version = "1.0.10"1259source = "registry+https://github.com/rust-lang/crates.io-index"1259source = "registry+https://github.com/rust-lang/crates.io-index"1260checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"1260checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"126112611262[[package]]1262[[package]]1263name = "js-sys"1263name = "js-sys"1264version = "0.3.64"1264version = "0.3.66"1265source = "registry+https://github.com/rust-lang/crates.io-index"1265source = "registry+https://github.com/rust-lang/crates.io-index"1266checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"1266checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"1267dependencies = [1267dependencies = [1268 "wasm-bindgen",1268 "wasm-bindgen",1269]1269]127912791280[[package]]1280[[package]]1281name = "libc"1281name = "libc"1282version = "0.2.149"1282version = "0.2.151"1283source = "registry+https://github.com/rust-lang/crates.io-index"1283source = "registry+https://github.com/rust-lang/crates.io-index"1284checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"1284checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"128512851286[[package]]1286[[package]]1287name = "libm"1287name = "libm"1288version = "0.2.7"1288version = "0.2.8"1289source = "registry+https://github.com/rust-lang/crates.io-index"1289source = "registry+https://github.com/rust-lang/crates.io-index"1290checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"1290checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"129112911292[[package]]1292[[package]]1293name = "libmimalloc-sys"1293name = "libmimalloc-sys"1307dependencies = [1307dependencies = [1308 "bitflags 2.4.1",1308 "bitflags 2.4.1",1309 "libc",1309 "libc",1310 "redox_syscall 0.4.1",1310 "redox_syscall",1311]1311]131213121313[[package]]1313[[package]]131813181319[[package]]1319[[package]]1320name = "linux-raw-sys"1320name = "linux-raw-sys"1321version = "0.4.10"1321version = "0.4.12"1322source = "registry+https://github.com/rust-lang/crates.io-index"1322source = "registry+https://github.com/rust-lang/crates.io-index"1323checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"1323checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"132413241325[[package]]1325[[package]]1326name = "lock_api"1326name = "lock_api"1327version = "0.4.10"1327version = "0.4.11"1328source = "registry+https://github.com/rust-lang/crates.io-index"1328source = "registry+https://github.com/rust-lang/crates.io-index"1329checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"1329checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"1330dependencies = [1330dependencies = [1331 "autocfg",1331 "autocfg",1332 "scopeguard",1332 "scopeguard",135513551356[[package]]1356[[package]]1357name = "memchr"1357name = "memchr"1358version = "2.6.4"1358version = "2.7.1"1359source = "registry+https://github.com/rust-lang/crates.io-index"1359source = "registry+https://github.com/rust-lang/crates.io-index"1360checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"1360checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"136113611362[[package]]1362[[package]]1363name = "memoffset"1363name = "memoffset"139413941395[[package]]1395[[package]]1396name = "mio"1396name = "mio"1397version = "0.8.8"1397version = "0.8.10"1398source = "registry+https://github.com/rust-lang/crates.io-index"1398source = "registry+https://github.com/rust-lang/crates.io-index"1399checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"1399checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"1400dependencies = [1400dependencies = [1401 "libc",1401 "libc",1402 "wasi 0.11.0+wasi-snapshot-preview1",1402 "wasi 0.11.0+wasi-snapshot-preview1",151415141515[[package]]1515[[package]]1516name = "object"1516name = "object"1517version = "0.32.1"1517version = "0.32.2"1518source = "registry+https://github.com/rust-lang/crates.io-index"1518source = "registry+https://github.com/rust-lang/crates.io-index"1519checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"1519checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"1520dependencies = [1520dependencies = [1521 "memchr",1521 "memchr",1522]1522]153515351536[[package]]1536[[package]]1537name = "openssh"1537name = "openssh"1538version = "0.10.1"1538version = "0.10.2"1539source = "registry+https://github.com/rust-lang/crates.io-index"1539source = "registry+https://github.com/rust-lang/crates.io-index"1540checksum = "3dfe68c42d6ee6bd9de175b7a5d9bb86aa99d4e2fa7cf2f2a44e97f60b6d2759"1540checksum = "8274f2bf1fc3785406a3ff07c92c15590c00e84efb883da77b671562ca9a6115"1541dependencies = [1541dependencies = [1542 "dirs",1542 "dirs",1543 "libc",1543 "libc",159515951596[[package]]1596[[package]]1597name = "parking_lot_core"1597name = "parking_lot_core"1598version = "0.9.8"1598version = "0.9.9"1599source = "registry+https://github.com/rust-lang/crates.io-index"1599source = "registry+https://github.com/rust-lang/crates.io-index"1600checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"1600checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"1601dependencies = [1601dependencies = [1602 "cfg-if",1602 "cfg-if",1603 "libc",1603 "libc",1604 "redox_syscall 0.3.5",1604 "redox_syscall",1605 "smallvec",1605 "smallvec",1606 "windows-targets 0.48.5",1606 "windows-targets 0.48.5",1607]1607]1659dependencies = [1659dependencies = [1660 "proc-macro2",1660 "proc-macro2",1661 "quote",1661 "quote",1662 "syn 2.0.38",1662 "syn 2.0.43",1663]1663]166416641665[[package]]1665[[package]]172117211722[[package]]1722[[package]]1723name = "portable-atomic"1723name = "portable-atomic"1724version = "1.4.3"1724version = "1.6.0"1725source = "registry+https://github.com/rust-lang/crates.io-index"1725source = "registry+https://github.com/rust-lang/crates.io-index"1726checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b"1726checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"172717271728[[package]]1728[[package]]1729name = "powerfmt"1729name = "powerfmt"176317631764[[package]]1764[[package]]1765name = "proc-macro2"1765name = "proc-macro2"1766version = "1.0.69"1766version = "1.0.71"1767source = "registry+https://github.com/rust-lang/crates.io-index"1767source = "registry+https://github.com/rust-lang/crates.io-index"1768checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"1768checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"1769dependencies = [1769dependencies = [1770 "unicode-ident",1770 "unicode-ident",1771]1771]1849source = "registry+https://github.com/rust-lang/crates.io-index"1849source = "registry+https://github.com/rust-lang/crates.io-index"1850checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"1850checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"1851dependencies = [1851dependencies = [1852 "getrandom 0.2.10",1852 "getrandom 0.2.11",1853]1853]185418541855[[package]]1855[[package]]1861 "rand_core 0.5.1",1861 "rand_core 0.5.1",1862]1862]18631864[[package]]1865name = "redox_syscall"1866version = "0.3.5"1867source = "registry+https://github.com/rust-lang/crates.io-index"1868checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"1869dependencies = [1870 "bitflags 1.3.2",1871]187218631873[[package]]1864[[package]]1874name = "redox_syscall"1865name = "redox_syscall"1885source = "registry+https://github.com/rust-lang/crates.io-index"1876source = "registry+https://github.com/rust-lang/crates.io-index"1886checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"1877checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"1887dependencies = [1878dependencies = [1888 "getrandom 0.2.10",1879 "getrandom 0.2.11",1889 "libredox",1880 "libredox",1890 "thiserror",1881 "thiserror",1891]1882]2015 "proc-macro2",2006 "proc-macro2",2016 "quote",2007 "quote",2017 "rust-embed-utils",2008 "rust-embed-utils",2018 "syn 2.0.38",2009 "syn 2.0.43",2019 "walkdir",2010 "walkdir",2020]2011]20212012204320342044[[package]]2035[[package]]2045name = "rustix"2036name = "rustix"2046version = "0.38.21"2037version = "0.38.28"2047source = "registry+https://github.com/rust-lang/crates.io-index"2038source = "registry+https://github.com/rust-lang/crates.io-index"2048checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"2039checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"2049dependencies = [2040dependencies = [2050 "bitflags 2.4.1",2041 "bitflags 2.4.1",2051 "errno",2042 "errno",2052 "libc",2043 "libc",2053 "linux-raw-sys",2044 "linux-raw-sys",2054 "windows-sys 0.48.0",2045 "windows-sys 0.52.0",2055]2046]205620472057[[package]]2048[[package]]2058name = "ryu"2049name = "ryu"2059version = "1.0.15"2050version = "1.0.16"2060source = "registry+https://github.com/rust-lang/crates.io-index"2051source = "registry+https://github.com/rust-lang/crates.io-index"2061checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"2052checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"206220532063[[package]]2054[[package]]2064name = "salsa20"2055name = "salsa20"211621072117[[package]]2108[[package]]2118name = "self_cell"2109name = "self_cell"2119version = "0.10.2"2110version = "0.10.3"2120source = "registry+https://github.com/rust-lang/crates.io-index"2111source = "registry+https://github.com/rust-lang/crates.io-index"2121checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"2112checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"2113dependencies = [2114 "self_cell 1.0.3",2115]21162117[[package]]2118name = "self_cell"2119version = "1.0.3"2120source = "registry+https://github.com/rust-lang/crates.io-index"2121checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba"212221222123[[package]]2123[[package]]2124name = "serde"2124name = "serde"2146dependencies = [2146dependencies = [2147 "proc-macro2",2147 "proc-macro2",2148 "quote",2148 "quote",2149 "syn 2.0.38",2149 "syn 2.0.43",2150]2150]215121512152[[package]]2152[[package]]216221622163[[package]]2163[[package]]2164name = "serde_spanned"2164name = "serde_spanned"2165version = "0.6.3"2165version = "0.6.5"2166source = "registry+https://github.com/rust-lang/crates.io-index"2166source = "registry+https://github.com/rust-lang/crates.io-index"2167checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"2167checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"2168dependencies = [2168dependencies = [2169 "serde",2169 "serde",2170]2170]218221822183[[package]]2183[[package]]2184name = "sharded-slab"2184name = "sharded-slab"2185version = "0.1.4"2185version = "0.1.7"2186source = "registry+https://github.com/rust-lang/crates.io-index"2186source = "registry+https://github.com/rust-lang/crates.io-index"2187checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"2187checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"2188dependencies = [2188dependencies = [2189 "lazy_static",2189 "lazy_static",2190]2190]223122312232[[package]]2232[[package]]2233name = "smallvec"2233name = "smallvec"2234version = "1.11.1"2234version = "1.11.2"2235source = "registry+https://github.com/rust-lang/crates.io-index"2235source = "registry+https://github.com/rust-lang/crates.io-index"2236checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"2236checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"223722372238[[package]]2238[[package]]2239name = "smol_str"2239name = "smol_str"224622462247[[package]]2247[[package]]2248name = "socket2"2248name = "socket2"2249version = "0.5.4"2249version = "0.5.5"2250source = "registry+https://github.com/rust-lang/crates.io-index"2250source = "registry+https://github.com/rust-lang/crates.io-index"2251checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"2251checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"2252dependencies = [2252dependencies = [2253 "libc",2253 "libc",2254 "windows-sys 0.48.0",2254 "windows-sys 0.48.0",230523052306[[package]]2306[[package]]2307name = "syn"2307name = "syn"2308version = "2.0.38"2308version = "2.0.43"2309source = "registry+https://github.com/rust-lang/crates.io-index"2309source = "registry+https://github.com/rust-lang/crates.io-index"2310checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"2310checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"2311dependencies = [2311dependencies = [2312 "proc-macro2",2312 "proc-macro2",2313 "quote",2313 "quote",234223422343[[package]]2343[[package]]2344name = "tempfile"2344name = "tempfile"2345version = "3.8.1"2345version = "3.9.0"2346source = "registry+https://github.com/rust-lang/crates.io-index"2346source = "registry+https://github.com/rust-lang/crates.io-index"2347checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"2347checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"2348dependencies = [2348dependencies = [2349 "cfg-if",2349 "cfg-if",2350 "fastrand",2350 "fastrand",2351 "redox_syscall 0.4.1",2351 "redox_syscall",2352 "rustix",2352 "rustix",2353 "windows-sys 0.48.0",2353 "windows-sys 0.52.0",2354]2354]235523552356[[package]]2356[[package]]2357name = "termcolor"2357name = "termcolor"2358version = "1.3.0"2358version = "1.4.0"2359source = "registry+https://github.com/rust-lang/crates.io-index"2359source = "registry+https://github.com/rust-lang/crates.io-index"2360checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"2360checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"2361dependencies = [2361dependencies = [2362 "winapi-util",2362 "winapi-util",2363]2363]238023802381[[package]]2381[[package]]2382name = "thiserror"2382name = "thiserror"2383version = "1.0.50"2383version = "1.0.53"2384source = "registry+https://github.com/rust-lang/crates.io-index"2384source = "registry+https://github.com/rust-lang/crates.io-index"2385checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"2385checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09"2386dependencies = [2386dependencies = [2387 "thiserror-impl",2387 "thiserror-impl",2388]2388]238923892390[[package]]2390[[package]]2391name = "thiserror-impl"2391name = "thiserror-impl"2392version = "1.0.50"2392version = "1.0.53"2393source = "registry+https://github.com/rust-lang/crates.io-index"2393source = "registry+https://github.com/rust-lang/crates.io-index"2394checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"2394checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19"2395dependencies = [2395dependencies = [2396 "proc-macro2",2396 "proc-macro2",2397 "quote",2397 "quote",2398 "syn 2.0.38",2398 "syn 2.0.43",2399]2399]240024002401[[package]]2401[[package]]241024102411[[package]]2411[[package]]2412name = "time"2412name = "time"2413version = "0.3.30"2413version = "0.3.31"2414source = "registry+https://github.com/rust-lang/crates.io-index"2414source = "registry+https://github.com/rust-lang/crates.io-index"2415checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"2415checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"2416dependencies = [2416dependencies = [2417 "deranged",2417 "deranged",2418 "powerfmt",2418 "powerfmt",242924292430[[package]]2430[[package]]2431name = "time-macros"2431name = "time-macros"2432version = "0.2.15"2432version = "0.2.16"2433source = "registry+https://github.com/rust-lang/crates.io-index"2433source = "registry+https://github.com/rust-lang/crates.io-index"2434checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"2434checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"2435dependencies = [2435dependencies = [2436 "time-core",2436 "time-core",2437]2437]243824382439[[package]]2439[[package]]2440name = "tinystr"2440name = "tinystr"2441version = "0.7.2"2441version = "0.7.5"2442source = "registry+https://github.com/rust-lang/crates.io-index"2442source = "registry+https://github.com/rust-lang/crates.io-index"2443checksum = "8faa444297615a4e020acb64146b0603c9c395c03a97c17fd9028816d3b4d63e"2443checksum = "83c02bf3c538ab32ba913408224323915f4ef9a6d61c0e85d493f355921c0ece"2444dependencies = [2444dependencies = [2445 "displaydoc",2445 "displaydoc",2446]2446]244724472448[[package]]2448[[package]]2449name = "tokio"2449name = "tokio"2450version = "1.33.0"2450version = "1.35.1"2451source = "registry+https://github.com/rust-lang/crates.io-index"2451source = "registry+https://github.com/rust-lang/crates.io-index"2452checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"2452checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"2453dependencies = [2453dependencies = [2454 "backtrace",2454 "backtrace",2455 "bytes",2455 "bytes",246624662467[[package]]2467[[package]]2468name = "tokio-macros"2468name = "tokio-macros"2469version = "2.1.0"2469version = "2.2.0"2470source = "registry+https://github.com/rust-lang/crates.io-index"2470source = "registry+https://github.com/rust-lang/crates.io-index"2471checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"2471checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"2472dependencies = [2472dependencies = [2473 "proc-macro2",2473 "proc-macro2",2474 "quote",2474 "quote",2475 "syn 2.0.38",2475 "syn 2.0.43",2476]2476]247724772478[[package]]2478[[package]]251025102511[[package]]2511[[package]]2512name = "toml"2512name = "toml"2513version = "0.8.0"2513version = "0.8.8"2514source = "registry+https://github.com/rust-lang/crates.io-index"2514source = "registry+https://github.com/rust-lang/crates.io-index"2515checksum = "c226a7bba6d859b63c92c4b4fe69c5b6b72d0cb897dbc8e6012298e6154cb56e"2515checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"2516dependencies = [2516dependencies = [2517 "serde",2517 "serde",2518 "serde_spanned",2518 "serde_spanned",252225222523[[package]]2523[[package]]2524name = "toml_datetime"2524name = "toml_datetime"2525version = "0.6.3"2525version = "0.6.5"2526source = "registry+https://github.com/rust-lang/crates.io-index"2526source = "registry+https://github.com/rust-lang/crates.io-index"2527checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"2527checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"2528dependencies = [2528dependencies = [2529 "serde",2529 "serde",2530]2530]253125312532[[package]]2532[[package]]2533name = "toml_edit"2533name = "toml_edit"2534version = "0.20.0"2534version = "0.21.0"2535source = "registry+https://github.com/rust-lang/crates.io-index"2535source = "registry+https://github.com/rust-lang/crates.io-index"2536checksum = "8ff63e60a958cefbb518ae1fd6566af80d9d4be430a33f3723dfc47d1d411d95"2536checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"2537dependencies = [2537dependencies = [2538 "indexmap",2538 "indexmap",2539 "serde",2539 "serde",2561dependencies = [2561dependencies = [2562 "proc-macro2",2562 "proc-macro2",2563 "quote",2563 "quote",2564 "syn 2.0.38",2564 "syn 2.0.43",2565]2565]256625662567[[package]]2567[[package]]258825882589[[package]]2589[[package]]2590name = "tracing-log"2590name = "tracing-log"2591version = "0.1.3"2591version = "0.2.0"2592source = "registry+https://github.com/rust-lang/crates.io-index"2592source = "registry+https://github.com/rust-lang/crates.io-index"2593checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"2593checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"2594dependencies = [2594dependencies = [2595 "lazy_static",2596 "log",2595 "log",2596 "once_cell",2597 "tracing-core",2597 "tracing-core",2598]2598]259925992600[[package]]2600[[package]]2601name = "tracing-subscriber"2601name = "tracing-subscriber"2602version = "0.3.17"2602version = "0.3.18"2603source = "registry+https://github.com/rust-lang/crates.io-index"2603source = "registry+https://github.com/rust-lang/crates.io-index"2604checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"2604checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"2605dependencies = [2605dependencies = [2606 "matchers",2606 "matchers",2607 "nu-ansi-term",2607 "nu-ansi-term",263226322633[[package]]2633[[package]]2634name = "unic-langid"2634name = "unic-langid"2635version = "0.9.1"2635version = "0.9.4"2636source = "registry+https://github.com/rust-lang/crates.io-index"2636source = "registry+https://github.com/rust-lang/crates.io-index"2637checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f"2637checksum = "238722e6d794ed130f91f4ea33e01fcff4f188d92337a21297892521c72df516"2638dependencies = [2638dependencies = [2639 "unic-langid-impl",2639 "unic-langid-impl",2640]2640]264126412642[[package]]2642[[package]]2643name = "unic-langid-impl"2643name = "unic-langid-impl"2644version = "0.9.1"2644version = "0.9.4"2645source = "registry+https://github.com/rust-lang/crates.io-index"2645source = "registry+https://github.com/rust-lang/crates.io-index"2646checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff"2646checksum = "4bd55a2063fdea4ef1f8633243a7b0524cbeef1905ae04c31a1c9b9775c55bc6"2647dependencies = [2647dependencies = [2648 "serde",2648 "serde",2649 "tinystr",2649 "tinystr",277227722773[[package]]2773[[package]]2774name = "wasm-bindgen"2774name = "wasm-bindgen"2775version = "0.2.87"2775version = "0.2.89"2776source = "registry+https://github.com/rust-lang/crates.io-index"2776source = "registry+https://github.com/rust-lang/crates.io-index"2777checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"2777checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"2778dependencies = [2778dependencies = [2779 "cfg-if",2779 "cfg-if",2780 "wasm-bindgen-macro",2780 "wasm-bindgen-macro",2781]2781]278227822783[[package]]2783[[package]]2784name = "wasm-bindgen-backend"2784name = "wasm-bindgen-backend"2785version = "0.2.87"2785version = "0.2.89"2786source = "registry+https://github.com/rust-lang/crates.io-index"2786source = "registry+https://github.com/rust-lang/crates.io-index"2787checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"2787checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"2788dependencies = [2788dependencies = [2789 "bumpalo",2789 "bumpalo",2790 "log",2790 "log",2791 "once_cell",2791 "once_cell",2792 "proc-macro2",2792 "proc-macro2",2793 "quote",2793 "quote",2794 "syn 2.0.38",2794 "syn 2.0.43",2795 "wasm-bindgen-shared",2795 "wasm-bindgen-shared",2796]2796]279727972798[[package]]2798[[package]]2799name = "wasm-bindgen-macro"2799name = "wasm-bindgen-macro"2800version = "0.2.87"2800version = "0.2.89"2801source = "registry+https://github.com/rust-lang/crates.io-index"2801source = "registry+https://github.com/rust-lang/crates.io-index"2802checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"2802checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"2803dependencies = [2803dependencies = [2804 "quote",2804 "quote",2805 "wasm-bindgen-macro-support",2805 "wasm-bindgen-macro-support",2806]2806]280728072808[[package]]2808[[package]]2809name = "wasm-bindgen-macro-support"2809name = "wasm-bindgen-macro-support"2810version = "0.2.87"2810version = "0.2.89"2811source = "registry+https://github.com/rust-lang/crates.io-index"2811source = "registry+https://github.com/rust-lang/crates.io-index"2812checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"2812checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"2813dependencies = [2813dependencies = [2814 "proc-macro2",2814 "proc-macro2",2815 "quote",2815 "quote",2816 "syn 2.0.38",2816 "syn 2.0.43",2817 "wasm-bindgen-backend",2817 "wasm-bindgen-backend",2818 "wasm-bindgen-shared",2818 "wasm-bindgen-shared",2819]2819]282028202821[[package]]2821[[package]]2822name = "wasm-bindgen-shared"2822name = "wasm-bindgen-shared"2823version = "0.2.87"2823version = "0.2.89"2824source = "registry+https://github.com/rust-lang/crates.io-index"2824source = "registry+https://github.com/rust-lang/crates.io-index"2825checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"2825checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"282628262827[[package]]2827[[package]]2828name = "winapi"2828name = "winapi"2856checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"2856checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"285728572858[[package]]2858[[package]]2859name = "windows"2859name = "windows-core"2860version = "0.48.0"2860version = "0.52.0"2861source = "registry+https://github.com/rust-lang/crates.io-index"2861source = "registry+https://github.com/rust-lang/crates.io-index"2862checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"2862checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"2863dependencies = [2863dependencies = [2864 "windows-targets 0.48.5",2864 "windows-targets 0.52.0",2865]2865]286628662867[[package]]2867[[package]]2882 "windows-targets 0.48.5",2882 "windows-targets 0.48.5",2883]2883]28842885[[package]]2886name = "windows-sys"2887version = "0.52.0"2888source = "registry+https://github.com/rust-lang/crates.io-index"2889checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"2890dependencies = [2891 "windows-targets 0.52.0",2892]288428932885[[package]]2894[[package]]2886name = "windows-targets"2895name = "windows-targets"2912 "windows_x86_64_msvc 0.48.5",2921 "windows_x86_64_msvc 0.48.5",2913]2922]29232924[[package]]2925name = "windows-targets"2926version = "0.52.0"2927source = "registry+https://github.com/rust-lang/crates.io-index"2928checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"2929dependencies = [2930 "windows_aarch64_gnullvm 0.52.0",2931 "windows_aarch64_msvc 0.52.0",2932 "windows_i686_gnu 0.52.0",2933 "windows_i686_msvc 0.52.0",2934 "windows_x86_64_gnu 0.52.0",2935 "windows_x86_64_gnullvm 0.52.0",2936 "windows_x86_64_msvc 0.52.0",2937]291429382915[[package]]2939[[package]]2916name = "windows_aarch64_gnullvm"2940name = "windows_aarch64_gnullvm"2924source = "registry+https://github.com/rust-lang/crates.io-index"2948source = "registry+https://github.com/rust-lang/crates.io-index"2925checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"2949checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"29502951[[package]]2952name = "windows_aarch64_gnullvm"2953version = "0.52.0"2954source = "registry+https://github.com/rust-lang/crates.io-index"2955checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"292629562927[[package]]2957[[package]]2928name = "windows_aarch64_msvc"2958name = "windows_aarch64_msvc"2936source = "registry+https://github.com/rust-lang/crates.io-index"2966source = "registry+https://github.com/rust-lang/crates.io-index"2937checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"2967checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"29682969[[package]]2970name = "windows_aarch64_msvc"2971version = "0.52.0"2972source = "registry+https://github.com/rust-lang/crates.io-index"2973checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"293829742939[[package]]2975[[package]]2940name = "windows_i686_gnu"2976name = "windows_i686_gnu"2948source = "registry+https://github.com/rust-lang/crates.io-index"2984source = "registry+https://github.com/rust-lang/crates.io-index"2949checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"2985checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"29862987[[package]]2988name = "windows_i686_gnu"2989version = "0.52.0"2990source = "registry+https://github.com/rust-lang/crates.io-index"2991checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"295029922951[[package]]2993[[package]]2952name = "windows_i686_msvc"2994name = "windows_i686_msvc"2960source = "registry+https://github.com/rust-lang/crates.io-index"3002source = "registry+https://github.com/rust-lang/crates.io-index"2961checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"3003checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"30043005[[package]]3006name = "windows_i686_msvc"3007version = "0.52.0"3008source = "registry+https://github.com/rust-lang/crates.io-index"3009checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"296230102963[[package]]3011[[package]]2964name = "windows_x86_64_gnu"3012name = "windows_x86_64_gnu"2972source = "registry+https://github.com/rust-lang/crates.io-index"3020source = "registry+https://github.com/rust-lang/crates.io-index"2973checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"3021checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"30223023[[package]]3024name = "windows_x86_64_gnu"3025version = "0.52.0"3026source = "registry+https://github.com/rust-lang/crates.io-index"3027checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"297430282975[[package]]3029[[package]]2976name = "windows_x86_64_gnullvm"3030name = "windows_x86_64_gnullvm"2984source = "registry+https://github.com/rust-lang/crates.io-index"3038source = "registry+https://github.com/rust-lang/crates.io-index"2985checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"3039checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"30403041[[package]]3042name = "windows_x86_64_gnullvm"3043version = "0.52.0"3044source = "registry+https://github.com/rust-lang/crates.io-index"3045checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"298630462987[[package]]3047[[package]]2988name = "windows_x86_64_msvc"3048name = "windows_x86_64_msvc"2996source = "registry+https://github.com/rust-lang/crates.io-index"3056source = "registry+https://github.com/rust-lang/crates.io-index"2997checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"3057checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"30583059[[package]]3060name = "windows_x86_64_msvc"3061version = "0.52.0"3062source = "registry+https://github.com/rust-lang/crates.io-index"3063checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"299830642999[[package]]3065[[package]]3000name = "winnow"3066name = "winnow"3001version = "0.5.15"3067version = "0.5.31"3002source = "registry+https://github.com/rust-lang/crates.io-index"3068source = "registry+https://github.com/rust-lang/crates.io-index"3003checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"3069checksum = "97a4882e6b134d6c28953a387571f1acdd3496830d5e36c5e3a1075580ea641c"3004dependencies = [3070dependencies = [3005 "memchr",3071 "memchr",3006]3072]302430903025[[package]]3091[[package]]3026name = "zeroize"3092name = "zeroize"3027version = "1.6.0"3093version = "1.7.0"3028source = "registry+https://github.com/rust-lang/crates.io-index"3094source = "registry+https://github.com/rust-lang/crates.io-index"3029checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"3095checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"3030dependencies = [3096dependencies = [3031 "zeroize_derive",3097 "zeroize_derive",3032]3098]3039dependencies = [3105dependencies = [3040 "proc-macro2",3106 "proc-macro2",3041 "quote",3107 "quote",3042 "syn 2.0.38",3108 "syn 2.0.43",3043]3109]30443110cmds/fleet/Cargo.tomldiffbeforeafterboth--- a/cmds/fleet/Cargo.toml
+++ b/cmds/fleet/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "fleet"
description = "NixOS configuration management"
-version = "0.1.0"
+version = "0.2.0"
authors = ["Yaroslav Bolyukin <iam@lach.pw>"]
edition = "2021"
cmds/fleet/src/better_nix_eval.rsdiffbeforeafterboth--- a/cmds/fleet/src/better_nix_eval.rs
+++ b/cmds/fleet/src/better_nix_eval.rs
@@ -9,7 +9,7 @@
use std::sync::{Arc, OnceLock};
use anyhow::{anyhow, bail, ensure, Context, Result};
-use better_command::{ClonableHandler, NixHandler, Handler, NoopHandler};
+use better_command::{ClonableHandler, Handler, NixHandler, NoopHandler};
use futures::StreamExt;
use itertools::Itertools;
use r2d2::{Pool, PooledConnection};
@@ -299,8 +299,11 @@
let mut fexpr = b"builtins.toJSON (".to_vec();
fexpr.extend_from_slice(expr.as_ref());
fexpr.push(b')');
- let v = self.execute_expression_string(fexpr).await?;
- Ok(serde_json::from_str(&v)?)
+ let v = self
+ .execute_expression_string(fexpr)
+ .await
+ .context("string expression")?;
+ serde_json::from_str(&v).context("json parse")
}
async fn execute_expression_wrapping(
&mut self,
@@ -450,15 +453,26 @@
#[macro_export]
macro_rules! nix_expr_inner {
- (Obj { $($ident:ident: $($val:tt)+),* $(,)? }) => {{
- use $crate::better_nix_eval::NixExprBuilder;
+ //(@munch_object FIXME: value should be arbitrary nix_expr_inner input... Time to write proc-macro?
+ (@obj($o:ident) $field:ident, $($tt:tt)*) => {{
+ $o.obj_key(
+ NixExprBuilder::string(stringify!($field)),
+ NixExprBuilder::field($field),
+ );
+ nix_expr_inner!(@obj($o) $($tt)*);
+ }};
+ (@obj($o:ident) $field:ident: $v:block, $($tt:tt)*) => {{
+ $o.obj_key(
+ NixExprBuilder::string(stringify!($field)),
+ NixExprBuilder::serialized(&$v),
+ );
+ nix_expr_inner!(@obj($o) $($tt)*);
+ }};
+ (@obj($o:ident)) => {{}};
+ (Obj { $($tt:tt)* }) => {{
+ use $crate::{better_nix_eval::NixExprBuilder, nix_expr_inner};
let mut out = NixExprBuilder::object();
- $(
- out.obj_key(
- NixExprBuilder::string(stringify!($ident)),
- $crate::nix_expr_inner!($($val)+),
- );
- )*
+ nix_expr_inner!(@obj(out) $($tt)*);
out.end_obj();
out
}};
@@ -522,6 +536,9 @@
$o.push(Index::ExprApply($crate::nix_expr_inner!($($var)+)));
nix_go!(@o($o) $($tt)*);
};
+ (@o($o:ident) | $($var:tt)*) => {
+ $o.push(Index::Pipe($crate::nix_expr_inner!($($var)+)));
+ };
(@o($o:ident)) => {};
($field:ident $($tt:tt)+) => {{
use $crate::{nix_go, better_nix_eval::Index};
@@ -545,6 +562,7 @@
Apply(String),
Expr(NixExprBuilder),
ExprApply(NixExprBuilder),
+ Pipe(NixExprBuilder),
}
impl Index {
pub fn var(v: impl AsRef<str>) -> Self {
@@ -582,6 +600,9 @@
Index::ExprApply(e) => {
write!(f, "<apply>({})", e.out)
}
+ Index::Pipe(e) => {
+ write!(f, "<map>({})", e.out)
+ }
}
}
}
@@ -604,9 +625,9 @@
session: NixSession,
value: Option<u32>,
}
-fn context(full_path: Option<&[Index]>, query: &str) -> String {
+fn context(op: &str, full_path: Option<&[Index]>, query: &str) -> String {
if let Some(full_path) = &full_path {
- format!("full path: {}", PathDisplay(full_path))
+ format!("on {op}, full path: {}", PathDisplay(full_path))
} else {
format!("query: {query:?}")
}
@@ -628,7 +649,7 @@
.await
.execute_assign(query)
.await
- .with_context(|| context(None, query))?;
+ .with_context(|| context("new root", None, query))?;
Ok(Self(Arc::new(FieldInner {
full_path: None,
session,
@@ -686,6 +707,12 @@
query.push_str(&index);
query = format!("({query})");
}
+ Index::Pipe(v) => {
+ let index = Field::new(self.0.session.clone(), &v.out).await?;
+ used_fields.push(index.clone());
+ let index = format!("sess_field_{}", index.0.value.expect("value"));
+ query = format!("({index} {query})");
+ }
}
}
@@ -720,7 +747,7 @@
.await
.execute_expression_to_json(&query)
.await
- .with_context(|| context(self.0.full_path.as_deref(), &query))
+ .with_context(|| context("as_json", self.0.full_path.as_deref(), &query))
}
pub async fn has_field(&self, name: &str) -> Result<bool> {
let id = self.0.value.expect("can't list root fields");
@@ -733,7 +760,7 @@
.await
.execute_expression_to_json(&query)
.await
- .with_context(|| context(self.0.full_path.as_deref(), &query))
+ .with_context(|| context("has_field", self.0.full_path.as_deref(), &query))
}
pub async fn list_fields(&self) -> Result<Vec<String>> {
let id = self.0.value.expect("can't list root fields");
@@ -745,7 +772,7 @@
.await
.execute_expression_to_json(&query)
.await
- .with_context(|| context(self.0.full_path.as_deref(), &query))
+ .with_context(|| context("list field", self.0.full_path.as_deref(), &query))
}
pub async fn type_of(&self) -> Result<String> {
let id = self.0.value.expect("can't list root fields");
@@ -757,7 +784,11 @@
.await
.execute_expression_to_json(&query)
.await
- .with_context(|| context(self.0.full_path.as_deref(), &query))
+ .with_context(|| context("type_of", self.0.full_path.as_deref(), &query))
+ }
+ pub async fn import(&self) -> Result<Self> {
+ let import = Self::new(self.0.session.clone(), "import").await?;
+ Ok(nix_go!(self | import))
}
pub async fn build(&self) -> Result<HashMap<String, PathBuf>> {
let id = self.0.value.expect("can't use build on not-value");
@@ -773,7 +804,7 @@
ensure!(
!vid.is_empty(),
"build failed: {}",
- context(self.0.full_path.as_deref(), &query),
+ context("build", self.0.full_path.as_deref(), &query),
);
let Some(vid) = vid.strip_prefix("This derivation produced the following outputs:\n")
else {
cmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/build_systems.rs
+++ b/cmds/fleet/src/cmds/build_systems.rs
@@ -53,7 +53,7 @@
fn build_attr(&self) -> String {
match self {
PackageAction::SdImage => "sdImage".to_owned(),
- PackageAction::InstallationCd => "installationCd".to_owned(),
+ PackageAction::InstallationCd => "isoImage".to_owned(),
}
}
}
@@ -178,7 +178,7 @@
if !build.disable_rollback {
let _span = info_span!("preparing").entered();
info!("preparing for rollback");
- let generation = get_current_generation(&host).await?;
+ let generation = get_current_generation(host).await?;
info!(
"rollback target would be {} {}",
generation.id, generation.datetime
@@ -234,7 +234,7 @@
let mut switch_script = built.clone();
switch_script.push("bin");
switch_script.push("switch-to-configuration");
- let mut cmd = host.cmd(switch_script).await?;
+ let mut cmd = host.cmd(switch_script).in_current_span().await?;
cmd.arg(action.name());
if let Err(e) = cmd.sudo().run().in_current_span().await {
error!("failed to activate: {e}");
@@ -285,11 +285,9 @@
info!("building");
let host = config.host(&host).await?;
let action = Action::from(self.subcommand.clone());
- let fleet_field = &config.fleet_field;
+ let fleet_config = &config.config_field;
let drv = nix_go!(
- fleet_field.buildSystems(Obj {
- localSystem: { config.local_system.clone() }
- })[{ action.build_attr() }][{ &host.name }]
+ fleet_config.hosts[{ &host.name }].nixosSystem.config.system.build[{ action.build_attr() }]
);
let outputs = drv.build().await.map_err(|e| {
if action.build_attr() == "sdImage" {
cmds/fleet/src/cmds/info.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/info.rs
+++ b/cmds/fleet/src/cmds/info.rs
@@ -37,9 +37,9 @@
InfoCmd::ListHosts { ref tagged } => {
'host: for host in config.list_hosts().await? {
if !tagged.is_empty() {
- let fleet_field = &config.fleet_field;
+ let config = &config.config_unchecked_field;
let tags: Vec<String> =
- nix_go_json!(fleet_field.configuredSystems[{ host.name }].config.tags);
+ nix_go_json!(config.hosts[{ host.name }].nixosSystem.config.tags);
for tag in tagged {
if !tags.contains(tag) {
continue 'host;
cmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/secrets/mod.rs
+++ b/cmds/fleet/src/cmds/secrets/mod.rs
@@ -10,14 +10,15 @@
use futures::StreamExt;
use itertools::Itertools;
use owo_colors::OwoColorize;
+use serde::Deserialize;
use std::{
- collections::HashSet,
+ collections::{BTreeSet, HashSet},
io::{self, Cursor, Read},
path::PathBuf,
};
use tabled::{Table, Tabled};
use tokio::fs::read_to_string;
-use tracing::{info, info_span, warn};
+use tracing::{error, info, info_span, warn, Instrument};
#[derive(Parser)]
pub enum Secret {
@@ -92,77 +93,182 @@
List {},
}
-async fn generate_shared(
+#[tracing::instrument(skip(config, secret, field, prefer_identities))]
+async fn update_owner_set(
+ secret_name: &str,
config: &Config,
- display_name: &str,
- secret: Field,
+ mut secret: FleetSharedSecret,
+ field: Field,
+ updated_set: &[String],
+ prefer_identities: &[String],
) -> Result<FleetSharedSecret> {
- Ok(if secret.has_field("generateImpure").await? {
- let config_field = &config.config_unchecked_field;
- let generate = nix_go!(secret.generateImpure);
- let owners: Vec<String> = nix_go_json!(secret.expectedOwners);
+ let original_set = secret.owners.clone();
- let on: String = nix_go_json!(generate.on);
- let call_package = nix_go!(
- config_field.buildableSystems(Obj {
- localSystem: { config.local_system.clone() }
- })[{ on }]
- .config
- .nixpkgs
- .resolvedPkgs
- .callPackage
- );
+ let set = original_set.iter().collect::<BTreeSet<_>>();
+ let expected_set = updated_set.iter().collect::<BTreeSet<_>>();
- let host = config.host(&on).await?;
+ if set == expected_set {
+ info!("no need to update owner list, it is already correct");
+ return Ok(secret);
+ }
- let generator = nix_go!(call_package(generate.generator)(Obj {}));
- let generator = generator.build().await?;
- let generator = generator
- .get("out")
- .ok_or_else(|| anyhow!("missing generateImpure out"))?;
- let generator = host.remote_derivation(generator).await?;
+ let should_regenerate = if set.difference(&expected_set).next().is_some() {
+ // TODO: Remove this warning for revokable secrets.
+ warn!("host was removed from secret owners, but until this host rebuild, the secret will still be stored on it.");
+ nix_go_json!(field.regenerateOnOwnerRemoved)
+ } else if expected_set.difference(&set).next().is_some() {
+ nix_go_json!(field.regenerateOnOwnerAdded)
+ } else {
+ false
+ };
+
+ if should_regenerate {
+ info!("secret is owner-dependent, will regenerate");
+ let generated = generate_shared(config, secret_name, field, updated_set.to_vec()).await?;
+ Ok(generated)
+ } else {
+ let identity_holder = if !prefer_identities.is_empty() {
+ prefer_identities
+ .iter()
+ .find(|i| original_set.iter().any(|s| s == *i))
+ } else {
+ secret.owners.first()
+ };
+ let Some(identity_holder) = identity_holder else {
+ bail!("no available holder found");
+ };
- let mut recipients = String::new();
- for owner in &owners {
- let key = config.key(owner).await?;
- recipients.push_str(&format!("-r \"{key}\" "));
+ if let Some(data) = secret.secret.secret {
+ let host = config.host(identity_holder).await?;
+ let encrypted = host.reencrypt(data, updated_set.to_vec()).await?;
+ secret.secret.secret = Some(encrypted);
}
- recipients.push_str("-e");
- let out = host.mktemp_dir().await?;
+ secret.owners = updated_set.to_vec();
+ Ok(secret)
+ }
+}
+
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+enum GeneratorKind {
+ Impure,
+}
+
+async fn generate_impure(
+ config: &Config,
+ _display_name: &str,
+ secret: Field,
+ default_generator: Field,
+ owners: &[String],
+) -> Result<FleetSecret> {
+ let config_field = &config.config_unchecked_field;
+ let generator = nix_go!(secret.generator);
+
+ let on: String = nix_go_json!(default_generator.impureOn);
+ let call_package = nix_go!(
+ config_field.buildableSystems(Obj {
+ localSystem: { config.local_system.clone() },
+ })[{ on }]
+ .config
+ .nixpkgs
+ .resolvedPkgs
+ .callPackage
+ );
+
+ let host = config.host(&on).await?;
+
+ let generator = nix_go!(call_package(generator)(Obj {}));
+ let generator = generator.build().await?;
+ let generator = generator
+ .get("out")
+ .ok_or_else(|| anyhow!("missing generateImpure out"))?;
+ let generator = host.remote_derivation(generator).await?;
+
+ let mut recipients = String::new();
+ for owner in owners {
+ let key = config.key(owner).await?;
+ recipients.push_str(&format!("-r \"{key}\" "));
+ }
+ recipients.push_str("-e");
- let mut gen = host.cmd(generator).await?;
- gen.env("rageArgs", recipients).env("out", &out);
- gen.run().await?;
+ let out = host.mktemp_dir().await?;
- {
- let marker = host.read_file_text(format!("{out}/marker")).await?;
- ensure!(marker == "SUCCESS", "generation not succeeded");
- }
+ let mut gen = host.cmd(generator).await?;
+ gen.env("rageArgs", recipients).env("out", &out);
+ gen.run().await.context("impure generator")?;
- let public = host.read_file_text(format!("{out}/public")).await.ok();
- let secret = host.read_file_bin(format!("{out}/secret")).await.ok();
- if let Some(secret) = &secret {
- ensure!(
- age::Decryptor::new(Cursor::new(&secret)).is_ok(),
- "builder produced non-encrypted value as secret, this is highly insecure"
- );
+ {
+ let marker = host.read_file_text(format!("{out}/marker")).await?;
+ ensure!(marker == "SUCCESS", "generation not succeeded");
+ }
+
+ let public = host.read_file_text(format!("{out}/public")).await.ok();
+ let secret = host.read_file_bin(format!("{out}/secret")).await.ok();
+ if let Some(secret) = &secret {
+ ensure!(
+ age::Decryptor::new(Cursor::new(&secret)).is_ok(),
+ "builder produced non-encrypted value as secret, this is highly insecure, and not allowed."
+ );
+ }
+
+ let created_at = host.read_file_value(format!("{out}/created_at")).await?;
+ let expires_at = host.read_file_value(format!("{out}/expires_at")).await.ok();
+
+ Ok(FleetSecret {
+ created_at,
+ expires_at,
+ public,
+ secret: secret.map(SecretData),
+ })
+}
+async fn generate(
+ config: &Config,
+ display_name: &str,
+ secret: Field,
+ owners: &[String],
+) -> Result<FleetSecret> {
+ let generator = nix_go!(secret.generator);
+ // Can't properly check on nix module system level
+ {
+ let gen_ty = generator.type_of().await?;
+ if gen_ty == "null" {
+ bail!("secret has no generator defined, can't automatically generate it.");
}
+ if gen_ty != "lambda" {
+ bail!("generator should be lambda, got {gen_ty}");
+ }
+ }
+ let default_pkgs = &config.default_pkgs;
+ let default_call_package = nix_go!(default_pkgs.callPackage);
+ // Generators provide additional information in passthru, to access
+ // passthru we should call generator, but information about where this generator is supposed to build
+ // is located in passthru... Thus evaluating generator on host.
+ //
+ // Maybe it is also possible to do some magic with __functor?
+ //
+ // I don't want to make modules always responsible for additional secret data anyway,
+ // so it should be in derivation, and not in the secret data itself.
+ let default_generator = nix_go!(default_call_package(generator)(Obj {}));
- let created_at = host.read_file_value(format!("{out}/created_at")).await?;
- let expires_at = host.read_file_value(format!("{out}/expires_at")).await.ok();
+ let kind: GeneratorKind = nix_go_json!(default_generator.generatorKind);
- FleetSharedSecret {
- owners,
- secret: FleetSecret {
- created_at,
- expires_at,
- public,
- secret: secret.map(SecretData),
- },
+ match kind {
+ GeneratorKind::Impure => {
+ generate_impure(config, display_name, secret, default_generator, owners).await
}
- } else {
- bail!("no generator defined for {display_name}")
+ }
+}
+async fn generate_shared(
+ config: &Config,
+ display_name: &str,
+ secret: Field,
+ expected_owners: Vec<String>,
+) -> Result<FleetSharedSecret> {
+ // let owners: Vec<String> = nix_go_json!(secret.expectedOwners);
+ Ok(FleetSharedSecret {
+ secret: generate(config, display_name, secret, &expected_owners).await?,
+ owners: expected_owners,
})
}
@@ -270,9 +376,7 @@
machines = shared.owners;
}
- let recipients = config
- .recipients(&machines.iter().map(String::as_str).collect_vec())
- .await?;
+ let recipients = config.recipients(machines.clone()).await?;
let secret = {
let mut input = vec![];
@@ -362,7 +466,7 @@
remove_machines,
prefer_identities,
} => {
- let mut secret = config.shared_secret(&name)?;
+ let secret = config.shared_secret(&name)?;
if secret.secret.secret.is_none() {
bail!("no secret");
}
@@ -378,61 +482,84 @@
if target_machines.is_empty() {
info!("no machines left for secret, removing it");
config.remove_shared(&name);
- return Ok(());
- }
-
- if target_machines == initial_machines {
- warn!("secret owners are already correct");
return Ok(());
}
- let identity_holder = if !prefer_identities.is_empty() {
- prefer_identities
- .iter()
- .find(|i| initial_machines.iter().any(|s| s == *i))
- } else {
- secret.owners.first()
- };
- let Some(identity_holder) = identity_holder else {
- bail!("no available holder found");
- };
- let target_recipients = futures::stream::iter(&target_machines)
- .then(|m| async { config.key(m).await })
- .collect::<Vec<_>>()
- .await;
- let target_recipients =
- target_recipients.into_iter().collect::<Result<Vec<_>>>()?;
+ let config_field = &config.config_unchecked_field;
+ let config_field = nix_go!(config_field.configUnchecked);
+ let field = nix_go!(config_field.sharedSecrets[{ name }]);
- if let Some(data) = secret.secret.secret {
- let host = config.host(&identity_holder).await?;
- let encrypted = host.reencrypt(data, target_recipients).await?;
- secret.secret.secret = Some(encrypted);
- }
-
- secret.owners = target_machines;
- config.replace_shared(name, secret);
+ let updated = update_owner_set(
+ &name,
+ config,
+ secret,
+ field,
+ &target_machines,
+ &prefer_identities,
+ )
+ .await?;
+ config.replace_shared(name, updated);
}
Secret::Regenerate { prefer_identities } => {
+ info!("checking for secrets to regenerate");
{
+ let _span = info_span!("shared").entered();
let expected_shared_set = config
.list_configured_shared()
.await?
.into_iter()
.collect::<HashSet<_>>();
let shared_set = config.list_shared().into_iter().collect::<HashSet<_>>();
- for removed in expected_shared_set.difference(&shared_set) {
- info!("generating secret: {removed}");
+ for missing in expected_shared_set.difference(&shared_set) {
let config_field = &config.config_unchecked_field;
let config_field = nix_go!(config_field.configUnchecked);
- let secret = nix_go!(config_field.sharedSecrets[{ removed }]);
- let shared = generate_shared(config, removed, secret).await?;
- config.replace_shared(removed.to_string(), shared)
+ let secret = nix_go!(config_field.sharedSecrets[{ missing }]);
+ let expected_owners: Option<Vec<String>> =
+ nix_go_json!(secret.expectedOwners);
+ let Some(expected_owners) = expected_owners else {
+ // TODO: Might still need to regenerate
+ continue;
+ };
+ info!("generating secret: {missing}");
+ let shared = generate_shared(config, missing, secret, expected_owners)
+ .in_current_span()
+ .await?;
+ config.replace_shared(missing.to_string(), shared)
+ }
+ }
+ for host in config.list_hosts().await? {
+ let _span = info_span!("host", host = host.name).entered();
+ let expected_set = host
+ .list_configured_secrets()
+ .in_current_span()
+ .await?
+ .into_iter()
+ .collect::<HashSet<_>>();
+ let stored_set = config
+ .list_secrets(&host.name)
+ .into_iter()
+ .collect::<HashSet<_>>();
+ for missing in expected_set.difference(&stored_set) {
+ info!("generating secret: {missing}");
+ let secret = host.secret_field(missing).in_current_span().await?;
+ let generated =
+ match generate(config, missing, secret, &[host.name.clone()])
+ .in_current_span()
+ .await
+ {
+ Ok(v) => v,
+ Err(e) => {
+ error!("{e}");
+ continue;
+ }
+ };
+ config.insert_secret(&host.name, missing.to_string(), generated)
}
}
let mut to_remove = Vec::new();
for name in &config.list_shared() {
info!("updating secret: {name}");
- let mut data = config.shared_secret(name)?;
+ let data = config.shared_secret(name)?;
let config_field = &config.config_unchecked_field;
let config_field = nix_go!(config_field.configUnchecked);
let expected_owners: Vec<String> =
@@ -442,55 +569,20 @@
to_remove.push(name.to_string());
continue;
}
- let set = data.owners.iter().collect::<HashSet<_>>();
- let expected_set = expected_owners.iter().collect::<HashSet<_>>();
- let should_remove = set.difference(&expected_set).next().is_some();
- if set == expected_set {
- info!("secret data is ok");
- continue;
- }
let secret = nix_go!(config_field.sharedSecrets[{ name }]);
- let owner_dependent: bool = nix_go_json!(secret.ownerDependent);
- let regenerate_on_remove: bool = nix_go_json!(secret.regenerateOnOwnerRemoved);
- #[allow(clippy::nonminimal_bool)]
- if !owner_dependent && !(should_remove && regenerate_on_remove) {
- warn!("reencrypting secret '{name}' for new owner set");
- // TODO: force regeneration
- if should_remove {
- warn!("secret will not be regenerated for removed machines, and until host rebuild, they will still possess the ability to decode secret");
- }
-
- let identity_holder = if !prefer_identities.is_empty() {
- prefer_identities
- .iter()
- .find(|i| data.owners.iter().any(|s| s == *i))
- } else {
- data.owners.first()
- };
- let Some(identity_holder) = identity_holder else {
- bail!("no available holder found");
- };
-
- let target_recipients = futures::stream::iter(&expected_owners)
- .then(|m| async { config.key(m).await })
- .collect::<Vec<_>>()
- .await;
- let target_recipients =
- target_recipients.into_iter().collect::<Result<Vec<_>>>()?;
-
- if let Some(secret) = data.secret.secret {
- let host = config.host(identity_holder).await?;
- let encrypted = host.reencrypt(secret, target_recipients).await?;
-
- data.secret.secret = Some(encrypted);
- }
- data.owners = expected_owners;
- config.replace_shared(name.to_owned(), data);
- } else {
- let shared = generate_shared(config, name, secret).await?;
- config.replace_shared(name.to_owned(), shared)
- }
+ config.replace_shared(
+ name.to_owned(),
+ update_owner_set(
+ &name,
+ config,
+ data,
+ secret,
+ &expected_owners,
+ &prefer_identities,
+ )
+ .await?,
+ );
}
for k in to_remove {
config.remove_shared(&k);
cmds/fleet/src/command.rsdiffbeforeafterboth--- a/cmds/fleet/src/command.rs
+++ b/cmds/fleet/src/command.rs
@@ -1,5 +1,3 @@
-use std::thread::sleep;
-use std::time::Duration;
use std::{ffi::OsStr, pin, process::Stdio, sync::Arc, task::Poll};
use anyhow::{anyhow, Result};
@@ -9,7 +7,7 @@
use openssh::{OverSsh, OwningCommand, Session};
use tokio::{io::AsyncRead, process::Command, select};
use tokio_util::codec::{BytesCodec, FramedRead, LinesCodec};
-use tracing::{info, debug};
+use tracing::debug;
fn escape_bash(input: &str, out: &mut String) {
const TO_ESCAPE: &str = "$ !\"#&'()*,;<>?[\\]^`{|}";
@@ -162,6 +160,10 @@
self
}
pub fn sudo(mut self) -> Self {
+ // TODO: Multiple escalation strategies.
+ // Maybe escalation should be moved to ConfigHost, to also support cases
+ // when there is no sudo on remote machine, but instead we can reconnect
+ // as root using ssh?
if std::env::var_os("NO_SUDO").is_some() {
let mut out = Self::new("su");
out.ssh_session = self.ssh_session.take();
@@ -267,7 +269,7 @@
) -> Result<Option<Vec<u8>>> {
cmd.stderr(Stdio::piped());
cmd.stdout(Stdio::piped());
- debug!("running command {cmd:?} on local");
+ debug!("running command {str:?} on local");
let mut child = cmd.spawn()?;
let mut stderr = child.stderr.take().unwrap();
let stdout = child.stdout.take().unwrap();
@@ -328,7 +330,7 @@
err_handler: &mut dyn Handler,
mut out_handler: Option<&mut dyn Handler>,
) -> Result<Option<Vec<u8>>> {
- debug!("running command {cmd:?} over ssh");
+ debug!("running command {str:?} over ssh");
cmd.stderr(openssh::Stdio::piped());
cmd.stdout(openssh::Stdio::piped());
let mut child = cmd.spawn().await?;
cmds/fleet/src/host.rsdiffbeforeafterboth--- a/cmds/fleet/src/host.rs
+++ b/cmds/fleet/src/host.rs
@@ -14,6 +14,7 @@
use openssh::SessionBuilder;
use serde::de::DeserializeOwned;
use tempfile::NamedTempFile;
+use tracing::instrument;
use crate::{
better_nix_eval::{Field, NixSessionPool},
@@ -28,12 +29,13 @@
pub opts: FleetOpts,
pub data: Mutex<FleetData>,
pub nix_args: Vec<OsString>,
- /// fleetConfigurations.<name>.<localSystem>
- pub fleet_field: Field,
- /// fleet_config.configUnchecked
+ /// fleet_config.config
pub config_field: Field,
- /// fleet_config.unchecked
+ /// fleet_config.unchecked.config
pub config_unchecked_field: Field,
+
+ /// import nixpkgs {system = local};
+ pub default_pkgs: Field,
}
#[derive(Clone)]
@@ -48,9 +50,12 @@
}
pub struct ConfigHost {
+ config: Config,
pub name: String,
pub local: bool,
pub session: OnceLock<Arc<openssh::Session>>,
+
+ pub nixos_config: Field,
}
impl ConfigHost {
async fn open_session(&self) -> Result<Arc<openssh::Session>> {
@@ -64,7 +69,7 @@
let session = session
.connect(&self.name)
.await
- .map_err(|e| anyhow!("ssh error: {e}"))?;
+ .map_err(|e| anyhow!("ssh error while connecting to {}: {e}", self.name))?;
let session = Arc::new(session);
self.session.set(session.clone()).expect("TOCTOU happened");
Ok(session)
@@ -119,7 +124,8 @@
let mut cmd = self.cmd("fleet-install-secrets").await?;
cmd.arg("reencrypt").eqarg("--secret", data.encode_z85());
for target in targets {
- cmd.eqarg("--targets", target);
+ let key = self.config.key(&target).await?;
+ cmd.eqarg("--targets", key);
}
let encoded = cmd
.sudo()
@@ -139,7 +145,7 @@
.arg("--substitute-on-destination")
.comparg("--to", format!("ssh-ng://{}", self.name))
.arg(path);
- nix.run_nix().await?;
+ nix.run_nix().await.context("nix copy")?;
Ok(path.to_owned())
}
pub async fn systemctl_stop(&self, name: &str) -> Result<()> {
@@ -161,6 +167,25 @@
}
cmd.run().await
}
+
+ pub async fn list_configured_secrets(&self) -> Result<Vec<String>> {
+ let nixos = &self.nixos_config;
+ let secrets = nix_go!(nixos.secrets);
+ let mut out = Vec::new();
+ for name in secrets.list_fields().await? {
+ let secret = nix_go!(secrets[{ name }]);
+ let is_shared: bool = nix_go_json!(secret.shared);
+ if is_shared {
+ continue;
+ }
+ out.push(name);
+ }
+ Ok(out)
+ }
+ pub async fn secret_field(&self, name: &str) -> Result<Field> {
+ let nixos = &self.nixos_config;
+ Ok(nix_go!(nixos.secrets[{ name }]))
+ }
}
impl Config {
@@ -178,28 +203,28 @@
}
pub async fn host(&self, name: &str) -> Result<ConfigHost> {
+ let config = &self.config_unchecked_field;
+ let nixos_config = nix_go!(config.configuredSystems[{ name }].config);
Ok(ConfigHost {
+ config: self.clone(),
name: name.to_owned(),
local: self.is_local(name),
session: OnceLock::new(),
+ nixos_config,
})
}
pub async fn list_hosts(&self) -> Result<Vec<ConfigHost>> {
- let fleet_field = &self.fleet_field;
- let names = nix_go!(fleet_field.configuredHosts).list_fields().await?;
+ let config = &self.config_unchecked_field;
+ let names = nix_go!(config.hosts).list_fields().await?;
let mut out = vec![];
for name in names {
- out.push(ConfigHost {
- local: self.is_local(&name),
- name,
- session: OnceLock::new(),
- })
+ out.push(self.host(&name).await?);
}
Ok(out)
}
pub async fn system_config(&self, host: &str) -> Result<Field> {
- let fleet_field = &self.fleet_field;
- Ok(nix_go!(fleet_field.configuredSystems[{ host }].config))
+ let fleet_field = &self.config_unchecked_field;
+ Ok(nix_go!(fleet_field.hosts[{ host }].nixosSystem.config))
}
pub(super) fn data(&self) -> MutexGuard<FleetData> {
@@ -233,6 +258,14 @@
data.shared_secrets.remove(secret);
}
+ pub fn list_secrets(&self, host: &str) -> Vec<String> {
+ let data = self.data();
+ let Some(secrets) = data.host_secrets.get(host) else {
+ return Vec::new();
+ };
+ secrets.keys().cloned().collect()
+ }
+
pub fn has_secret(&self, host: &str, secret: &str) -> bool {
let data = self.data();
let Some(host_secrets) = data.host_secrets.get(host) else {
@@ -319,18 +352,27 @@
let pool = NixSessionPool::new(directory.as_os_str().to_owned(), nix_args.clone()).await?;
let root_field = pool.get().await?;
+ let builtins_field = Field::field(root_field.clone(), "builtins").await?;
if self.local_system == "detect" {
- let builtins_field = Field::field(root_field.clone(), "builtins").await?;
self.local_system = nix_go_json!(builtins_field.currentSystem);
}
let local_system = self.local_system.clone();
let fleet_root = Field::field(root_field, "fleetConfigurations").await?;
-
let fleet_field = nix_go!(fleet_root.default);
- let config_field = nix_go!(fleet_field.configUnchecked);
- let config_unchecked_field = nix_go!(fleet_field.unchecked);
+ let config_field = nix_go!(fleet_field.config);
+ let config_unchecked_field = nix_go!(fleet_field.unchecked.config);
+
+ let import = nix_go!(builtins_field.import);
+ let overlays = nix_go!(fleet_field.overlays);
+ let nixpkgs = nix_go!(fleet_field.nixpkgs | import);
+
+ let default_pkgs = nix_go!(nixpkgs(Obj {
+ overlays,
+ system: { self.local_system.clone() },
+ }));
+
let mut fleet_data_path = directory.clone();
fleet_data_path.push("fleet.nix");
let bytes = std::fs::read_to_string(fleet_data_path)?;
@@ -342,9 +384,9 @@
data,
local_system,
nix_args,
- fleet_field,
config_field,
config_unchecked_field,
+ default_pkgs,
})))
}
}
cmds/fleet/src/keys.rsdiffbeforeafterboth--- a/cmds/fleet/src/keys.rs
+++ b/cmds/fleet/src/keys.rs
@@ -43,9 +43,9 @@
age::ssh::Recipient::from_str(&key).map_err(|e| anyhow!("parse recipient error: {:?}", e))
}
- pub async fn recipients(&self, hosts: &[&str]) -> Result<Vec<impl Recipient>> {
+ pub async fn recipients(&self, hosts: Vec<String>) -> Result<Vec<impl Recipient>> {
futures::stream::iter(hosts.iter())
- .then(|m| self.recipient(m))
+ .then(|m| self.recipient(m.as_ref()))
.try_collect::<Vec<_>>()
.await
}
cmds/fleet/src/main.rsdiffbeforeafterboth--- a/cmds/fleet/src/main.rs
+++ b/cmds/fleet/src/main.rs
@@ -12,6 +12,8 @@
mod fleetdata;
use std::ffi::OsString;
+use std::io::{stderr, stdout, Write};
+use std::process::exit;
use std::time::Duration;
use anyhow::{bail, Result};
@@ -24,7 +26,7 @@
use host::{Config, FleetOpts};
use human_repr::HumanCount;
use indicatif::{ProgressState, ProgressStyle};
-use tracing::info;
+use tracing::{error, info};
use tracing::{info_span, Instrument};
use tracing_indicatif::IndicatifLayer;
use tracing_subscriber::{prelude::*, EnvFilter};
@@ -81,7 +83,7 @@
}
#[derive(Parser)]
-#[clap(version = "1.0", author)]
+#[clap(version, author)]
struct RootOpts {
#[clap(flatten)]
fleet_opts: FleetOpts,
@@ -136,13 +138,13 @@
),
);
- let filter = EnvFilter::from_default_env();
+ let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
tracing_subscriber::registry()
.with(
tracing_subscriber::fmt::layer()
.without_time()
- .with_target(false)
+ .with_target(true)
.with_writer(indicatif_layer.get_stderr_writer())
.with_filter(filter), // .withou,
)
@@ -151,8 +153,15 @@
}
#[tokio::main]
-async fn main() -> Result<()> {
+async fn main() {
setup_logging();
+ if let Err(e) = main_real().await {
+ error!("{e:#}");
+ exit(1);
+ }
+}
+
+async fn main_real() -> Result<()> {
let _ = better_nix_eval::TOKIO_RUNTIME.set(tokio::runtime::Handle::current());
let nix_args = std::env::var_os("NIX_ARGS")
flake.lockdiffbeforeafterboth--- a/flake.lock
+++ b/flake.lock
@@ -38,11 +38,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1703705939,
- "narHash": "sha256-9s2Ep3NyRDj9HUgfv2TQUwQEanRUAmeXkvKIr/o1XbY=",
+ "lastModified": 1703974965,
+ "narHash": "sha256-dvZjLuAcLnv25bqStTL2ZICC5YSs8aynF5amRM+I6UM=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "1ada32da4ba24d7310653c9ac54888bee463f455",
+ "rev": "9f434bd436e2bb5615827469ed651e30c26daada",
"type": "github"
},
"original": {
@@ -67,11 +67,11 @@
]
},
"locked": {
- "lastModified": 1703643208,
- "narHash": "sha256-UL4KO8JxnD5rOycwHqBAf84lExF1/VnYMDC7b/wpPDU=",
+ "lastModified": 1703902408,
+ "narHash": "sha256-qXdWvu+tlgNjeoz8yQMRKSom6QyRROfgpmeOhwbujqw=",
"owner": "oxalica",
"repo": "rust-overlay",
- "rev": "ce117f3e0de8262be8cd324ee6357775228687cf",
+ "rev": "319f57cd2c34348c55970a4bf2b35afe82088681",
"type": "github"
},
"original": {
flake.nixdiffbeforeafterboth--- a/flake.nix
+++ b/flake.nix
@@ -29,7 +29,7 @@
llvmPkgs = pkgs.buildPackages.llvmPackages_11;
rust =
(pkgs.rustChannelOf {
- date = "2023-12-26";
+ date = "2023-12-29";
channel = "nightly";
})
.default
lib/default.nixdiffbeforeafterboth--- a/lib/default.nix
+++ b/lib/default.nix
@@ -1,18 +1,31 @@
{flake-utils}: {
fleetConfiguration = {
+ # TODO: Provide by fleet, instead of requesting user to provide it.
+ # This is not good that user needs to provide it, as it becomes a flake data, and fleet arbitrarily rewriting it
+ # always dirnets the flake. Instead, fleetConfiguration should return function, parameters of which should be filled
+ # by fleet itself, which is possible since fleet moving to nix repl execution.
data,
nixpkgs,
+ overlays ? [],
hosts,
- ...
- } @ allConfig: let
+ modules,
+ globalModules ? [],
+ }: let
hostNames = nixpkgs.lib.attrNames hosts;
- config = builtins.removeAttrs allConfig ["nixpkgs" "data"];
fleetLib = import ./fleetLib.nix {
inherit nixpkgs hostNames;
};
in let
root = nixpkgs.lib.evalModules {
- modules = (import ../modules/fleet/_modules.nix) ++ [config data];
+ modules =
+ (import ../modules/fleet/_modules.nix)
+ ++ [
+ data
+ ({...}: {
+ inherit globalModules hosts;
+ })
+ ]
+ ++ modules;
specialArgs = {
inherit nixpkgs fleetLib;
};
@@ -25,84 +38,20 @@
withData = {
root,
data,
- }: rec {
+ }: {
configuredHosts = root.config.hosts;
- configuredUncheckedHosts = root.config.hosts;
- configuredSystems = configuredSystemsWithExtraModules [];
- configuredSystemsWithExtraModules = extraModules:
- nixpkgs.lib.listToAttrs (
- map
- (
- name: {
- inherit name;
- value = nixpkgs.lib.nixosSystem {
- system = configuredHosts.${name}.system;
- modules = configuredHosts.${name}.modules ++ extraModules;
- specialArgs = {
- inherit fleetLib;
- fleet = fleetLib.hostsToAttrs (host: configuredSystems.${host}.config);
- };
- };
- }
- )
- (builtins.attrNames root.config.hosts)
- );
- buildableSystems = {localSystem}: let
- buildConfigurationModule = {config, ...}: {
- # Equivalent to nixpkgs.localSystem
- # nixpkgs.system = localSystem;
- nixpkgs.buildPlatform.system = localSystem;
- };
- in
- configuredSystemsWithExtraModules [
- buildConfigurationModule
- ];
- buildSystems = {localSystem}: let
- buildConfigurationModule = {config, ...}: {
- # Equivalent to nixpkgs.localSystem
- # nixpkgs.system = localSystem;
- nixpkgs.buildPlatform.system = localSystem;
- };
- in {
- toplevel = builtins.mapAttrs (_name: value: value.config.system.build.toplevel) (configuredSystemsWithExtraModules [
- buildConfigurationModule
- ({...}: {
- buildTarget = "toplevel";
- })
- ]);
- sdImage = builtins.mapAttrs (_name: value: value.config.system.build.sdImage) (configuredSystemsWithExtraModules [
- buildConfigurationModule
- #(nixpkgs + "/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix")
- ({...}: {
- buildTarget = "sd-image";
- })
- ]);
- installationCd = builtins.mapAttrs (_name: value: value.config.system.build.isoImage) (configuredSystemsWithExtraModules [
- buildConfigurationModule
- (nixpkgs + "/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix")
- ({lib, ...}: {
- buildTarget = "installation-cd";
- # Needed for https://github.com/NixOS/nixpkgs/issues/58959
- boot.supportedFilesystems = lib.mkForce ["btrfs" "reiserfs" "vfat" "f2fs" "xfs" "ntfs" "cifs"];
- })
- ]);
- };
- configUnchecked = root.config;
+ config = root.config;
};
defaultData = withData {
inherit data;
root = checkedRoot;
};
uncheckedData = withData {inherit data root;};
- in rec {
- inherit (defaultData) configuredHosts configuredSystems buildSystems configUnchecked buildableSystems;
+ in {
+ inherit nixpkgs overlays;
+ inherit (defaultData) configuredHosts configuredSystems config buildableSystems;
unchecked = {
- inherit (uncheckedData) configuredHosts configuredSystems buildSystems configUnchecked buildableSystems;
- };
- injectData = data: let
- injectedData = withData data;
- in {
- inherit (injectedData) configuredHosts configuredSystems buildSystems configUnchecked;
+ inherit (uncheckedData) configuredHosts configuredSystems config buildableSystems;
};
};
}
modules/fleet/meta.nixdiffbeforeafterboth--- a/modules/fleet/meta.nix
+++ b/modules/fleet/meta.nix
@@ -1,49 +1,82 @@
-{ lib, fleetLib, config, ... }: with lib;
-let
- host = with types; {
- options = {
- modules = mkOption {
- type = listOf (mkOptionType {
- name = "submodule";
- inherit (submodule { }) check;
- merge = lib.options.mergeOneOption;
- description = "Nixos modules";
- });
- description = "List of nixos modules";
- default = [ ];
- };
- system = mkOption {
- type = str;
- description = "Type of system";
+{
+ lib,
+ fleetLib,
+ config,
+ nixpkgs,
+ ...
+}:
+with lib; let
+ hostModule = with types;
+ {...} @ hostConfig: {
+ options = {
+ modules = mkOption {
+ type = listOf (mkOptionType {
+ name = "submodule";
+ inherit (submodule {}) check;
+ merge = lib.options.mergeOneOption;
+ description = "Nixos modules";
+ });
+ description = "List of nixos modules";
+ default = [];
+ };
+ system = mkOption {
+ type = str;
+ description = "Type of system";
+ };
+ encryptionKey = mkOption {
+ type = str;
+ description = "Encryption key";
+ };
+ nixosSystem = mkOption {
+ type = unspecified;
+ description = "Nixos configuration";
+ };
};
- encryptionKey = mkOption {
- type = str;
- description = "Encryption key";
+ config.nixosSystem = nixpkgs.lib.nixosSystem {
+ inherit (hostConfig.config) system modules;
+ specialArgs = {
+ inherit fleetLib;
+ fleet = fleetLib.hostsToAttrs (host: config.hosts.${host}.nixosSystem.config);
+ };
};
};
+ overlayType = mkOptionType {
+ name = "nixpkgs-overlay";
+ description = "nixpkgs overlay";
+ check = lib.isFunction;
+ merge = lib.mergeOneOption;
};
-in
-{
+in {
options = with types; {
hosts = mkOption {
- type = attrsOf (submodule host);
- default = { };
+ type = attrsOf (submodule hostModule);
+ default = {};
description = "Configurations of individual hosts";
};
globalModules = mkOption {
type = listOf (mkOptionType {
name = "submodule";
- inherit (submodule { }) check;
+ inherit (submodule {}) check;
merge = lib.options.mergeOneOption;
description = "Nixos modules";
});
description = "Modules, which should be added to every system";
- default = [ ];
+ default = [];
};
+ overlays = mkOption {
+ default = [];
+ type = listOf overlayType;
+ };
};
config = {
hosts = fleetLib.hostsToAttrs (host: {
- modules = config.globalModules;
+ modules =
+ config.globalModules
+ ++ [
+ ({...}: {
+ nixpkgs.overlays = config.overlays;
+ })
+ ];
});
globalModules = import ../../nixos/modules/module-list.nix;
};
modules/fleet/secrets.nixdiffbeforeafterboth--- a/modules/fleet/secrets.nix
+++ b/modules/fleet/secrets.nix
@@ -1,69 +1,48 @@
{ lib, fleetLib, config, ... }: with lib; with fleetLib;
let
- sharedSecret = with types; {
+ sharedSecret = with types; ({config, ...}: {
options = {
expectedOwners = mkOption {
- type = listOf str;
+ type = nullOr (listOf str);
description = ''
- List of hosts to encrypt secret for
+ List of hosts to encrypt secret for. null if managed by user (= via owners field from fleet.nix)
Secrets would be decrypted and stored to /run/secrets/$\{name} on owners
'';
- default = [ ];
};
- ownerDependent = mkOption {
+ # TODO: Aren't those options may be just desugared to data/expectedData?
+ regenerateOnOwnerAdded = mkOption {
type = bool;
- description = "Is this secret owner-dependent, and needs to be regenerated on ownership set change, or it may be just reencrypted";
+ description = ''
+ Is this secret owner-dependent, and needs to be regenerated on ownership set change, or it may be just reencrypted.
+
+ You want to have this option set to true, when this secret contains some reference to its owners, i.e x509 SANs.
+ '';
};
- generateImpure = mkOption {
- type = unspecified;
+ regenerateOnOwnerRemoved = mkOption {
+ default = config.regenerateOnOwnerAdded;
+ type = bool;
+ description = ''
+ Should this secret be removed on owner removal, or it may be just reencrypted
+
+ Most probably its value should be equal to regenerateOnOwnerAdded, override only if you know what are you doing.
+ Contrary to regenerateOnOwnerAdded, you may want to set this option to false, when host permissions are revoked
+ in some other way than by this secret ownership, I.e by firewall/etc.
+ '';
};
generator = mkOption {
- type = nullOr (submodule {
- packages = mkOption {
- type = attrsOf package;
- description = ''
- Derivation to execute for shared secret generation (key = system).
- This derivation should produce directory, with exactly two files:
- - publicData
- - encryptedSecretData
-
- If null - secret value may only be created manually.
- '';
- };
- expectedData = mkOption {
- type = types.unspecified;
- description = "Data expected to be used for secret generation, if doesn't match specified - secret should be regenerated";
- };
- dependencies = mkOption {
- type = listOf str;
- description = ''
- List of secrets, on which this secret depends.
-
- During generation, generator command will be ran on host, which already has specified secrets generated.
- '';
- default = [];
- };
- data = mkOption {
- type = types.unspecified;
- description = "Data used for secret generation. Imported from fleet.nix";
- default = null;
- internal = true;
- };
- });
- default = null;
- };
- expireIn = mkOption {
- type = nullOr int;
- description = "Time in hours, in which this secret should be regenerated";
+ type = nullOr unspecified;
+ description = "Derivation to evaluate for secret generation";
default = null;
};
createdAt = mkOption {
type = nullOr str;
+ description = "When this secret was (re)generated";
default = null;
};
expiresAt = mkOption {
type = nullOr str;
+ description = "On which date this secret will expire, someone should regenerate this secret before it expires.";
default = null;
};
@@ -78,6 +57,9 @@
'';
default = [ ];
};
+ # TODO: Make secret generator generate arbitrary number of secret/public parts?
+ # Make it generate a folder, where all files except suffixed by .enc are public, and the rest are secret?
+ # How should modules refer to those files then?
public = mkOption {
type = nullOr str;
description = "Secret public data. Imported from fleet.nix";
@@ -90,7 +72,7 @@
internal = true;
};
};
- };
+ });
hostSecret = with types; {
options = {
createdAt = mkOption {
@@ -132,7 +114,7 @@
config = {
assertions = mapAttrsToList
(name: secret: {
- assertion = builtins.sort (a: b: a < b) secret.owners == builtins.sort (a: b: a < b) secret.expectedOwners;
+ assertion = secret.expectedOwners == null || builtins.sort (a: b: a < b) secret.owners == builtins.sort (a: b: a < b) secret.expectedOwners;
message = "Shared secret ${name} is expected to be encrypted for ${builtins.toJSON secret.expectedOwners}, but it is encrypted for ${builtins.toJSON secret.owners}. Run fleet secrets regenerate to fix";
})
config.sharedSecrets;
@@ -141,6 +123,7 @@
let
cleanupSecret = (secretName: v: {
inherit (v) public secret;
+ shared = true;
});
in
[
nixos/secrets.nixdiffbeforeafterboth--- a/nixos/secrets.nix
+++ b/nixos/secrets.nix
@@ -5,7 +5,7 @@
let
sysConfig = config;
secretType = types.submodule ({ config, ... }: {
- config = let secretName = config._module.args.name; in rec {
+ config = let secretName = config._module.args.name; in {
stableSecretPath = mkOptionDefault "/run/secrets/secret-stable-${secretName}";
secretPath = mkOptionDefault "/run/secrets/secret-${config.secretHash}-${secretName}";
secretHash = mkOptionDefault (if config.secret != null then (builtins.hashString "sha1" config.secret) else throw "secret is not defined for secret ${secretName}");
@@ -14,63 +14,74 @@
publicPath = mkOptionDefault "/run/secrets/public-${config.publicHash}-${secretName}";
publicHash = mkOptionDefault (if config.public != null then (builtins.hashString "sha1" config.public) else throw "public is not defined for secret ${secretName}");
};
- options = {
+ options = with types; {
+ shared = mkOption {
+ description = "Is this secret owned by this machine, or propagated from shared secrets";
+ default = false;
+ };
+
+ generator = mkOption {
+ type = nullOr unspecified;
+ description = "Derivation to evaluate for secret generation";
+ default = null;
+ };
+
public = mkOption {
- type = types.nullOr types.str;
+ type = nullOr str;
description = "Secret public data";
default = null;
};
secret = mkOption {
- type = types.nullOr types.str;
+ type = nullOr str;
description = "Encrypted secret data";
default = null;
};
mode = mkOption {
- type = types.str;
+ type = str;
description = "Secret mode";
default = "0440";
};
owner = mkOption {
- type = types.str;
+ type = str;
description = "Owner of the secret";
default = "root";
};
group = mkOption {
- type = types.str;
+ type = str;
description = "Group of the secret";
default = sysConfig.users.users.${config.owner}.group;
};
secretHash = mkOption {
- type = types.str;
+ type = str;
description = "Hash of .secret field";
};
publicHash = mkOption {
- type = types.str;
+ type = str;
description = "Hash of .public field";
};
stableSecretPath = mkOption {
- type = types.str;
+ type = str;
description = ''
Use this, if target process supports re-reading of secret from disk,
and doesn't needs to be restarted when secret is updated in file
'';
};
secretPath = mkOption {
- type = types.str;
+ type = str;
description = "Path to decrypted secret, suffixed with contents hash";
};
stablePublicPath = mkOption {
- type = types.str;
+ type = str;
description = ''
Use this, if target process supports re-reading of secret from disk,
and doesn't needs to be restarted when secret is updated in file
'';
};
publicPath = mkOption {
- type = types.str;
+ type = str;
description = "Path to the public part of secret";
};
};