difftreelog
refactor replace eval with repl where possible
in: trunk
22 files changed
Cargo.lockdiffbeforeafterboth2# It is not intended for manual editing.2# It is not intended for manual editing.3version = 33version = 345[[package]]6name = "abort-on-drop"7version = "0.2.2"8source = "registry+https://github.com/rust-lang/crates.io-index"9checksum = "5dd6d700ad9af641490c1f7d67980d2de4d1433016e5b12f819448d3c832142a"10dependencies = [11 "tokio",12]4135[[package]]14[[package]]6name = "addr2line"15name = "addr2line"140 "libc",149 "libc",141]150]151152[[package]]153name = "ansi-str"154version = "0.8.0"155source = "registry+https://github.com/rust-lang/crates.io-index"156checksum = "1cf4578926a981ab0ca955dc023541d19de37112bc24c1a197bd806d3d86ad1d"157dependencies = [158 "ansitok",159]160161[[package]]162name = "ansitok"163version = "0.2.0"164source = "registry+https://github.com/rust-lang/crates.io-index"165checksum = "220044e6a1bb31ddee4e3db724d29767f352de47445a6cd75e1a173142136c83"166dependencies = [167 "nom",168 "vte 0.10.1",169]142170143[[package]]171[[package]]144name = "anstream"172name = "anstream"145version = "0.5.0"173version = "0.6.4"146source = "registry+https://github.com/rust-lang/crates.io-index"174source = "registry+https://github.com/rust-lang/crates.io-index"147checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"175checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"148dependencies = [176dependencies = [149 "anstyle",177 "anstyle",150 "anstyle-parse",178 "anstyle-parse",156184157[[package]]185[[package]]158name = "anstyle"186name = "anstyle"159version = "1.0.3"187version = "1.0.4"160source = "registry+https://github.com/rust-lang/crates.io-index"188source = "registry+https://github.com/rust-lang/crates.io-index"161checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"189checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"162190163[[package]]191[[package]]164name = "anstyle-parse"192name = "anstyle-parse"165version = "0.2.1"193version = "0.2.2"166source = "registry+https://github.com/rust-lang/crates.io-index"194source = "registry+https://github.com/rust-lang/crates.io-index"167checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"195checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"168dependencies = [196dependencies = [169 "utf8parse",197 "utf8parse",170]198]180208181[[package]]209[[package]]182name = "anstyle-wincon"210name = "anstyle-wincon"183version = "2.1.0"211version = "3.0.1"184source = "registry+https://github.com/rust-lang/crates.io-index"212source = "registry+https://github.com/rust-lang/crates.io-index"185checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"213checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"186dependencies = [214dependencies = [187 "anstyle",215 "anstyle",188 "windows-sys 0.48.0",216 "windows-sys 0.48.0",200source = "registry+https://github.com/rust-lang/crates.io-index"228source = "registry+https://github.com/rust-lang/crates.io-index"201checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"229checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"230231[[package]]232name = "arrayvec"233version = "0.5.2"234source = "registry+https://github.com/rust-lang/crates.io-index"235checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"202236203[[package]]237[[package]]204name = "arrayvec"238name = "arrayvec"208242209[[package]]243[[package]]210name = "async-trait"244name = "async-trait"211version = "0.1.73"245version = "0.1.74"212source = "registry+https://github.com/rust-lang/crates.io-index"246source = "registry+https://github.com/rust-lang/crates.io-index"213checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"247checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"214dependencies = [248dependencies = [215 "proc-macro2",249 "proc-macro2",216 "quote",250 "quote",217 "syn 2.0.37",251 "syn 2.0.38",218]252]253254[[package]]255name = "atty"256version = "0.2.14"257source = "registry+https://github.com/rust-lang/crates.io-index"258checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"259dependencies = [260 "hermit-abi 0.1.19",261 "libc",262 "winapi",263]219264220[[package]]265[[package]]221name = "autocfg"266name = "autocfg"246291247[[package]]292[[package]]248name = "base64"293name = "base64"249version = "0.21.4"294version = "0.21.5"250source = "registry+https://github.com/rust-lang/crates.io-index"295source = "registry+https://github.com/rust-lang/crates.io-index"251checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2"296checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"252297253[[package]]298[[package]]254name = "base64ct"299name = "base64ct"281326282[[package]]327[[package]]283name = "bitflags"328name = "bitflags"284version = "2.4.0"329version = "2.4.1"285source = "registry+https://github.com/rust-lang/crates.io-index"330source = "registry+https://github.com/rust-lang/crates.io-index"286checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"331checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"287dependencies = [332dependencies = [288 "serde",333 "serde",289]334]322source = "registry+https://github.com/rust-lang/crates.io-index"367source = "registry+https://github.com/rust-lang/crates.io-index"323checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"368checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"369370[[package]]371name = "bytecount"372version = "0.6.7"373source = "registry+https://github.com/rust-lang/crates.io-index"374checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205"324375325[[package]]376[[package]]326name = "byteorder"377name = "byteorder"419470420[[package]]471[[package]]421name = "clap"472name = "clap"422version = "4.4.4"473version = "4.4.7"423source = "registry+https://github.com/rust-lang/crates.io-index"474source = "registry+https://github.com/rust-lang/crates.io-index"424checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"475checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"425dependencies = [476dependencies = [426 "clap_builder",477 "clap_builder",427 "clap_derive",478 "clap_derive",428]479]429480430[[package]]481[[package]]431name = "clap_builder"482name = "clap_builder"432version = "4.4.4"483version = "4.4.7"433source = "registry+https://github.com/rust-lang/crates.io-index"484source = "registry+https://github.com/rust-lang/crates.io-index"434checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"485checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"435dependencies = [486dependencies = [436 "anstream",487 "anstream",437 "anstyle",488 "anstyle",444495445[[package]]496[[package]]446name = "clap_derive"497name = "clap_derive"447version = "4.4.2"498version = "4.4.7"448source = "registry+https://github.com/rust-lang/crates.io-index"499source = "registry+https://github.com/rust-lang/crates.io-index"449checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"500checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"450dependencies = [501dependencies = [451 "heck",502 "heck",452 "proc-macro2",503 "proc-macro2",453 "quote",504 "quote",454 "syn 2.0.37",505 "syn 2.0.38",455]506]456507457[[package]]508[[package]]458name = "clap_lex"509name = "clap_lex"459version = "0.5.1"510version = "0.6.0"460source = "registry+https://github.com/rust-lang/crates.io-index"511source = "registry+https://github.com/rust-lang/crates.io-index"461checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"512checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"462513463[[package]]514[[package]]464name = "colorchoice"515name = "colorchoice"552checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"603checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"553dependencies = [604dependencies = [554 "cfg-if",605 "cfg-if",555 "hashbrown 0.14.0",606 "hashbrown 0.14.1",556 "lock_api",607 "lock_api",557 "once_cell",608 "once_cell",558 "parking_lot_core",609 "parking_lot_core",570621571[[package]]622[[package]]572name = "deranged"623name = "deranged"573version = "0.3.8"624version = "0.3.9"574source = "registry+https://github.com/rust-lang/crates.io-index"625source = "registry+https://github.com/rust-lang/crates.io-index"575checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"626checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"576dependencies = [627dependencies = [628 "powerfmt",577 "serde",629 "serde",578]630]579631606dependencies = [658dependencies = [607 "proc-macro2",659 "proc-macro2",608 "quote",660 "quote",609 "syn 2.0.37",661 "syn 2.0.38",610]662]611663612[[package]]664[[package]]642694643[[package]]695[[package]]644name = "errno"696name = "errno"645version = "0.3.3"697version = "0.3.5"646source = "registry+https://github.com/rust-lang/crates.io-index"698source = "registry+https://github.com/rust-lang/crates.io-index"647checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"699checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"648dependencies = [700dependencies = [649 "errno-dragonfly",650 "libc",701 "libc",651 "windows-sys 0.48.0",702 "windows-sys 0.48.0",652]703]653654[[package]]655name = "errno-dragonfly"656version = "0.1.2"657source = "registry+https://github.com/rust-lang/crates.io-index"658checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"659dependencies = [660 "cc",661 "libc",662]663704664[[package]]705[[package]]665name = "fastrand"706name = "fastrand"666version = "2.0.0"707version = "2.0.1"667source = "registry+https://github.com/rust-lang/crates.io-index"708source = "registry+https://github.com/rust-lang/crates.io-index"668checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"709checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"669710670[[package]]711[[package]]671name = "find-crate"712name = "find-crate"680name = "fleet"721name = "fleet"681version = "0.1.0"722version = "0.1.0"682dependencies = [723dependencies = [724 "abort-on-drop",683 "age",725 "age",684 "age-core",726 "age-core",685 "anyhow",727 "anyhow",686 "async-trait",728 "async-trait",687 "base64 0.21.4",729 "base64 0.21.5",688 "chrono",730 "chrono",689 "clap",731 "clap",690 "futures",732 "futures",693 "itertools",735 "itertools",694 "nixlike",736 "nixlike",695 "once_cell",737 "once_cell",738 "owo-colors",696 "peg",739 "peg",740 "r2d2",697 "serde",741 "serde",698 "serde_json",742 "serde_json",743 "shlex",744 "tabled",699 "tempfile",745 "tempfile",700 "time",746 "time",701 "tokio",747 "tokio",702 "tokio-util",748 "tokio-util",703 "tracing",749 "tracing",704 "tracing-indicatif",750 "tracing-indicatif",705 "tracing-subscriber",751 "tracing-subscriber",752 "unindent",706 "z85",753 "z85",707]754]708755766 "thiserror",813 "thiserror",767]814]815816[[package]]817name = "fnv"818version = "1.0.7"819source = "registry+https://github.com/rust-lang/crates.io-index"820checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"768821769[[package]]822[[package]]770name = "futures"823name = "futures"771version = "0.3.28"824version = "0.3.29"772source = "registry+https://github.com/rust-lang/crates.io-index"825source = "registry+https://github.com/rust-lang/crates.io-index"773checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"826checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"774dependencies = [827dependencies = [775 "futures-channel",828 "futures-channel",776 "futures-core",829 "futures-core",783836784[[package]]837[[package]]785name = "futures-channel"838name = "futures-channel"786version = "0.3.28"839version = "0.3.29"787source = "registry+https://github.com/rust-lang/crates.io-index"840source = "registry+https://github.com/rust-lang/crates.io-index"788checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"841checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"789dependencies = [842dependencies = [790 "futures-core",843 "futures-core",791 "futures-sink",844 "futures-sink",792]845]793846794[[package]]847[[package]]795name = "futures-core"848name = "futures-core"796version = "0.3.28"849version = "0.3.29"797source = "registry+https://github.com/rust-lang/crates.io-index"850source = "registry+https://github.com/rust-lang/crates.io-index"798checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"851checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"799852800[[package]]853[[package]]801name = "futures-executor"854name = "futures-executor"802version = "0.3.28"855version = "0.3.29"803source = "registry+https://github.com/rust-lang/crates.io-index"856source = "registry+https://github.com/rust-lang/crates.io-index"804checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"857checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"805dependencies = [858dependencies = [806 "futures-core",859 "futures-core",807 "futures-task",860 "futures-task",810863811[[package]]864[[package]]812name = "futures-io"865name = "futures-io"813version = "0.3.28"866version = "0.3.29"814source = "registry+https://github.com/rust-lang/crates.io-index"867source = "registry+https://github.com/rust-lang/crates.io-index"815checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"868checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"816869817[[package]]870[[package]]818name = "futures-macro"871name = "futures-macro"819version = "0.3.28"872version = "0.3.29"820source = "registry+https://github.com/rust-lang/crates.io-index"873source = "registry+https://github.com/rust-lang/crates.io-index"821checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"874checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"822dependencies = [875dependencies = [823 "proc-macro2",876 "proc-macro2",824 "quote",877 "quote",825 "syn 2.0.37",878 "syn 2.0.38",826]879]827880828[[package]]881[[package]]829name = "futures-sink"882name = "futures-sink"830version = "0.3.28"883version = "0.3.29"831source = "registry+https://github.com/rust-lang/crates.io-index"884source = "registry+https://github.com/rust-lang/crates.io-index"832checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"885checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"833886834[[package]]887[[package]]835name = "futures-task"888name = "futures-task"836version = "0.3.28"889version = "0.3.29"837source = "registry+https://github.com/rust-lang/crates.io-index"890source = "registry+https://github.com/rust-lang/crates.io-index"838checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"891checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"839892840[[package]]893[[package]]841name = "futures-util"894name = "futures-util"842version = "0.3.28"895version = "0.3.29"843source = "registry+https://github.com/rust-lang/crates.io-index"896source = "registry+https://github.com/rust-lang/crates.io-index"844checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"897checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"845dependencies = [898dependencies = [846 "futures-channel",899 "futures-channel",847 "futures-core",900 "futures-core",911964912[[package]]965[[package]]913name = "hashbrown"966name = "hashbrown"914version = "0.14.0"967version = "0.14.1"915source = "registry+https://github.com/rust-lang/crates.io-index"968source = "registry+https://github.com/rust-lang/crates.io-index"916checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"969checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"917970918[[package]]971[[package]]919name = "heck"972name = "heck"920version = "0.4.1"973version = "0.4.1"921source = "registry+https://github.com/rust-lang/crates.io-index"974source = "registry+https://github.com/rust-lang/crates.io-index"922checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"975checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"976977[[package]]978name = "hermit-abi"979version = "0.1.19"980source = "registry+https://github.com/rust-lang/crates.io-index"981checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"982dependencies = [983 "libc",984]923985924[[package]]986[[package]]925name = "hermit-abi"987name = "hermit-abi"1014 "proc-macro2",1076 "proc-macro2",1015 "quote",1077 "quote",1016 "strsim",1078 "strsim",1017 "syn 2.0.37",1079 "syn 2.0.38",1018 "unic-langid",1080 "unic-langid",1019]1081]102010821028 "i18n-config",1090 "i18n-config",1029 "proc-macro2",1091 "proc-macro2",1030 "quote",1092 "quote",1031 "syn 2.0.37",1093 "syn 2.0.38",1032]1094]103310951034[[package]]1096[[package]]105611181057[[package]]1119[[package]]1058name = "indexmap"1120name = "indexmap"1059version = "2.0.0"1121version = "2.0.2"1060source = "registry+https://github.com/rust-lang/crates.io-index"1122source = "registry+https://github.com/rust-lang/crates.io-index"1061checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"1123checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"1062dependencies = [1124dependencies = [1063 "equivalent",1125 "equivalent",1064 "hashbrown 0.14.0",1126 "hashbrown 0.14.1",1065]1127]106611281067[[package]]1129[[package]]1128source = "registry+https://github.com/rust-lang/crates.io-index"1190source = "registry+https://github.com/rust-lang/crates.io-index"1129checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"1191checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"1130dependencies = [1192dependencies = [1131 "hermit-abi",1193 "hermit-abi 0.3.3",1132 "rustix",1194 "rustix",1133 "windows-sys 0.48.0",1195 "windows-sys 0.48.0",1134]1196]11971198[[package]]1199name = "is_ci"1200version = "1.1.1"1201source = "registry+https://github.com/rust-lang/crates.io-index"1202checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"113512031136[[package]]1204[[package]]1137name = "itertools"1205name = "itertools"116812361169[[package]]1237[[package]]1170name = "libc"1238name = "libc"1171version = "0.2.148"1239version = "0.2.149"1172source = "registry+https://github.com/rust-lang/crates.io-index"1240source = "registry+https://github.com/rust-lang/crates.io-index"1173checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"1241checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"117412421175[[package]]1243[[package]]1176name = "libm"1244name = "libm"119612641197[[package]]1265[[package]]1198name = "linux-raw-sys"1266name = "linux-raw-sys"1199version = "0.4.7"1267version = "0.4.10"1200source = "registry+https://github.com/rust-lang/crates.io-index"1268source = "registry+https://github.com/rust-lang/crates.io-index"1201checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"1269checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"120212701203[[package]]1271[[package]]1204name = "lock_api"1272name = "lock_api"123313011234[[package]]1302[[package]]1235name = "memchr"1303name = "memchr"1236version = "2.6.3"1304version = "2.6.4"1237source = "registry+https://github.com/rust-lang/crates.io-index"1305source = "registry+https://github.com/rust-lang/crates.io-index"1238checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"1306checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"123913071240[[package]]1308[[package]]1241name = "memoffset"1309name = "memoffset"1246 "autocfg",1314 "autocfg",1247]1315]12481249[[package]]1250name = "memoffset"1251version = "0.7.1"1252source = "registry+https://github.com/rust-lang/crates.io-index"1253checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"1254dependencies = [1255 "autocfg",1256]125713161258[[package]]1317[[package]]1259name = "mimalloc"1318name = "mimalloc"129213511293[[package]]1352[[package]]1294name = "nix"1353name = "nix"1295version = "0.26.4"1354version = "0.27.1"1296source = "registry+https://github.com/rust-lang/crates.io-index"1355source = "registry+https://github.com/rust-lang/crates.io-index"1297checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"1356checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"1298dependencies = [1357dependencies = [1299 "bitflags 1.3.2",1358 "bitflags 2.4.1",1300 "cfg-if",1359 "cfg-if",1301 "libc",1360 "libc",1302 "memoffset 0.7.1",1303 "pin-utils",1304]1361]130513621306[[package]]1363[[package]]1310 "alejandra",1367 "alejandra",1311 "linked-hash-map",1368 "linked-hash-map",1312 "peg",1369 "peg",1313 "rnix",1314 "ron",1370 "ron",1315 "serde",1371 "serde",1316 "serde-transcode",1372 "serde-transcode",137814341379[[package]]1435[[package]]1380name = "num-traits"1436name = "num-traits"1381version = "0.2.16"1437version = "0.2.17"1382source = "registry+https://github.com/rust-lang/crates.io-index"1438source = "registry+https://github.com/rust-lang/crates.io-index"1383checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"1439checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"1384dependencies = [1440dependencies = [1385 "autocfg",1441 "autocfg",1386 "libm",1442 "libm",1392source = "registry+https://github.com/rust-lang/crates.io-index"1448source = "registry+https://github.com/rust-lang/crates.io-index"1393checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"1449checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"1394dependencies = [1450dependencies = [1395 "hermit-abi",1451 "hermit-abi 0.3.3",1396 "libc",1452 "libc",1397]1453]139814541429source = "registry+https://github.com/rust-lang/crates.io-index"1485source = "registry+https://github.com/rust-lang/crates.io-index"1430checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"1486checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"14871488[[package]]1489name = "owo-colors"1490version = "3.5.0"1491source = "registry+https://github.com/rust-lang/crates.io-index"1492checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"1493dependencies = [1494 "supports-color",1495]14961497[[package]]1498name = "papergrid"1499version = "0.10.0"1500source = "registry+https://github.com/rust-lang/crates.io-index"1501checksum = "a2ccbe15f2b6db62f9a9871642746427e297b0ceb85f9a7f1ee5ff47d184d0c8"1502dependencies = [1503 "ansi-str",1504 "ansitok",1505 "bytecount",1506 "fnv",1507 "unicode-width",1508]143115091432[[package]]1510[[package]]1433name = "parking_lot"1511name = "parking_lot"1447dependencies = [1525dependencies = [1448 "cfg-if",1526 "cfg-if",1449 "libc",1527 "libc",1450 "redox_syscall",1528 "redox_syscall 0.3.5",1451 "smallvec",1529 "smallvec",1452 "windows-targets 0.48.5",1530 "windows-targets 0.48.5",1453]1531]146315411464[[package]]1542[[package]]1465name = "peg"1543name = "peg"1466version = "0.8.1"1544version = "0.8.2"1467source = "registry+https://github.com/rust-lang/crates.io-index"1545source = "registry+https://github.com/rust-lang/crates.io-index"1468checksum = "a07f2cafdc3babeebc087e499118343442b742cc7c31b4d054682cc598508554"1546checksum = "400bcab7d219c38abf8bd7cc2054eb9bbbd4312d66f6a5557d572a203f646f61"1469dependencies = [1547dependencies = [1470 "peg-macros",1548 "peg-macros",1471 "peg-runtime",1549 "peg-runtime",1472]1550]147315511474[[package]]1552[[package]]1475name = "peg-macros"1553name = "peg-macros"1476version = "0.8.1"1554version = "0.8.2"1477source = "registry+https://github.com/rust-lang/crates.io-index"1555source = "registry+https://github.com/rust-lang/crates.io-index"1478checksum = "4a90084dc05cf0428428e3d12399f39faad19b0909f64fb9170c9fdd6d9cd49b"1556checksum = "46e61cce859b76d19090f62da50a9fe92bab7c2a5f09e183763559a2ac392c90"1479dependencies = [1557dependencies = [1480 "peg-runtime",1558 "peg-runtime",1481 "proc-macro2",1559 "proc-macro2",148415621485[[package]]1563[[package]]1486name = "peg-runtime"1564name = "peg-runtime"1487version = "0.8.1"1565version = "0.8.2"1488source = "registry+https://github.com/rust-lang/crates.io-index"1566source = "registry+https://github.com/rust-lang/crates.io-index"1489checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739"1567checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922"149015681491[[package]]1569[[package]]1492name = "pin-project"1570name = "pin-project"1505dependencies = [1583dependencies = [1506 "proc-macro2",1584 "proc-macro2",1507 "quote",1585 "quote",1508 "syn 2.0.37",1586 "syn 2.0.38",1509]1587]151015881511[[package]]1589[[package]]1571source = "registry+https://github.com/rust-lang/crates.io-index"1649source = "registry+https://github.com/rust-lang/crates.io-index"1572checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b"1650checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b"16511652[[package]]1653name = "powerfmt"1654version = "0.2.0"1655source = "registry+https://github.com/rust-lang/crates.io-index"1656checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"157316571574[[package]]1658[[package]]1575name = "ppv-lite86"1659name = "ppv-lite86"160316871604[[package]]1688[[package]]1605name = "proc-macro2"1689name = "proc-macro2"1606version = "1.0.67"1690version = "1.0.69"1607source = "registry+https://github.com/rust-lang/crates.io-index"1691source = "registry+https://github.com/rust-lang/crates.io-index"1608checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"1692checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"1609dependencies = [1693dependencies = [1610 "unicode-ident",1694 "unicode-ident",1611]1695]1619 "proc-macro2",1703 "proc-macro2",1620]1704]17051706[[package]]1707name = "r2d2"1708version = "0.8.10"1709source = "registry+https://github.com/rust-lang/crates.io-index"1710checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"1711dependencies = [1712 "log",1713 "parking_lot",1714 "scheduled-thread-pool",1715]162117161622[[package]]1717[[package]]1623name = "rand"1718name = "rand"1699 "bitflags 1.3.2",1794 "bitflags 1.3.2",1700]1795]17961797[[package]]1798name = "redox_syscall"1799version = "0.4.1"1800source = "registry+https://github.com/rust-lang/crates.io-index"1801checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"1802dependencies = [1803 "bitflags 1.3.2",1804]170118051702[[package]]1806[[package]]1703name = "regex"1807name = "regex"1760source = "registry+https://github.com/rust-lang/crates.io-index"1864source = "registry+https://github.com/rust-lang/crates.io-index"1761checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"1865checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"1762dependencies = [1866dependencies = [1763 "base64 0.21.4",1867 "base64 0.21.5",1764 "bitflags 2.4.0",1868 "bitflags 2.4.1",1765 "serde",1869 "serde",1766 "serde_derive",1870 "serde_derive",1767]1871]1774dependencies = [1878dependencies = [1775 "countme",1879 "countme",1776 "hashbrown 0.9.1",1880 "hashbrown 0.9.1",1777 "memoffset 0.6.5",1881 "memoffset",1778 "rustc-hash",1882 "rustc-hash",1779 "text-size",1883 "text-size",1780]1884]1820 "proc-macro2",1924 "proc-macro2",1821 "quote",1925 "quote",1822 "rust-embed-utils",1926 "rust-embed-utils",1823 "syn 2.0.37",1927 "syn 2.0.38",1824 "walkdir",1928 "walkdir",1825]1929]18261930184819521849[[package]]1953[[package]]1850name = "rustix"1954name = "rustix"1851version = "0.38.14"1955version = "0.38.21"1852source = "registry+https://github.com/rust-lang/crates.io-index"1956source = "registry+https://github.com/rust-lang/crates.io-index"1853checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f"1957checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"1854dependencies = [1958dependencies = [1855 "bitflags 2.4.0",1959 "bitflags 2.4.1",1856 "errno",1960 "errno",1857 "libc",1961 "libc",1858 "linux-raw-sys",1962 "linux-raw-sys",1883 "winapi-util",1987 "winapi-util",1884]1988]19891990[[package]]1991name = "scheduled-thread-pool"1992version = "0.2.7"1993source = "registry+https://github.com/rust-lang/crates.io-index"1994checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19"1995dependencies = [1996 "parking_lot",1997]188519981886[[package]]1999[[package]]1887name = "scopeguard"2000name = "scopeguard"191820311919[[package]]2032[[package]]1920name = "serde"2033name = "serde"1921version = "1.0.188"2034version = "1.0.190"1922source = "registry+https://github.com/rust-lang/crates.io-index"2035source = "registry+https://github.com/rust-lang/crates.io-index"1923checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"2036checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"1924dependencies = [2037dependencies = [1925 "serde_derive",2038 "serde_derive",1926]2039]193620491937[[package]]2050[[package]]1938name = "serde_derive"2051name = "serde_derive"1939version = "1.0.188"2052version = "1.0.190"1940source = "registry+https://github.com/rust-lang/crates.io-index"2053source = "registry+https://github.com/rust-lang/crates.io-index"1941checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"2054checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"1942dependencies = [2055dependencies = [1943 "proc-macro2",2056 "proc-macro2",1944 "quote",2057 "quote",1945 "syn 2.0.37",2058 "syn 2.0.38",1946]2059]194720601948[[package]]2061[[package]]196720801968[[package]]2081[[package]]1969name = "sha2"2082name = "sha2"1970version = "0.10.7"2083version = "0.10.8"1971source = "registry+https://github.com/rust-lang/crates.io-index"2084source = "registry+https://github.com/rust-lang/crates.io-index"1972checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"2085checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"1973dependencies = [2086dependencies = [1974 "cfg-if",2087 "cfg-if",1975 "cpufeatures",2088 "cpufeatures",1985 "lazy_static",2098 "lazy_static",1986]2099]21002101[[package]]2102name = "shlex"2103version = "1.2.0"2104source = "registry+https://github.com/rust-lang/crates.io-index"2105checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"198721061988[[package]]2107[[package]]1989name = "signal-hook-registry"2108name = "signal-hook-registry"2066source = "registry+https://github.com/rust-lang/crates.io-index"2185source = "registry+https://github.com/rust-lang/crates.io-index"2067checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"2186checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"21872188[[package]]2189name = "supports-color"2190version = "1.3.1"2191source = "registry+https://github.com/rust-lang/crates.io-index"2192checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f"2193dependencies = [2194 "atty",2195 "is_ci",2196]206821972069[[package]]2198[[package]]2070name = "syn"2199name = "syn"2073checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"2202checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"2074dependencies = [2203dependencies = [2075 "proc-macro2",2204 "proc-macro2",2205 "quote",2076 "unicode-ident",2206 "unicode-ident",2077]2207]207822082079[[package]]2209[[package]]2080name = "syn"2210name = "syn"2081version = "2.0.37"2211version = "2.0.38"2082source = "registry+https://github.com/rust-lang/crates.io-index"2212source = "registry+https://github.com/rust-lang/crates.io-index"2083checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"2213checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"2084dependencies = [2214dependencies = [2085 "proc-macro2",2215 "proc-macro2",2086 "quote",2216 "quote",2087 "unicode-ident",2217 "unicode-ident",2088]2218]22192220[[package]]2221name = "tabled"2222version = "0.14.0"2223source = "registry+https://github.com/rust-lang/crates.io-index"2224checksum = "dfe9c3632da101aba5131ed63f9eed38665f8b3c68703a6bb18124835c1a5d22"2225dependencies = [2226 "ansi-str",2227 "ansitok",2228 "papergrid",2229 "tabled_derive",2230 "unicode-width",2231]22322233[[package]]2234name = "tabled_derive"2235version = "0.6.0"2236source = "registry+https://github.com/rust-lang/crates.io-index"2237checksum = "99f688a08b54f4f02f0a3c382aefdb7884d3d69609f785bd253dc033243e3fe4"2238dependencies = [2239 "heck",2240 "proc-macro-error",2241 "proc-macro2",2242 "quote",2243 "syn 1.0.109",2244]208922452090[[package]]2246[[package]]2091name = "tempfile"2247name = "tempfile"2092version = "3.8.0"2248version = "3.8.1"2093source = "registry+https://github.com/rust-lang/crates.io-index"2249source = "registry+https://github.com/rust-lang/crates.io-index"2094checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"2250checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"2095dependencies = [2251dependencies = [2096 "cfg-if",2252 "cfg-if",2097 "fastrand",2253 "fastrand",2098 "redox_syscall",2254 "redox_syscall 0.4.1",2099 "rustix",2255 "rustix",2100 "windows-sys 0.48.0",2256 "windows-sys 0.48.0",2101]2257]212722832128[[package]]2284[[package]]2129name = "thiserror"2285name = "thiserror"2130version = "1.0.48"2286version = "1.0.50"2131source = "registry+https://github.com/rust-lang/crates.io-index"2287source = "registry+https://github.com/rust-lang/crates.io-index"2132checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"2288checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"2133dependencies = [2289dependencies = [2134 "thiserror-impl",2290 "thiserror-impl",2135]2291]213622922137[[package]]2293[[package]]2138name = "thiserror-impl"2294name = "thiserror-impl"2139version = "1.0.48"2295version = "1.0.50"2140source = "registry+https://github.com/rust-lang/crates.io-index"2296source = "registry+https://github.com/rust-lang/crates.io-index"2141checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"2297checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"2142dependencies = [2298dependencies = [2143 "proc-macro2",2299 "proc-macro2",2144 "quote",2300 "quote",2145 "syn 2.0.37",2301 "syn 2.0.38",2146]2302]214723032148[[package]]2304[[package]]215723132158[[package]]2314[[package]]2159name = "time"2315name = "time"2160version = "0.3.28"2316version = "0.3.30"2161source = "registry+https://github.com/rust-lang/crates.io-index"2317source = "registry+https://github.com/rust-lang/crates.io-index"2162checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48"2318checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"2163dependencies = [2319dependencies = [2164 "deranged",2320 "deranged",2321 "powerfmt",2165 "serde",2322 "serde",2166 "time-core",2323 "time-core",2167 "time-macros",2324 "time-macros",2168]2325]216923262170[[package]]2327[[package]]2171name = "time-core"2328name = "time-core"2172version = "0.1.1"2329version = "0.1.2"2173source = "registry+https://github.com/rust-lang/crates.io-index"2330source = "registry+https://github.com/rust-lang/crates.io-index"2174checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"2331checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"217523322176[[package]]2333[[package]]2177name = "time-macros"2334name = "time-macros"2178version = "0.2.14"2335version = "0.2.15"2179source = "registry+https://github.com/rust-lang/crates.io-index"2336source = "registry+https://github.com/rust-lang/crates.io-index"2180checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572"2337checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"2181dependencies = [2338dependencies = [2182 "time-core",2339 "time-core",2183]2340]219323502194[[package]]2351[[package]]2195name = "tokio"2352name = "tokio"2196version = "1.32.0"2353version = "1.33.0"2197source = "registry+https://github.com/rust-lang/crates.io-index"2354source = "registry+https://github.com/rust-lang/crates.io-index"2198checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"2355checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"2199dependencies = [2356dependencies = [2200 "backtrace",2357 "backtrace",2201 "bytes",2358 "bytes",2218dependencies = [2375dependencies = [2219 "proc-macro2",2376 "proc-macro2",2220 "quote",2377 "quote",2221 "syn 2.0.37",2378 "syn 2.0.38",2222]2379]222323802224[[package]]2381[[package]]2225name = "tokio-util"2382name = "tokio-util"2226version = "0.7.9"2383version = "0.7.10"2227source = "registry+https://github.com/rust-lang/crates.io-index"2384source = "registry+https://github.com/rust-lang/crates.io-index"2228checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"2385checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"2229dependencies = [2386dependencies = [2230 "bytes",2387 "bytes",2231 "futures-core",2388 "futures-core",2298dependencies = [2455dependencies = [2299 "proc-macro2",2456 "proc-macro2",2300 "quote",2457 "quote",2301 "syn 2.0.37",2458 "syn 2.0.38",2302]2459]230324602304[[package]]2461[[package]]2407source = "registry+https://github.com/rust-lang/crates.io-index"2564source = "registry+https://github.com/rust-lang/crates.io-index"2408checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"2565checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"25662567[[package]]2568name = "unindent"2569version = "0.2.3"2570source = "registry+https://github.com/rust-lang/crates.io-index"2571checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"240925722410[[package]]2573[[package]]2411name = "universal-hash"2574name = "universal-hash"2444 "itoa",2607 "itoa",2445 "log",2608 "log",2446 "unicode-width",2609 "unicode-width",2447 "vte",2610 "vte 0.11.1",2448]2611]26122613[[package]]2614name = "vte"2615version = "0.10.1"2616source = "registry+https://github.com/rust-lang/crates.io-index"2617checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983"2618dependencies = [2619 "arrayvec 0.5.2",2620 "utf8parse",2621 "vte_generate_state_changes",2622]244926232450[[package]]2624[[package]]2451name = "vte"2625name = "vte"2452version = "0.11.1"2626version = "0.11.1"2453source = "registry+https://github.com/rust-lang/crates.io-index"2627source = "registry+https://github.com/rust-lang/crates.io-index"2454checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"2628checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"2455dependencies = [2629dependencies = [2456 "arrayvec",2630 "arrayvec 0.7.4",2457 "utf8parse",2631 "utf8parse",2458 "vte_generate_state_changes",2632 "vte_generate_state_changes",2459]2633]2511 "once_cell",2685 "once_cell",2512 "proc-macro2",2686 "proc-macro2",2513 "quote",2687 "quote",2514 "syn 2.0.37",2688 "syn 2.0.38",2515 "wasm-bindgen-shared",2689 "wasm-bindgen-shared",2516]2690]251726912533dependencies = [2707dependencies = [2534 "proc-macro2",2708 "proc-macro2",2535 "quote",2709 "quote",2536 "syn 2.0.37",2710 "syn 2.0.38",2537 "wasm-bindgen-backend",2711 "wasm-bindgen-backend",2538 "wasm-bindgen-shared",2712 "wasm-bindgen-shared",2539]2713]2759dependencies = [2933dependencies = [2760 "proc-macro2",2934 "proc-macro2",2761 "quote",2935 "quote",2762 "syn 2.0.37",2936 "syn 2.0.38",2763]2937]27642938README.adocdiffbeforeafterboth667- Modules can configure multiple hosts at once (I.e for wireguard/kubernetes installation)7- Modules can configure multiple hosts at once (I.e for wireguard/kubernetes installation)8- Secrets can be securely stored in Git (No one except target hosts can decrypt them), automatically regenerated, reencrypted, etc.8- Secrets can be securely stored in Git (No one except target hosts can decrypt them), automatically regenerated, reencrypted, etc.9- Automatic rollback on deployment failure, which will work, as long as system is passing initrd stage (So still be carefull with root filesystem mount)910cmds/fleet/Cargo.tomldiffbeforeafterboth9anyhow = "1.0"9anyhow = "1.0"10serde = { version = "1.0", features = ["derive"] }10serde = { version = "1.0", features = ["derive"] }11serde_json = "1.0"11serde_json = "1.0"12time = { version = "0.3.2", features = ["serde"] }12time = { version = "0.3.30", features = ["serde"] }13tempfile = "3.2"13tempfile = "3.8"14once_cell = "1.5"14once_cell = "1.18"15hostname = "0.3.1"15hostname = "0.3.1"16age-core = "0.9.0"16age-core = "0.9.0"17peg = "0.8.0"17peg = "0.8.2"18nixlike = { path = "../../crates/nixlike" }18nixlike = { path = "../../crates/nixlike" }19age = { version = "0.9.0", features = ["ssh", "armor"] }19age = { version = "0.9.2", features = ["ssh", "armor"] }20base64 = "0.21.0"20base64 = "0.21.5"21chrono = { version = "0.4.19", features = ["serde"] }21chrono = { version = "0.4.31", features = ["serde"] }22z85 = "3.0.3"22z85 = "3.0.5"23clap = { version = "4.0.29", features = [23clap = { version = "4.4.7", features = [24 "derive",24 "derive",25 "env",25 "env",26 "wrap_help",26 "wrap_help",27 "unicode",27 "unicode",28] }28] }29tokio = { version = "1.14.0", features = ["full"] }29tokio = { version = "1.33.0", features = ["full"] }30tracing = "0.1"30tracing = "0.1"31tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }31tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }32tokio-util = { version = "0.7.0", features = ["codec"] }32tokio-util = { version = "0.7.10", features = ["codec"] }33async-trait = "0.1.52"33async-trait = "0.1.74"34futures = "0.3.17"34futures = "0.3.29"35tracing-indicatif = "0.3.5"35tracing-indicatif = "0.3.5"36indicatif = "0.17.7"36indicatif = "0.17.7"37itertools = "0.11.0"37itertools = "0.11.0"38shlex = "1.2.0"39tabled = { version = "0.14.0", features = ["color"] }40owo-colors = { version = "3.5.0", features = ["supports-color", "supports-colors"] }41r2d2 = "0.8.10"42abort-on-drop = "0.2.2"43unindent = "0.2.3"3844cmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth121 cmd.comparg("--profile", "/nix/var/nix/profiles/system")121 cmd.comparg("--profile", "/nix/var/nix/profiles/system")122 .arg("--list-generations");122 .arg("--list-generations");123 // Sudo is required due to --list-generations acquiring lock on the profile.123 // Sudo is required due to --list-generations acquiring lock on the profile.124 let data = config.run_string_on(&host, cmd, true).await?;124 let data = config.run_string_on(host, cmd, true).await?;125 let generations = data125 let generations = data126 .split('\n')126 .split('\n')127 .map(|e| e.trim())127 .map(|e| e.trim())128 .filter(|&l| l != "")128 .filter(|&l| !l.is_empty())129 .filter_map(|g| {129 .filter_map(|g| {130 let gen: Option<Generation> = try {130 let gen: Option<Generation> = try {131 let mut parts = g.split_whitespace();131 let mut parts = g.split_whitespace();170async fn systemctl_stop(config: &Config, host: &str, unit: &str) -> Result<()> {170async fn systemctl_stop(config: &Config, host: &str, unit: &str) -> Result<()> {171 let mut cmd = MyCommand::new("systemctl");171 let mut cmd = MyCommand::new("systemctl");172 cmd.arg("stop").arg(unit);172 cmd.arg("stop").arg(unit);173 config.run_on(&host, cmd, true).await173 config.run_on(host, cmd, true).await174}174}175175176async fn systemctl_start(config: &Config, host: &str, unit: &str) -> Result<()> {176async fn systemctl_start(config: &Config, host: &str, unit: &str) -> Result<()> {177 let mut cmd = MyCommand::new("systemctl");177 let mut cmd = MyCommand::new("systemctl");178 cmd.arg("start").arg(unit);178 cmd.arg("start").arg(unit);179 config.run_on(&host, cmd, true).await179 config.run_on(host, cmd, true).await180}180}181181182async fn execute_upload(182async fn execute_upload(195 if !build.disable_rollback {195 if !build.disable_rollback {196 let _span = info_span!("preparing").entered();196 let _span = info_span!("preparing").entered();197 info!("preparing for rollback");197 info!("preparing for rollback");198 let generation = get_current_generation(&config, &host).await?;198 let generation = get_current_generation(config, host).await?;199 info!(199 info!(200 "rollback target would be {} {}",200 "rollback target would be {} {}",201 generation.id, generation.datetime201 generation.id, generation.datetime202 );202 );203 {203 {204 let mut cmd = MyCommand::new("sh");204 let mut cmd = MyCommand::new("sh");205 cmd.arg("-c").arg(format!("mark=$(mktemp -p /etc -t fleet_rollback_marker.XXXXX) && echo -n {} > $mark && mv --no-clobber $mark /etc/fleet_rollback_marker", generation.id));205 cmd.arg("-c").arg(format!("mark=$(mktemp -p /etc -t fleet_rollback_marker.XXXXX) && echo -n {} > $mark && mv --no-clobber $mark /etc/fleet_rollback_marker", generation.id));206 if let Err(e) = config.run_on(&host, cmd, true).await {206 if let Err(e) = config.run_on(host, cmd, true).await {207 error!("failed to set rollback marker: {e}");207 error!("failed to set rollback marker: {e}");208 failed = true;208 failed = true;209 }209 }225 .arg("systemctl")225 .arg("systemctl")226 .arg("start")226 .arg("start")227 .arg("rollback-watchdog.service");227 .arg("rollback-watchdog.service");228 if let Err(e) = config.run_on(&host, cmd, true).await {228 if let Err(e) = config.run_on(host, cmd, true).await {229 error!("failed to schedule rollback run: {e}");229 error!("failed to schedule rollback run: {e}");230 failed = true;230 failed = true;231 }231 }236 let mut cmd = MyCommand::new("nix-env");236 let mut cmd = MyCommand::new("nix-env");237 cmd.comparg("--profile", "/nix/var/nix/profiles/system")237 cmd.comparg("--profile", "/nix/var/nix/profiles/system")238 .comparg("--set", &built);238 .comparg("--set", &built);239 if let Err(e) = config.run_on(&host, cmd, true).await {239 if let Err(e) = config.run_on(host, cmd, true).await {240 error!("failed to switch generation: {e}");240 error!("failed to switch generation: {e}");241 failed = true;241 failed = true;242 }242 }249 switch_script.push("switch-to-configuration");249 switch_script.push("switch-to-configuration");250 let mut cmd = MyCommand::new(switch_script);250 let mut cmd = MyCommand::new(switch_script);251 cmd.arg(action.name());251 cmd.arg(action.name());252 if let Err(e) = config.run_on(&host, cmd, true).in_current_span().await {252 if let Err(e) = config.run_on(host, cmd, true).in_current_span().await {253 error!("failed to activate: {e}");253 error!("failed to activate: {e}");254 failed = true;254 failed = true;255 }255 }256 }256 }257 if !build.disable_rollback {257 if !build.disable_rollback {258 if failed {258 if failed {259 info!("executing rollback");259 info!("executing rollback");260 if let Err(e) = systemctl_start(&config, &host, "rollback-watchdog.service")260 if let Err(e) = systemctl_start(config, host, "rollback-watchdog.service")261 .instrument(info_span!("rollback"))261 .instrument(info_span!("rollback"))262 .await262 .await263 {263 {267 info!("trying to mark upgrade as successful");267 info!("trying to mark upgrade as successful");268 let mut cmd = MyCommand::new("rm");268 let mut cmd = MyCommand::new("rm");269 cmd.arg("-f").arg("/etc/fleet_rollback_marker");269 cmd.arg("-f").arg("/etc/fleet_rollback_marker");270 if let Err(e) = config.run_on(&host, cmd, true).in_current_span().await {270 if let Err(e) = config.run_on(host, cmd, true).in_current_span().await {271 error!("failed to remove rollback marker. This is bad, as the system will be rolled back by watchdog: {e}")271 error!("failed to remove rollback marker. This is bad, as the system will be rolled back by watchdog: {e}")272 }272 }273 }273 }274 info!("disarming watchdog, just in case");274 info!("disarming watchdog, just in case");275 if let Err(_e) = systemctl_stop(&config, &host, "rollback-watchdog.timer").await {275 if let Err(_e) = systemctl_stop(config, host, "rollback-watchdog.timer").await {276 // It is ok, if there was no reboot - then timer might not be running.276 // It is ok, if there was no reboot - then timer might not be running.277 }277 }278 if action.should_schedule_rollback_run() {278 if action.should_schedule_rollback_run() {279 if let Err(e) = systemctl_stop(&config, &host, "rollback-watchdog-run.timer").await {279 if let Err(e) = systemctl_stop(config, host, "rollback-watchdog-run.timer").await {280 error!("failed to disarm rollback run: {e}");280 error!("failed to disarm rollback run: {e}");281 }281 }282 }282 }283 } else {283 } else {284 let mut cmd = MyCommand::new("rm");284 let mut cmd = MyCommand::new("rm");285 cmd.arg("-f").arg("/etc/fleet_rollback_marker");285 cmd.arg("-f").arg("/etc/fleet_rollback_marker");286 if let Err(_e) = config.run_on(&host, cmd, true).in_current_span().await {286 if let Err(_e) = config.run_on(host, cmd, true).in_current_span().await {287 // Marker might not exist, yet better try to remove it.287 // Marker might not exist, yet better try to remove it.288 }288 }289 }289 }341 sign.arg("nix")341 sign.arg("nix")342 .arg("store")342 .arg("store")343 .arg("sign")343 .arg("sign")344 .comparg("-k", "/etc/nix/private-key")344 .comparg("--key-file", "/etc/nix/private-key")345 .arg("-r")345 .arg("-r")346 .arg(&built);346 .arg(&built);347 if let Err(e) = sign.run_nix().await {347 if let Err(e) = sign.run_nix().await {353 let mut nix = MyCommand::new("nix");353 let mut nix = MyCommand::new("nix");354 nix.arg("copy")354 nix.arg("copy")355 .arg("--substitute-on-destination")355 .arg("--substitute-on-destination")356 .comparg("--to", format!("ssh-ng://root@{host}"))356 .comparg("--to", format!("ssh-ng://{host}"))357 .arg(&built);357 .arg(&built);358 match nix.run_nix().await {358 match nix.run_nix().await {359 Ok(()) => break,359 Ok(()) => break,423 let hosts = config.list_hosts().await?;423 let hosts = config.list_hosts().await?;424 let set = LocalSet::new();424 let set = LocalSet::new();425 let this = &self;425 let this = &self;426 for host in hosts.iter() {426 for host in hosts.into_iter() {427 if config.should_skip(host) {427 if config.should_skip(&host.name) {428 continue;428 continue;429 }429 }430 let config = config.clone();430 let config = config.clone();431 let host = host.clone();432 let this = this.clone();431 let this = this.clone();433 let span = info_span!("deployment", host = field::display(&host));432 let span = info_span!("deployment", host = field::display(&host.name));433 let hostname = host.name;434 set.spawn_local(434 set.spawn_local(435 (async move {435 (async move {436 match this.build_task(config, host).await {436 match this.build_task(config, hostname).await {437 Ok(_) => {}437 Ok(_) => {}438 Err(e) => {438 Err(e) => {439 error!("failed to deploy host: {}", e)439 error!("failed to deploy host: {}", e)cmds/fleet/src/cmds/info.rsdiffbeforeafterboth36 InfoCmd::ListHosts { ref tagged } => {36 InfoCmd::ListHosts { ref tagged } => {37 'host: for host in config.list_hosts().await? {37 'host: for host in config.list_hosts().await? {38 if !tagged.is_empty() {38 if !tagged.is_empty() {39 let tags: Vec<String> = config.config_attr(&host, "tags").await?;39 let tags: Vec<String> = config40 .fleet_field41 .get_field_deep(["configuredSystems", &host.name, "config", "tags"])42 .await?43 .as_json()44 .await?;40 for tag in tagged {45 for tag in tagged {41 if !tags.contains(tag) {46 if !tags.contains(tag) {42 continue 'host;47 continue 'host;43 }48 }44 }49 }45 }50 }46 data.push(host);51 data.push(host.name);47 }52 }48 }53 }49 InfoCmd::HostIps {54 InfoCmd::HostIps {56 "at leas one of --external or --internal must be set"61 "at leas one of --external or --internal must be set"57 );62 );58 let mut out = <BTreeSet<String>>::new();63 let mut out = <BTreeSet<String>>::new();64 let host = config.system_config(&host).await?;59 if external {65 if external {60 out.extend(66 out.extend(61 config67 host.get_field_deep(["network", "externalIps"])68 .await?62 .config_attr::<Vec<String>>(&host, "network.externalIps")69 .as_json::<Vec<String>>()63 .await?,70 .await?,64 );71 );65 }72 }66 if internal {73 if internal {67 out.extend(74 out.extend(68 config75 host.get_field_deep(["network", "internalIps"])76 .await?69 .config_attr::<Vec<String>>(&host, "network.internalIps")77 .as_json::<Vec<String>>()70 .await?,78 .await?,71 );79 );72 }80 }cmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth3 host::Config,3 host::Config,4};4};5use anyhow::{bail, ensure, Context, Result};5use anyhow::{bail, ensure, Context, Result};6use chrono::Utc;6use clap::Parser;7use clap::Parser;7use futures::{StreamExt, TryStreamExt};8use futures::{StreamExt, TryStreamExt};9use owo_colors::OwoColorize;8use std::{10use std::{9 collections::HashSet,11 collections::HashSet,10 io::{self, Cursor, Read},12 io::{self, Cursor, Read},11 path::PathBuf,13 path::PathBuf,12};14};15use tabled::{Table, Tabled};13use tokio::fs::read_to_string;16use tokio::fs::read_to_string;14use tracing::{error, info, warn};17use tracing::{error, info, info_span, warn};151816#[derive(Parser)]19#[derive(Parser)]17pub enum Secrets {20pub enum Secrets {73 #[clap(long)]76 #[clap(long)]74 prefer_identities: Vec<String>,77 prefer_identities: Vec<String>,75 },78 },79 List {},76}80}778178impl Secrets {82impl Secrets {79 pub async fn run(self, config: &Config) -> Result<()> {83 pub async fn run(self, config: &Config) -> Result<()> {80 match self {84 match self {81 Secrets::ForceKeys => {85 Secrets::ForceKeys => {82 for host in config.list_hosts().await? {86 for host in config.list_hosts().await? {83 if config.should_skip(&host) {87 if config.should_skip(&host.name) {84 continue;88 continue;85 }89 }86 config.key(&host).await?;90 config.key(&host.name).await?;87 }91 }88 }92 }89 Secrets::AddShared {93 Secrets::AddShared {128 FleetSharedSecret {132 FleetSharedSecret {129 owners: machines,133 owners: machines,130 secret: FleetSecret {134 secret: FleetSecret {135 created_at: Utc::now(),131 expire_at: None,136 expires_at: None,132 secret,137 secret,133 public: match (public, public_file) {138 public: match (public, public_file) {134 (Some(v), None) => Some(v),139 (Some(v), None) => Some(v),175 &machine,180 &machine,176 name,181 name,177 FleetSecret {182 FleetSecret {183 created_at: Utc::now(),178 expire_at: None,184 expires_at: None,179 secret,185 secret,180 public: match (public, public_file) {186 public: match (public, public_file) {181 (Some(v), None) => Some(v),187 (Some(v), None) => Some(v),291 target_recipients.into_iter().collect::<Result<Vec<_>>>()?;297 target_recipients.into_iter().collect::<Result<Vec<_>>>()?;292298293 let encrypted = config299 let encrypted = config294 .reencrypt_on_host(&identity_holder, secret.secret.secret, target_recipients)300 .reencrypt_on_host(identity_holder, secret.secret.secret, target_recipients)295 .await?;301 .await?;296302297 secret.owners = target_machines;303 secret.owners = target_machines;300 }306 }301 Secrets::Regenerate { prefer_identities } => {307 Secrets::Regenerate { prefer_identities } => {302 {308 {303 let expected_shared_set =304 config.shared_config_attr_names("sharedSecrets").await?;305 let expected_shared_set = expected_shared_set.iter().collect::<HashSet<_>>();309 let expected_shared_set = config310 .list_configured_shared()311 .await?312 .into_iter()313 .collect::<HashSet<_>>();306 let shared_set = config.list_shared();314 let shared_set = config.list_shared().into_iter().collect::<HashSet<_>>();307 let shared_set = shared_set.iter().collect::<HashSet<_>>();308 for removed in expected_shared_set.difference(&shared_set) {315 for removed in expected_shared_set.difference(&shared_set) {309 warn!("secret needs to be generated: {removed}")316 error!("secret needs to be generated: {removed}")310 }317 }311 }318 }312 let mut to_remove = Vec::new();319 let mut to_remove = Vec::new();313 for name in &config.list_shared() {320 for name in &config.list_shared() {314 info!("updating secret: {name}");321 info!("updating secret: {name}");315 let mut data = config.shared_secret(name)?;322 let mut data = config.shared_secret(name)?;316 let expected_owners: Vec<String> = config323 let expected_owners: Vec<String> = config324 .config_field317 .shared_config_attr(&format!("sharedSecrets.\"{name}\".expectedOwners"))325 .get_json_deep(["sharedSecrets", name, "expectedOwners"])318 .await?;326 .await?;319 if expected_owners.is_empty() {327 if expected_owners.is_empty() {320 warn!("secret was removed from fleet config: {name}, removing from data");328 warn!("secret was removed from fleet config: {name}, removing from data");326 let should_remove = set.difference(&expected_set).next().is_some();334 let should_remove = set.difference(&expected_set).next().is_some();327 if set != expected_set {335 if set != expected_set {328 let owner_dependent: bool = config336 let owner_dependent: bool = config337 .config_field329 .shared_config_attr(&format!("sharedSecrets.\"{name}\".ownerDependent"))338 .get_json_deep(["sharedSecrets", name, "ownerDependent"])330 .await?;339 .await?;331 if !owner_dependent {340 if !owner_dependent {332 warn!("reencrypting secret '{name}' for new owner set");341 warn!("reencrypting secret '{name}' for new owner set");355364356 let encrypted = config365 let encrypted = config357 .reencrypt_on_host(366 .reencrypt_on_host(358 &identity_holder,367 identity_holder,359 data.secret.secret,368 data.secret.secret,360 target_recipients,369 target_recipients,361 )370 )364 data.secret.secret = encrypted;373 data.secret.secret = encrypted;365 data.owners = expected_owners;374 data.owners = expected_owners;366 config.replace_shared(name.to_owned(), data);375 config.replace_shared(name.to_owned(), data);367 } else if let Some(generator) = config376 } else {368 .shared_config_attr::<Option<String>>(&format!(369 "sharedSecrets.\"{name}\".generator"370 ))371 .await?372 {373 todo!("regenerate secret {name} with {generator}");374 } else {375 error!("secret '{name}' should be regenerated manually");377 error!("secret '{name}' should be regenerated manually");376 }378 }377 } else {379 } else {382 config.remove_shared(&k);384 config.remove_shared(&k);383 }385 }384 }386 }387 Secrets::List {} => {388 let _span = info_span!("loading secrets").entered();389 let configured = config.list_configured_shared().await?;390 #[derive(Tabled)]391 struct SecretDisplay {392 #[tabled(rename = "Name")]393 name: String,394 #[tabled(rename = "Owners")]395 owners: String,396 }397 let mut table = vec![];398 for name in configured.iter().cloned() {399 let config = config.clone();400 let expected_owners = config.shared_secret_expected_owners(&name).await?;401 let data = config.shared_secret(&name)?;402 let owners = data403 .owners404 .iter()405 .map(|o| {406 if expected_owners.contains(o) {407 o.green().to_string()408 } else {409 o.red().to_string()410 }411 })412 .collect::<Vec<_>>();413 table.push(SecretDisplay {414 owners: owners.join(", "),415 name,416 })417 }418 info!("loaded\n{}", Table::new(table).to_string())419 }385 }420 }386 Ok(())421 Ok(())387 }422 }cmds/fleet/src/command.rsdiffbeforeafterboth2 collections::HashMap,3 ffi::OsStr,4 process::Stdio,5 sync::{Arc, Mutex},6 task::Poll,7};283use anyhow::{Context, Result};9use anyhow::Result;4use futures::StreamExt;10use futures::StreamExt;5use serde::{11use serde::{de::Visitor, Deserialize};6 de::{DeserializeOwned, Visitor},7 Deserialize,8};9use tokio::{io::AsyncRead, process::Command, select};12use tokio::{io::AsyncRead, process::Command, select};10use tokio_util::codec::{BytesCodec, FramedRead, LinesCodec};13use tokio_util::codec::{BytesCodec, FramedRead, LinesCodec};49 if !self.env.is_empty() {52 if !self.env.is_empty() {50 out.push("env".to_owned());53 out.push("env".to_owned());51 for (k, v) in self.env {54 for (k, v) in self.env {52 assert!(!k.contains("="));55 assert!(!k.contains('='));53 out.push(format!("{k}={v}"));56 out.push(format!("{k}={v}"));54 }57 }55 }58 }56 out.push(self.command);59 out.push(self.command);57 out.extend(self.args.into_iter());60 out.extend(self.args);58 out61 out59 }62 }60 fn into_string(self) -> String {63 fn into_string(self) -> String {63 out.push_str("env");66 out.push_str("env");64 for (k, v) in self.env {67 for (k, v) in self.env {65 out.push(' ');68 out.push(' ');66 assert!(!k.contains("="));69 assert!(!k.contains('='));67 escape_bash(&k, &mut out);70 escape_bash(&k, &mut out);68 out.push('=');71 out.push('=');69 escape_bash(&v, &mut out);72 escape_bash(&v, &mut out);136 let v = run_nix_inner_stdout(str, cmd, &mut PlainHandler).await?;139 let v = run_nix_inner_stdout(str, cmd, &mut PlainHandler).await?;137 Ok(v)140 Ok(v)138 }141 }139 pub async fn run_nix_json<T: DeserializeOwned>(self) -> Result<T> {140 let str = self.run_nix_string().await?;141 serde_json::from_str(&str).with_context(|| format!("{:?}", str))142 }143142144 pub async fn run_nix_string(self) -> Result<String> {143 pub async fn run_nix_string(self) -> Result<String> {145 let str = self.clone().into_string();144 let str = self.clone().into_string();172 cmd: Command,171 cmd: Command,173 handler: &mut dyn Handler,172 handler: &mut dyn Handler,174) -> Result<String> {173) -> Result<String> {175 Ok(run_nix_inner_raw(str, cmd, true, handler)174 Ok(run_nix_inner_raw(str, cmd, true, handler, None)176 .await?175 .await?177 .expect("has out"))176 .expect("has out"))178}177}179async fn run_nix_inner(str: String, cmd: Command, handler: &mut dyn Handler) -> Result<()> {178async fn run_nix_inner(str: String, cmd: Command, handler: &mut dyn Handler) -> Result<()> {180 let v = run_nix_inner_raw(str, cmd, false, handler).await?;179 let v = run_nix_inner_raw(str, cmd, false, handler, None).await?;181 assert!(v.is_none());180 assert!(v.is_none());182 Ok(())181 Ok(())183}182}184183185trait Handler {184pub trait Handler: Send {185 fn handle_line(&mut self, e: &str);186}187186 fn handle_err(&mut self, e: &str);188pub struct ClonableHandler<H>(Arc<Mutex<H>>);189impl<H> Clone for ClonableHandler<H> {190 fn clone(&self) -> Self {191 Self(self.0.clone())192 }193}194impl<H> ClonableHandler<H> {195 pub fn new(inner: H) -> Self {196 Self(Arc::new(Mutex::new(inner)))197 }198}199impl<H: Handler> Handler for ClonableHandler<H> {187 fn handle_info(&mut self, e: &str);200 fn handle_line(&mut self, e: &str) {188}201 self.0.lock().unwrap().handle_line(e)202 }203}189204190struct PlainHandler;205struct PlainHandler;191impl Handler for PlainHandler {206impl Handler for PlainHandler {192 fn handle_err(&mut self, e: &str) {207 fn handle_line(&mut self, e: &str) {193 info!(target: "log", "{e}");208 info!(target: "log", "{e}");194 }209 }195196 fn handle_info(&mut self, e: &str) {197 info!(target: "log", "{e}");198 }199}210}211212pub struct NoopHandler;213impl Handler for NoopHandler {214 fn handle_line(&mut self, _e: &str) {}215}200216201#[derive(Default)]217#[derive(Default)]202struct NixHandler {218pub struct NixHandler {203 spans: HashMap<u64, Span>,219 spans: HashMap<u64, Span>,204}220}205impl Handler for NixHandler {221impl Handler for NixHandler {206 fn handle_err(&mut self, e: &str) {222 fn handle_line(&mut self, e: &str) {207 if let Some(e) = e.strip_prefix("@nix ") {223 if let Some(e) = e.strip_prefix("@nix ") {208 let log: NixLog = match serde_json::from_str(e) {224 let log: NixLog = match serde_json::from_str(e) {209 Ok(l) => l,225 Ok(l) => l,214 };230 };215 match log {231 match log {216 NixLog::Msg { msg, raw_msg, .. } => {232 NixLog::Msg { msg, raw_msg, .. } => {233 #[allow(clippy::nonminimal_bool)]217 if !(msg.starts_with("\u{1b}[35;1mwarning:\u{1b}[0m Git tree '") && msg.ends_with("' is dirty"))234 if !(msg.starts_with("\u{1b}[35;1mwarning:\u{1b}[0m Git tree '") && msg.ends_with("' is dirty"))218 && !msg.starts_with("\u{1b}[35;1mwarning:\u{1b}[0m not writing modified lock file of flake")235 && !msg.starts_with("\u{1b}[35;1mwarning:\u{1b}[0m not writing modified lock file of flake")219 && msg != "\u{1b}[35;1mwarning:\u{1b}[0m \u{1b}[31;1merror:\u{1b}[0m SQLite database '\u{1b}[35;1m/nix/var/nix/db/db.sqlite\u{1b}[0m' is busy" {236 && msg != "\u{1b}[35;1mwarning:\u{1b}[0m \u{1b}[31;1merror:\u{1b}[0m SQLite database '\u{1b}[35;1m/nix/var/nix/db/db.sqlite\u{1b}[0m' is busy" {397 _ => warn!("unknown log: {:?}", log),414 _ => warn!("unknown log: {:?}", log),398 };415 };399 } else {416 } else {400 warn!(target = "nix", "unknown: {}", e.trim())417 let e = e.trim();418 if e.starts_with("Failed tcsetattr(TCSADRAIN): ") {419 return;420 }421 info!("{e}")401 }422 }402 }423 }403 fn handle_info(&mut self, o: &str) {404 self.handle_err(o)405 }406}424}407425408async fn run_nix_inner_raw(426async fn run_nix_inner_raw(409 str: String,427 str: String,410 mut cmd: Command,428 mut cmd: Command,411 want_stdout: bool,429 want_stdout: bool,412 handler: &mut dyn Handler,430 err_handler: &mut dyn Handler,431 mut out_handler: Option<&mut dyn Handler>,413) -> Result<Option<String>> {432) -> Result<Option<String>> {414 info!("running {str}");415 cmd.stderr(Stdio::piped());433 cmd.stderr(Stdio::piped());416 cmd.stdout(Stdio::piped());434 cmd.stdout(Stdio::piped());417 let mut child = cmd.spawn()?;435 let mut child = cmd.spawn()?;436 e = err.next() => {454 e = err.next() => {437 if let Some(e) = e {455 if let Some(e) = e {438 let e = e?;456 let e = e?;439 handler.handle_err(&e);457 err_handler.handle_line(&e);440 }458 }441 },459 },442 o = ob.next() => {460 o = ob.next() => {447 o = ol.next() => {465 o = ol.next() => {448 if let Some(o) = o {466 if let Some(o) = o {449 let o = o?;467 let o = o?;450 handler.handle_info(&o);468 if let Some(out) = out_handler.as_mut() {469 out.handle_line(&o)470 } else {471 err_handler.handle_line(&o)472 }473 // out_handler.handle_info(&o);451 }474 }452 },475 },453 code = child.wait() => {476 code = child.wait() => {463 Ok(out_buf.map(String::from_utf8).transpose()?)486 Ok(out_buf.map(String::from_utf8).transpose()?)464}487}488489pub trait ErrorRecorder: Send {490 /// Return true to discard message from logging491 fn push_message(&mut self, msg: &str) -> bool;492}465493466#[derive(Debug)]494#[derive(Debug)]467enum LogField {495enum LogField {cmds/fleet/src/extra_args.rsdiffbeforeafterboth12 })12 })13 .collect())13 .collect())14}14}15pub fn parse(s: &str) -> Result<Vec<OsString>> {15// pub fn parse(s: &str) -> Result<Vec<OsString>> {16 let osstr = OsString::try_from(s)?;16// let osstr = OsString::try_from(s)?;17 parse_os(&osstr)17// parse_os(&osstr)18}18// }1919cmds/fleet/src/fleetdata.rsdiffbeforeafterboth44#[serde(rename_all = "camelCase")]44#[serde(rename_all = "camelCase")]45#[must_use]45#[must_use]46pub struct FleetSecret {46pub struct FleetSecret {47 #[serde(default = "Utc::now")]48 pub created_at: DateTime<Utc>,47 #[serde(default)]49 #[serde(default)]48 #[serde(skip_serializing_if = "Option::is_none")]50 #[serde(skip_serializing_if = "Option::is_none", alias = "expire_at")]49 pub expire_at: Option<DateTime<Utc>>,51 pub expires_at: Option<DateTime<Utc>>,50 #[serde(skip_serializing_if = "Option::is_none")]52 #[serde(skip_serializing_if = "Option::is_none")]51 pub public: Option<String>,53 pub public: Option<String>,52 #[serde(54 #[serde(cmds/fleet/src/host.rsdiffbeforeafterboth1use std::{1use std::{2 cell::{Ref, RefCell, RefMut},3 env::current_dir,2 env::current_dir,4 ffi::OsString,3 ffi::OsString,5 io::Write,4 io::Write,6 ops::Deref,5 ops::Deref,7 path::PathBuf,6 path::PathBuf,8 sync::Arc,7 sync::{Arc, Mutex, MutexGuard},9};8};10911use anyhow::{bail, Context, Result};10use anyhow::{bail, Context, Result};12use clap::{ArgGroup, Parser};11use clap::{ArgGroup, Parser};13use serde::de::DeserializeOwned;14use tempfile::NamedTempFile;12use tempfile::NamedTempFile;151316use crate::{14use crate::{15 better_nix_eval::{Field, NixSessionPool},17 command::MyCommand,16 command::MyCommand,18 fleetdata::{FleetData, FleetSecret, FleetSharedSecret},17 fleetdata::{FleetData, FleetSecret, FleetSharedSecret},19};18};22 pub local_system: String,21 pub local_system: String,23 pub directory: PathBuf,22 pub directory: PathBuf,24 pub opts: FleetOpts,23 pub opts: FleetOpts,25 pub data: RefCell<FleetData>,24 pub data: Mutex<FleetData>,26 pub nix_args: Vec<OsString>,25 pub nix_args: Vec<OsString>,26 // fleetConfigurations.<name>27 pub fleet_field: Field,28 // fleet_config.configUnchecked29 pub config_field: Field,27}30}283129#[derive(Clone)]32#[derive(Clone)]37 }40 }38}41}4243pub struct ConfigHost {44 pub name: String,45}394640impl Config {47impl Config {41 pub fn should_skip(&self, host: &str) -> bool {48 pub fn should_skip(&self, host: &str) -> bool {60 }67 }61 command.run().await68 command.run().await62 }69 }63 #[must_use]64 pub async fn run_string_on(70 pub async fn run_string_on(65 &self,71 &self,66 host: &str,72 host: &str,86 str92 str87 }93 }889489 pub async fn list_hosts(&self) -> Result<Vec<String>> {95 pub async fn list_hosts(&self) -> Result<Vec<ConfigHost>> {90 let mut cmd = MyCommand::new("nix");96 let names = self.fleet_field91 cmd.arg("eval")92 .arg(self.configuration_attr_name("configuredHosts"))97 .get_field_deep(["configuredHosts"])98 .await?93 .args(["--apply", "builtins.attrNames", "--json", "--show-trace"])99 .list_fields()94 .args(&self.nix_args);100 .await?;101 let mut out = vec![];102 for name in names {95 cmd.run_nix_json().await103 out.push(ConfigHost {104 name,105 })106 }107 Ok(out)96 }108 }97 pub async fn shared_config_attr<T: DeserializeOwned>(&self, attr: &str) -> Result<T> {109 pub async fn system_config(&self, host: &str) -> Result<Field> {98 let mut cmd = MyCommand::new("nix");99 cmd.arg("eval")100 .arg(self.configuration_attr_name(&format!("configUnchecked.{}", attr)))110 self.fleet_field.get_field_deep(["configuredSystems", host, "config"]).await101 .args(["--json", "--show-trace"])102 .args(&self.nix_args);103 cmd.run_nix_json().await104 }111 }112105 pub async fn shared_config_attr_names(&self, attr: &str) -> Result<Vec<String>> {113 pub(super) fn data(&self) -> MutexGuard<FleetData> {106 let mut cmd = MyCommand::new("nix");107 cmd.arg("eval")108 .arg(self.configuration_attr_name(&format!("configUnchecked.{}", attr)))111 .args(&self.nix_args);112 cmd.run_nix_json().await113 }114 pub async fn config_attr<T: DeserializeOwned>(&self, host: &str, attr: &str) -> Result<T> {115 let mut cmd = MyCommand::new("nix");116 cmd.arg("eval")117 .arg(118 self.configuration_attr_name(&format!(114 self.data.lock().unwrap()119 "configuredSystems.{}.config.{}",120 host, attr121 )),122 )123 .args(["--json", "--show-trace"])124 .args(&self.nix_args);125 cmd.run_nix_json().await126 }115 }127128 pub(super) fn data(&self) -> Ref<FleetData> {116 pub(super) fn data_mut(&self) -> MutexGuard<FleetData> {129 self.data.borrow()117 self.data.lock().unwrap()130 }118 }119 /// Shared secrets configured in fleet.nix or in flake131 pub(super) fn data_mut(&self) -> RefMut<FleetData> {120 pub async fn list_configured_shared(&self) -> Result<Vec<String>> {132 self.data.borrow_mut()121 self.config_field122 .get_field("sharedSecrets")123 .await?124 .list_fields()125 .await133 }126 }134127 /// Shared secrets configured in fleet.nix135 pub fn list_shared(&self) -> Vec<String> {128 pub fn list_shared(&self) -> Vec<String> {136 let data = self.data();129 let data = self.data();137 data.shared_secrets.keys().cloned().collect()130 data.shared_secrets.keys().cloned().collect()149 data.shared_secrets.remove(secret);142 data.shared_secrets.remove(secret);150 }143 }151144152 pub fn list_secrets(&self, host: &str) -> Vec<String> {153 let data = self.data();154 let Some(host_secrets) = data.host_secrets.get(host) else {155 return Vec::new();156 };157 host_secrets.keys().cloned().collect()158 }159 pub fn has_secret(&self, host: &str, secret: &str) -> bool {145 pub fn has_secret(&self, host: &str, secret: &str) -> bool {160 let data = self.data();146 let data = self.data();161 let Some(host_secrets) = data.host_secrets.get(host) else {147 let Some(host_secrets) = data.host_secrets.get(host) else {180 .context("failed to call remote host for decrypt")?166 .context("failed to call remote host for decrypt")?181 .trim()167 .trim()182 .to_owned();168 .to_owned();183 Ok(z85::decode(encoded).context("bad encoded data? outdated host?")?)169 z85::decode(encoded).context("bad encoded data? outdated host?")184 }170 }185 pub async fn reencrypt_on_host(171 pub async fn reencrypt_on_host(186 &self,172 &self,201 .context("failed to call remote host for decrypt")?187 .context("failed to call remote host for decrypt")?202 .trim()188 .trim()203 .to_owned();189 .to_owned();204 Ok(z85::decode(encoded).context("bad encoded data? outdated host?")?)190 z85::decode(encoded).context("bad encoded data? outdated host?")205 }191 }206192207 #[must_use]208 pub fn host_secret(&self, host: &str, secret: &str) -> Result<FleetSecret> {193 pub fn host_secret(&self, host: &str, secret: &str) -> Result<FleetSecret> {209 let data = self.data();194 let data = self.data();210 let Some(host_secrets) = data.host_secrets.get(host) else {195 let Some(host_secrets) = data.host_secrets.get(host) else {215 };200 };216 Ok(secret.clone())201 Ok(secret.clone())217 }202 }218 #[must_use]219 pub fn shared_secret(&self, secret: &str) -> Result<FleetSharedSecret> {203 pub fn shared_secret(&self, secret: &str) -> Result<FleetSharedSecret> {220 let data = self.data();204 let data = self.data();221 let Some(secret) = data.shared_secrets.get(secret) else {205 let Some(secret) = data.shared_secrets.get(secret) else {222 bail!("no shared secret {secret}");206 bail!("no shared secret {secret}");223 };207 };224 Ok(secret.clone())208 Ok(secret.clone())225 }209 }210 pub async fn shared_secret_expected_owners(&self, secret: &str) -> Result<Vec<String>> {211 self.config_field212 .get_field_deep(["sharedSecrets", secret, "expectedOwners"])213 .await?214 .as_json()215 .await216 }226217227 pub fn save(&self) -> Result<()> {218 pub fn save(&self) -> Result<()> {228 let mut tempfile = NamedTempFile::new_in(self.directory.clone())?;219 let mut tempfile = NamedTempFile::new_in(self.directory.clone())?;229 let data = nixlike::serialize(&self.data() as &FleetData)?;220 let data = nixlike::serialize(&self.data() as &FleetData)?;230 tempfile.write_all(221 tempfile.write_all(231 format!(222 format!(232 "# This file contains fleet state and shouldn't be edited by hand\n\n{}\n",223 "# This file contains fleet state and shouldn't be edited by hand\n\n{}\n\n# vim: ts=2 et nowrap\n",233 data224 data234 )225 )235 .as_bytes(),226 .as_bytes(),259 // TODO: unhardcode x86_64-linux250 // TODO: unhardcode x86_64-linux260 /// Override detected system for host, to perform builds via251 /// Override detected system for host, to perform builds via261 /// binfmt-declared qemu instead of trying to crosscompile252 /// binfmt-declared qemu instead of trying to crosscompile262 #[clap(long, default_value = "x86_64-linux")]253 #[clap(long, default_value = "detect")]263 pub local_system: String,254 pub local_system: String,264}255}265256266impl FleetOpts {257impl FleetOpts {267 pub async fn build(mut self, nix_args: Vec<OsString>) -> Result<Config> {258 pub async fn build(mut self, nix_args: Vec<OsString>) -> Result<Config> {268 let local_system = self.local_system.clone();269 if self.localhost.is_none() {259 if self.localhost.is_none() {270 self.localhost260 self.localhost271 .replace(hostname::get().unwrap().to_str().unwrap().to_owned());261 .replace(hostname::get().unwrap().to_str().unwrap().to_owned());272 }262 }273 let directory = current_dir()?;263 let directory = current_dir()?;264265 let pool = NixSessionPool::new(directory.as_os_str().to_owned(), nix_args.clone()).await?;266 let root_field = pool.get().await?;267268 if self.local_system == "detect" {269 let builtins_field = Field::field(root_field.clone(), "builtins").await?;270 let system = builtins_field.get_field("currentSystem").await?;271 self.local_system = system.as_json().await?;272 }273 let local_system = self.local_system.clone();274275 let fleet_root = Field::field(root_field, "fleetConfigurations").await?;276277 let fleet_field = fleet_root278 .get_field_deep(["default", &local_system])279 .await?;280 let config_field = fleet_field.get_field("configUnchecked").await?;274281275 let mut fleet_data_path = directory.clone();282 let mut fleet_data_path = directory.clone();276 fleet_data_path.push("fleet.nix");283 fleet_data_path.push("fleet.nix");283 data,290 data,284 local_system,291 local_system,285 nix_args,292 nix_args,293 fleet_field,294 config_field,286 })))295 })))287 }296 }288}297}cmds/fleet/src/keys.rsdiffbeforeafterboth3use crate::command::MyCommand;3use crate::command::MyCommand;4use crate::host::Config;4use crate::host::Config;5use anyhow::{anyhow, Result};5use anyhow::{anyhow, Result};6use itertools::Itertools;6use tracing::warn;7use tracing::warn;788impl Config {9impl Config {40 age::ssh::Recipient::from_str(&key).map_err(|e| anyhow!("parse recipient error: {:?}", e))41 age::ssh::Recipient::from_str(&key).map_err(|e| anyhow!("parse recipient error: {:?}", e))41 }42 }424344 #[allow(dead_code)]43 pub async fn orphaned_data(&self) -> Result<Vec<String>> {45 pub async fn orphaned_data(&self) -> Result<Vec<String>> {44 let mut out = Vec::new();46 let mut out = Vec::new();45 let host_names = self.list_hosts().await?;47 let host_names = self48 .list_hosts()49 .await?50 .into_iter()51 .map(|h| h.name)52 .collect_vec();46 for hostname in self53 for hostname in self47 .data()54 .data()48 .hosts55 .hostscmds/fleet/src/main.rsdiffbeforeafterboth1#![feature(try_blocks)]1#![feature(try_blocks)]223pub mod cmds;3pub(crate) mod cmds;4pub mod command;4pub(crate) mod command;5pub mod host;5pub(crate) mod host;6pub mod keys;6pub(crate) mod keys;78pub(crate) mod extra_args;9pub(crate) mod better_nix_eval;7108mod fleetdata;11mod fleetdata;91214use clap::Parser;17use clap::Parser;151816use cmds::{build_systems::BuildSystems, info::Info, secrets::Secrets};19use cmds::{build_systems::BuildSystems, info::Info, secrets::Secrets};20use futures::future::LocalBoxFuture;21use futures::stream::FuturesUnordered;22use futures::TryStreamExt;17use host::{Config, FleetOpts};23use host::{Config, FleetOpts};18use indicatif::{ProgressState, ProgressStyle};24use indicatif::{ProgressState, ProgressStyle};19use tokio::process::Command;20use tracing::{info, metadata::LevelFilter};25use tracing::{info, metadata::LevelFilter};26use tracing::{info_span, Instrument};21use tracing_indicatif::IndicatifLayer;27use tracing_indicatif::IndicatifLayer;22use tracing_subscriber::{prelude::*, EnvFilter};28use tracing_subscriber::{prelude::*, EnvFilter};2930use crate::command::MyCommand;233124#[derive(Parser)]32#[derive(Parser)]25struct Prefetch {}33struct Prefetch {}31 info!("nothing to prefetch: no prefetch directory");39 info!("nothing to prefetch: no prefetch directory");32 return Ok(());40 return Ok(());33 }41 }42 let tasks = <FuturesUnordered<LocalBoxFuture<Result<()>>>>::new();34 for entry in std::fs::read_dir(&prefetch_dir)? {43 for entry in std::fs::read_dir(&prefetch_dir)? {44 tasks.push(Box::pin(async {35 let entry = entry?;45 let entry = entry?;36 if !entry.metadata()?.is_file() {46 if !entry.metadata()?.is_file() {37 bail!("only files should exist in prefetch directory");47 bail!("only files should exist in prefetch directory");38 }48 }39 info!("prefetching {:?}", entry.file_name());49 let span = info_span!(50 "prefetching",51 name = entry.file_name().to_string_lossy().as_ref()52 );40 let mut path = OsString::new();53 let mut path = OsString::new();41 path.push("file://");54 path.push("file://");42 path.push(entry.path());55 path.push(entry.path());5657 let mut status = MyCommand::new("nix");43 let status = Command::new("nix-prefetch-url").arg(path).status().await?;58 status.arg("store").arg("prefetch-file").arg(path);44 if !status.success() {59 status.run_nix_string().instrument(span).await?;45 bail!("failed with {status}");60 Ok(())46 }61 }));47 }62 }63 tasks.try_collect::<Vec<()>>().await?;48 Ok(())64 Ok(())49 }65 }50}66}81 Ok(())97 Ok(())82}98}99100// fn main() -> Result<()> {101// let pool = r2d2::Builder::<NixSessionPool>::new()102// .min_idle(Some(1))103// .max_lifetime(Some(Duration::from_secs(10)))104// .build(NixSessionPool {105// flake: ".".to_owned(),106// nix_args: vec![],107// })?;108// let conn = pool.get()?;109// let field = Field::root(conn);110// // let builtins = field.get_field("builtins")?;111// let cur_sys: String = field.get_field("builtins")?.as_json()?;112// eprintln!("current system = {cur_sys}");113// let v = field.get_field("fleetConfigurations")?;114// eprintln!("configs = {:?}", v.list_fields()?);115// let d = v.get_field("default")?;116// dbg!(d.list_fields());117// Ok(())118// }119//120121fn setup_logging() {122 let indicatif_layer = IndicatifLayer::new().with_progress_style(123 ProgressStyle::with_template(124 "{color_start}{span_child_prefix} {span_name}{{{span_fields}}}{color_end} {wide_msg} {color_start}{pos:>7}/{len:7}{elapsed}{color_end}",125 )126 .unwrap()127 .with_key(128 "color_start",129 |state: &ProgressState, writer: &mut dyn std::fmt::Write| {130 let elapsed = state.elapsed();131132 if elapsed > Duration::from_secs(60) {133 // Red134 let _ = write!(writer, "\x1b[{}m", 1 + 30);135 } else if elapsed > Duration::from_secs(30) {136 // Yellow137 let _ = write!(writer, "\x1b[{}m", 3 + 30);138 }139 },140 )141 .with_key(142 "color_end",143 |state: &ProgressState, writer: &mut dyn std::fmt::Write| {144 if state.elapsed() > Duration::from_secs(30) {145 let _ = write!(writer, "\x1b[0m");146 }147 },148 ),149 );150151 let filter = EnvFilter::from_default_env().add_directive(LevelFilter::INFO.into());152153 tracing_subscriber::registry()154 .with(155 tracing_subscriber::fmt::layer()156 .without_time()157 .with_target(false)158 .with_writer(indicatif_layer.get_stderr_writer())159 .with_filter(filter), // .withou,160 )161 .with(indicatif_layer)162 .init();163}8316484#[tokio::main]165#[tokio::main]85async fn main() -> Result<()> {166async fn main() -> Result<()> {167 setup_logging();86 let indicatif_layer = IndicatifLayer::new().with_progress_style(168 let _ = better_nix_eval::TOKIO_RUNTIME.set(tokio::runtime::Handle::current());87 ProgressStyle::with_template(88 "{color_start}{span_child_prefix} {span_name}{{{span_fields}}}{color_end} {wide_msg} {color_start}{pos:>7}/{len:7}{elapsed}{color_end}",89 )90 .unwrap()91 .with_key(92 "color_start",93 |state: &ProgressState, writer: &mut dyn std::fmt::Write| {94 let elapsed = state.elapsed();9596 if elapsed > Duration::from_secs(60) {97 // Red98 let _ = write!(writer, "\x1b[{}m", 1 + 30);99 } else if elapsed > Duration::from_secs(30) {100 // Yellow101 let _ = write!(writer, "\x1b[{}m", 3 + 30);102 }103 },104 )105 .with_key(106 "color_end",107 |state: &ProgressState, writer: &mut dyn std::fmt::Write| {108 if state.elapsed() > Duration::from_secs(30) {109 let _ = write!(writer, "\x1b[0m");110 }111 },112 ),113 );114169115 let filter = EnvFilter::from_default_env().add_directive(LevelFilter::INFO.into());170 let nix_args = std::env::var_os("NIX_ARGS")116117 tracing_subscriber::registry()118 .with(171 .map(|a| extra_args::parse_os(&a))119 tracing_subscriber::fmt::layer()120 .without_time()121 .with_target(false)122 .with_writer(indicatif_layer.get_stderr_writer())123 .with_filter(filter), // .withou,124 )125 .with(indicatif_layer)172 .transpose()?126 .init();127 info!("Starting");173 .unwrap_or_default();128 let mut os_args = std::env::args_os();129 let opts = RootOpts::parse_from((&mut os_args).take_while(|v| v != "--"));174 let opts = RootOpts::parse();130 let config = opts.fleet_opts.build(os_args.collect()).await?;175 let config = opts.fleet_opts.build(nix_args).await?;131176132 match run_command(&config, opts.command).await {177 match run_command(&config, opts.command).await {133 Ok(()) => {178 Ok(()) => {cmds/fleet/src/nix_eval.rsdiffbeforeafterbothno changes
cmds/install-secrets/Cargo.tomldiffbeforeafterboth4edition = "2021"4edition = "2021"556[dependencies]6[dependencies]7age = { version = "0.9.0", features = ["ssh"] }7age = { version = "0.9.2", features = ["ssh"] }8anyhow = "1.0.44"8anyhow = "1.0.75"9env_logger = "0.10.0"9env_logger = "0.10.0"10log = "0.4.14"10log = "0.4.20"11nix = "0.26.1"11nix = {version = "0.27.1", features = ["user", "fs"]}12serde = { version = "1.0.130", features = ["derive"] }12serde = { version = "1.0.190", features = ["derive"] }13serde_json = "1.0.89"13serde_json = "1.0.107"14clap = { version = "4.0.29", features = [14clap = { version = "4.4.7", features = [15 "derive",15 "derive",16 "env",16 "env",17 "wrap_help",17 "wrap_help",18 "unicode",18 "unicode",19] }19] }20tempfile = "3.2.0"20tempfile = "3.8.1"21z85 = "3.0.3"21z85 = "3.0.5"2222cmds/install-secrets/src/main.rsdiffbeforeafterboth4use clap::Parser;4use clap::Parser;5use log::{error, info, warn};5use log::{error, info, warn};6use nix::sys::stat::Mode;6use nix::sys::stat::Mode;7use nix::unistd::{chown, Group, User};7use nix::unistd::{User, Group, chown};8use serde::{Deserialize, Deserializer};8use serde::{Deserialize, Deserializer};9use std::fmt::{self, Display};9use std::fmt::{self, Display};10use std::fs::{self, File};10use std::fs::{self, File};161 let mut hashed = File::create(&value.secret_path)?;161 let mut hashed = File::create(&value.secret_path)?;162162163 // File is owned by root, and only root can modify it163 // File is owned by root, and only root can modify it164 let decrypted = decrypt(&secret, identity)?;164 let decrypted = decrypt(secret, identity)?;165 if decrypted.is_empty() {165 if decrypted.is_empty() {166 warn!("secret is decoded as empty, something is broken?");166 warn!("secret is decoded as empty, something is broken?");167 }167 }crates/nixlike/Cargo.tomldiffbeforeafterboth556[dependencies]6[dependencies]7alejandra = {git = "https://github.com/kamadorueda/alejandra"}7alejandra = {git = "https://github.com/kamadorueda/alejandra"}8rnix = "0.10.2"9linked-hash-map = "0.5.4"8linked-hash-map = "0.5.6"10peg = "0.8.0"9peg = "0.8.2"11serde = "1.0.130"10serde = "1.0.190"12thiserror = "1.0.29"11thiserror = "1.0.50"13serde_json = "1.0.91"12serde_json = "1.0.107"14ron = "0.8.0"13ron = "0.8.1"15serde-transcode = "1.1.1"14serde-transcode = "1.1.1"1615crates/nixlike/src/lib.rsdiffbeforeafterboth119 Ok(serialize_value_pretty(value))119 Ok(serialize_value_pretty(value))120}120}121122pub fn format_identifier(i: &str) -> String {123 let mut out = String::new();124 to_string::write_identifier(i, &mut out);125 out126}121127122#[test]128#[test]123fn test() {129fn test() {crates/nixlike/src/se_impl.rsdiffbeforeafterboth212 }212 }213213214 fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {214 fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {215 Ok(Value::Number(v as i64))215 Ok(Value::Number(v))216 }216 }217217218 fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {218 fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {crates/nixlike/src/to_string.rsdiffbeforeafterboth1use crate::Value;1use crate::Value;23pub fn write_identifier(k: &str, out: &mut String) {4 if k.contains(['.', '\'', '\"', '\\', '\n', '\t', '\r', '$']) {5 write_nix_str(k, out);6 } else {7 out.push_str(k);8 }9}2103fn write_nix_obj_key_buf(k: &str, v: &Value, out: &mut String) {11fn write_nix_obj_key_buf(k: &str, v: &Value, out: &mut String) {4 if k.contains('.') {5 out.push_str("\"");6 out.push_str(k);12 write_identifier(k, out);7 out.push_str("\"");8 } else {9 out.push_str(k);10 }11 match v {13 match v {12 Value::Object(o) if o.len() == 1 => {14 Value::Object(o) if o.len() == 1 => {13 let (k, v) = o.iter().next().unwrap();15 let (k, v) = o.iter().next().unwrap();141615 out.push_str(".");17 out.push('.');16 write_nix_obj_key_buf(k, v, out);18 write_nix_obj_key_buf(k, v, out);17 }19 }18 v => {20 v => {19 out.push_str(" = ");21 out.push_str(" = ");20 write_nix_buf(v, out);22 write_nix_buf(v, out);21 out.push_str(";");23 out.push(';');22 }24 }23 }25 }24}26}flake.lockdiffbeforeafterboth38 },38 },39 "nixpkgs": {39 "nixpkgs": {40 "locked": {40 "locked": {41 "lastModified": 1696884899,41 "lastModified": 1698350982,42 "narHash": "sha256-SZILkoh8KZxjvFHO3yzOUw7n1Mf9WqMdUqoxf8eKPM4=",42 "narHash": "sha256-zoEV8Ad3bOAejp0ys/mOpaHSWrzK+GupZwGGYfuWuEY=",43 "owner": "nixos",43 "owner": "nixos",44 "repo": "nixpkgs",44 "repo": "nixpkgs",45 "rev": "ba10489eae3b2b2f665947b516e7043594a235c8",45 "rev": "dd83f9de26ff7c0326468b659ea4729fa5cf6262",46 "type": "github"46 "type": "github"47 },47 },48 "original": {48 "original": {67 ]67 ]68 },68 },69 "locked": {69 "locked": {70 "lastModified": 1696817516,70 "lastModified": 1698199907,71 "narHash": "sha256-Xt9OY4Wnk9/vuUfA0OHFtmSlaen5GyiS9msgwOz3okI=",71 "narHash": "sha256-n8RtHBIb0rLuYs4RDehW6mj6r6Yam/ODY1af/VCcurw=",72 "owner": "oxalica",72 "owner": "oxalica",73 "repo": "rust-overlay",73 "repo": "rust-overlay",74 "rev": "c0df7f2a856b5ff27a3ce314f6d7aacf5fda546f",74 "rev": "22b8d29fd22cfaa2c311e0d6fd8a0ed9c2a1152b",75 "type": "github"75 "type": "github"76 },76 },77 "original": {77 "original": {flake.nixdiffbeforeafterboth15 inherit system; overlays = [ (import rust-overlay) ];15 inherit system; overlays = [ (import rust-overlay) ];16 };16 };17 llvmPkgs = pkgs.buildPackages.llvmPackages_11;17 llvmPkgs = pkgs.buildPackages.llvmPackages_11;18 rust = (pkgs.rustChannelOf { date = "2023-10-05"; channel = "nightly"; }).default.override { extensions = [ "rust-src" "rust-analyzer" ]; };18 rust = (pkgs.rustChannelOf { date = "2023-10-20"; channel = "nightly"; }).default.override { extensions = [ "rust-src" "rust-analyzer" ]; };19 rustPlatform = pkgs.makeRustPlatform { cargo = rust; rustc = rust; };19 rustPlatform = pkgs.makeRustPlatform { cargo = rust; rustc = rust; };20 in20 in21 {21 {292930 pkg-config30 pkg-config31 openssl31 openssl32 bacon32 ];33 ];33 };34 };34 });35 });modules/fleet/secrets.nixdiffbeforeafterboth55 description = "Time in hours, in which this secret should be regenerated";55 description = "Time in hours, in which this secret should be regenerated";56 default = null;56 default = null;57 };57 };58 createdAt = mkOption {59 type = nullOr str;60 default = null;61 };62 expiresAt = mkOption {63 type = nullOr str;64 default = null;65 };586659 owners = mkOption {67 owners = mkOption {60 type = listOf str;68 type = listOf str;82 };90 };83 hostSecret = with types; {91 hostSecret = with types; {84 options = {92 options = {85 generator = mkOption {93 createdAt = mkOption {86 type = package;94 type = nullOr str;87 description = "Derivation to execute for secret generation";95 default = null;88 };96 };89 expireIn = mkOption {97 expiresAt = mkOption {90 type = nullOr int;98 type = nullOr str;91 description = "Time in hours, in which this secret should be regenerated";92 default = null;99 default = null;93 };100 };94 public = mkOption {101 public = mkOption {95 type = nullOr str;102 type = nullOr str;96 description = "Secret public data";103 description = "Secret public data. Imported from fleet.nix";97 default = null;104 default = null;98 };105 };99 secret = mkOption {106 secret = mkOption {100 type = str;107 type = nullOr str;101 description = "Encrypted secret data";108 description = "Encrypted secret data. Imported from fleet.nix";109 default = null;110 internal = true;102 };111 };103 };112 };104 };113 };113 hostSecrets = mkOption {122 hostSecrets = mkOption {114 type = attrsOf (attrsOf (submodule hostSecret));123 type = attrsOf (attrsOf (submodule hostSecret));115 default = { };124 default = { };116 description = "Host secrets";125 description = "Host secrets. Imported from fleet.nix";126 internal = true;117 };127 };118 };128 };119 config = {129 config = {