diff --git a/.cspell.json b/.cspell.json index 935da0e..9655369 100644 --- a/.cspell.json +++ b/.cspell.json @@ -88,6 +88,7 @@ "rootfstype", "rootwait", "rugpi", + "russh", "rustfmt", "sectorsize", "sfdisk", diff --git a/Cargo.lock b/Cargo.lock index 537980b..bd5bb3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,78 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "const-random", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.18" @@ -167,12 +239,35 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bcrypt-pbkdf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2" +dependencies = [ + "blowfish", + "pbkdf2", + "sha2", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -184,6 +279,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -194,6 +292,25 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blowfish" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" +dependencies = [ + "byteorder", + "cipher", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -212,6 +329,15 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.2.5" @@ -233,6 +359,41 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.5.23" @@ -302,6 +463,32 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -336,6 +523,24 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -343,9 +548,83 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core", "typenum", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "delegate" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc2323e10c92e1cf4d86e11538512e6dc03ceb586842970b6332af3d4046a046" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "des" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" +dependencies = [ + "cipher", +] + [[package]] name = "digest" version = "0.10.7" @@ -353,7 +632,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -367,6 +648,66 @@ dependencies = [ "syn", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encode_unicode" version = "1.0.0" @@ -404,6 +745,22 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "flate2" version = "1.0.35" @@ -414,6 +771,18 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flurry" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf5efcf77a4da27927d3ab0509dec5b0954bb3bc59da5a1de9e52642ebd4cdf9" +dependencies = [ + "ahash", + "num_cpus", + "parking_lot", + "seize", +] + [[package]] name = "fnv" version = "1.0.7" @@ -429,6 +798,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -436,6 +820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -444,12 +829,34 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -468,8 +875,11 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-macro", + "futures-sink", "futures-task", "memchr", "pin-project-lite", @@ -485,6 +895,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -494,8 +905,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", ] [[package]] @@ -504,6 +927,17 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "h2" version = "0.3.26" @@ -535,12 +969,51 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "http" version = "0.2.12" @@ -613,6 +1086,29 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "icu_collections" version = "1.5.0" @@ -782,6 +1278,16 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", +] + [[package]] name = "ipnet" version = "2.10.1" @@ -815,6 +1321,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libc" @@ -822,6 +1331,12 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -861,12 +1376,27 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matchit" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "memchr" version = "2.7.4" @@ -939,6 +1469,74 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "rand", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -960,12 +1558,71 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primeorder", + "rand_core", + "sha2", +] + +[[package]] +name = "pageant" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "032d6201d2fb765158455ae0d5a510c016bb6da7232e5040e39e9c8db12b0afc" +dependencies = [ + "bytes", + "delegate", + "futures", + "rand", + "thiserror 1.0.69", + "tokio", + "windows", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -989,6 +1646,25 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1027,12 +1703,73 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs5" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" +dependencies = [ + "aes", + "cbc", + "der", + "pbkdf2", + "scrypt", + "sha2", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "pkcs5", + "rand_core", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.10.0" @@ -1048,6 +1785,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro2" version = "1.0.92" @@ -1097,13 +1843,57 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.5.8" +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" -dependencies = [ - "bitflags 2.6.0", -] +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reportify" @@ -1111,7 +1901,7 @@ version = "0.1.0" dependencies = [ "backtrace", "console", - "thiserror 2.0.8", + "thiserror 2.0.9", "tracing-error", ] @@ -1158,6 +1948,16 @@ dependencies = [ "winreg", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.8" @@ -1173,6 +1973,27 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rsa" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "sha2", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rugpi-admin" version = "0.1.0" @@ -1208,19 +2029,26 @@ dependencies = [ "nix", "reportify", "reqwest", + "rugpi-cli", "rugpi-common", "serde", "sha1", "tempfile", "thiserror 1.0.69", "toml 0.8.19", - "tracing", - "tracing-subscriber", "url", "uuid", "xscript 0.3.0", ] +[[package]] +name = "rugpi-cli" +version = "0.1.0" +dependencies = [ + "tracing", + "tracing-subscriber", +] + [[package]] name = "rugpi-common" version = "0.1.0" @@ -1258,6 +2086,7 @@ dependencies = [ "indoc", "nix", "reportify", + "rugpi-cli", "rugpi-common", "serde", "serde_json", @@ -1268,6 +2097,22 @@ dependencies = [ "xscript 0.3.0", ] +[[package]] +name = "rugpi-test" +version = "0.1.0" +dependencies = [ + "async-trait", + "clap", + "reportify", + "rugpi-cli", + "russh", + "russh-sftp", + "serde", + "thiserror 2.0.9", + "tokio", + "toml 0.8.19", +] + [[package]] name = "rugpi-util" version = "0.1.0" @@ -1280,12 +2125,167 @@ dependencies = [ "xscript 0.3.0", ] +[[package]] +name = "russh" +version = "0.49.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b206640a622d63529540fc48036aa39f211b2b71432a451156004f40655cdb4" +dependencies = [ + "aes", + "aes-gcm", + "async-trait", + "bitflags 2.6.0", + "byteorder", + "bytes", + "cbc", + "chacha20", + "ctr", + "curve25519-dalek", + "delegate", + "des", + "digest", + "elliptic-curve", + "flate2", + "futures", + "generic-array", + "hex-literal", + "hmac", + "log", + "num-bigint", + "once_cell", + "p256", + "p384", + "p521", + "poly1305", + "rand", + "rand_core", + "rsa", + "russh-cryptovec", + "russh-keys", + "russh-sftp", + "russh-util", + "sha1", + "sha2", + "signature", + "ssh-encoding", + "ssh-key", + "subtle", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "russh-cryptovec" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d8e7e854e1a87e4be00fa287c98cad23faa064d0464434beaa9f014ec3baa98" +dependencies = [ + "libc", + "ssh-encoding", + "winapi", +] + +[[package]] +name = "russh-keys" +version = "0.49.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "788a2439ce385856585346beb37c48e7c9eb5de5f4f00736720a19ffdb3f5bb5" +dependencies = [ + "aes", + "async-trait", + "bcrypt-pbkdf", + "block-padding", + "byteorder", + "bytes", + "cbc", + "ctr", + "data-encoding", + "der", + "digest", + "ecdsa", + "ed25519-dalek", + "elliptic-curve", + "futures", + "getrandom", + "hmac", + "home", + "inout", + "log", + "md5", + "num-integer", + "p256", + "p384", + "p521", + "pageant", + "pbkdf2", + "pkcs1", + "pkcs5", + "pkcs8", + "rand", + "rand_core", + "rsa", + "russh-cryptovec", + "russh-util", + "sec1", + "serde", + "sha1", + "sha2", + "signature", + "spki", + "ssh-encoding", + "ssh-key", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "typenum", + "zeroize", +] + +[[package]] +name = "russh-sftp" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a72c8afe2041c17435eecd85d0b7291841486fd3d1c4082e0b212e5437ca42" +dependencies = [ + "async-trait", + "bitflags 2.6.0", + "bytes", + "chrono", + "flurry", + "log", + "serde", + "thiserror 1.0.69", + "tokio", + "tokio-util", +] + +[[package]] +name = "russh-util" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c7dd577958c0cefbc8f8a2c05c48c88c42e2fdb760dbe9b96ae31d4de97a1f" +dependencies = [ + "chrono", + "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", +] + [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.42" @@ -1342,12 +2342,32 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "pbkdf2", + "salsa20", + "sha2", +] + [[package]] name = "sct" version = "0.7.1" @@ -1358,6 +2378,32 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "seize" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "689224d06523904ebcc9b482c6a3f4f7fb396096645c4cd10c0d2ff7371a34d3" + +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + [[package]] name = "serde" version = "1.0.216" @@ -1467,6 +2513,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "slab" version = "0.4.9" @@ -1498,6 +2554,68 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "aes", + "aes-gcm", + "cbc", + "chacha20", + "cipher", + "ctr", + "poly1305", + "ssh-encoding", + "subtle", +] + +[[package]] +name = "ssh-encoding" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" +dependencies = [ + "base64ct", + "bytes", + "pem-rfc7468", + "sha2", +] + +[[package]] +name = "ssh-key" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b86f5297f0f04d08cabaa0f6bff7cb6aec4d9c3b49d87990d63da9d9156a8c3" +dependencies = [ + "bcrypt-pbkdf", + "ed25519-dalek", + "num-bigint-dig", + "p256", + "p384", + "p521", + "rand_core", + "rsa", + "sec1", + "sha2", + "signature", + "ssh-cipher", + "ssh-encoding", + "subtle", + "zeroize", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1510,6 +2628,12 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.90" @@ -1583,11 +2707,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.8" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f5383f3e0071702bf93ab5ee99b52d26936be9dedd9413067cbdcddcb6141a" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" dependencies = [ - "thiserror-impl 2.0.8", + "thiserror-impl 2.0.9", ] [[package]] @@ -1603,9 +2727,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.8" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f357fcec90b3caef6623a099691be676d033b40a058ac95d2a6ade6fa0c943" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", @@ -1622,6 +2746,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinystr" version = "0.7.6" @@ -1671,6 +2804,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + [[package]] name = "tokio-util" version = "0.7.13" @@ -1831,10 +2976,14 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] @@ -1863,6 +3012,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -2050,6 +3209,79 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -2334,6 +3566,12 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + [[package]] name = "zerovec" version = "0.10.4" diff --git a/Cargo.toml b/Cargo.toml index 9352a52..0954938 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ serde = { version = "1", features = ["derive"] } nix = { version = "0.29", features = ["ioctl", "fs", "mount", "process"] } xscript = "0.3.0" tracing = "0.1" +rugpi-cli = { path = "crates/rugpi-cli" } rugpi-common = { path = "crates/rugpi-common" } reportify = { path = "crates/reportify" } diff --git a/crates/rugpi-bakery/Cargo.toml b/crates/rugpi-bakery/Cargo.toml index e1de946..856a663 100644 --- a/crates/rugpi-bakery/Cargo.toml +++ b/crates/rugpi-bakery/Cargo.toml @@ -16,14 +16,13 @@ indoc = "2.0.5" nix = { workspace = true, features = ["process", "fs"] } reportify.workspace = true reqwest = { version = "0.11.23", features = ["blocking", "rustls-tls", "gzip", "deflate"], default-features = false } +rugpi-cli.workspace = true rugpi-common = { path = "../rugpi-common" } serde = { version = "1.0.171", features = ["derive", "rc"] } sha1 = "0.10.5" tempfile = "3.8.1" thiserror = "1.0.43" toml = "0.8.8" -tracing = "0.1.40" -tracing-subscriber = "0.3.18" url = { version = "2.4.0", features = ["serde"] } uuid = { version = "1.8.0", features = ["v4"] } xscript.workspace = true diff --git a/crates/rugpi-bakery/src/main.rs b/crates/rugpi-bakery/src/main.rs index b586dce..4cb9e17 100644 --- a/crates/rugpi-bakery/src/main.rs +++ b/crates/rugpi-bakery/src/main.rs @@ -15,7 +15,6 @@ use project::{ use reportify::{bail, Report, ResultExt}; use rugpi_common::fsutils::copy_recursive; use serde::Deserialize; -use utils::logging::init_logging; pub mod bake; pub mod project; @@ -114,7 +113,7 @@ pub struct InitCommand { /// Entrypoint of the CLI. fn main() -> BakeryResult<()> { - init_logging(); + rugpi_cli::init(); let args = Args::parse(); match &args.command { diff --git a/crates/rugpi-bakery/src/project/recipes.rs b/crates/rugpi-bakery/src/project/recipes.rs index 57b54a5..6a53749 100644 --- a/crates/rugpi-bakery/src/project/recipes.rs +++ b/crates/rugpi-bakery/src/project/recipes.rs @@ -9,8 +9,8 @@ use std::{ }; use reportify::{bail, whatever, ResultExt}; +use rugpi_cli::warn; use serde::{Deserialize, Serialize}; -use tracing::warn; use super::repositories::RepositoryIdx; use crate::{ diff --git a/crates/rugpi-bakery/src/utils/logging.rs b/crates/rugpi-bakery/src/utils/logging.rs index 5b4c0e4..1ee6a93 100644 --- a/crates/rugpi-bakery/src/utils/logging.rs +++ b/crates/rugpi-bakery/src/utils/logging.rs @@ -1,21 +1,8 @@ -pub fn init_logging() { - let format = tracing_subscriber::fmt::format() - .without_time() - .with_target(false) - .compact(); - tracing_subscriber::fmt() - .with_writer(io::stderr) - .event_format(format) - .init(); -} - #[macro_export] macro_rules! bug { ($msg:literal) => { - tracing::error!("[BUG] {}", $msg) + rugpi_cli::error!("[BUG] {}", $msg) }; } -use std::io; - pub use bug; diff --git a/crates/rugpi-bakery/src/utils/prelude.rs b/crates/rugpi-bakery/src/utils/prelude.rs index a3085e7..a87a149 100644 --- a/crates/rugpi-bakery/src/utils/prelude.rs +++ b/crates/rugpi-bakery/src/utils/prelude.rs @@ -1,5 +1,5 @@ //! Custom prelude. -pub use tracing::{debug, error, info, trace, warn}; +pub use rugpi_cli::{debug, error, info, trace, warn}; pub use super::{logging::bug, once_cell_ext::OnceCellExt}; diff --git a/crates/rugpi-cli/Cargo.toml b/crates/rugpi-cli/Cargo.toml new file mode 100644 index 0000000..6b0db29 --- /dev/null +++ b/crates/rugpi-cli/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rugpi-cli" +edition = "2021" +authors.workspace = true +version.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true + +[dependencies] +tracing.workspace = true +tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } + +[lints] +workspace = true diff --git a/crates/rugpi-cli/src/lib.rs b/crates/rugpi-cli/src/lib.rs new file mode 100644 index 0000000..a43ea0c --- /dev/null +++ b/crates/rugpi-cli/src/lib.rs @@ -0,0 +1,16 @@ +use std::io; + +/// Re-export tracing macros. +pub use tracing::{debug, error, info, trace, warn}; + +/// Initialize logging and other CLI related functionality. +pub fn init() { + let format = tracing_subscriber::fmt::format() + .without_time() + .with_target(false) + .compact(); + tracing_subscriber::fmt() + .with_writer(io::stderr) + .event_format(format) + .init(); +} diff --git a/crates/rugpi-ctrl/Cargo.toml b/crates/rugpi-ctrl/Cargo.toml index 7bf25db..0801933 100644 --- a/crates/rugpi-ctrl/Cargo.toml +++ b/crates/rugpi-ctrl/Cargo.toml @@ -23,6 +23,7 @@ tracing.workspace = true indexmap = "2.5.0" serde_json = "1.0.133" reportify.workspace = true +rugpi-cli.workspace = true [lints] workspace = true diff --git a/crates/rugpi-ctrl/src/cli.rs b/crates/rugpi-ctrl/src/cli.rs index 91684e5..ce4f6cc 100644 --- a/crates/rugpi-ctrl/src/cli.rs +++ b/crates/rugpi-ctrl/src/cli.rs @@ -51,6 +51,8 @@ fn clear_rugpi_state_flag(name: &str) -> SystemResult<()> { } pub fn main() -> SystemResult<()> { + rugpi_cli::init(); + let args = Args::parse(); let system = System::initialize()?; match &args.command { diff --git a/crates/rugpi-test/Cargo.toml b/crates/rugpi-test/Cargo.toml new file mode 100644 index 0000000..f628787 --- /dev/null +++ b/crates/rugpi-test/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "rugpi-test" +edition = "2021" +authors.workspace = true +version.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true + +[dependencies] +async-trait = "0.1.83" +clap.workspace = true +reportify.workspace = true +rugpi-cli.workspace = true +russh = "0.49.2" +russh-sftp = "2.0.6" +serde.workspace = true +thiserror = "2.0.9" +tokio = { version = "1.42.0", features = ["full"] } +toml = "0.8.19" + +[lints] +workspace = true diff --git a/crates/rugpi-test/src/case.rs b/crates/rugpi-test/src/case.rs new file mode 100644 index 0000000..93f611c --- /dev/null +++ b/crates/rugpi-test/src/case.rs @@ -0,0 +1,37 @@ +//! Test case representation. + +use std::path::PathBuf; + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TestCase { + pub vm: VmConfig, + pub steps: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case", tag = "action")] +pub enum TestStep { + Reboot, + Copy { + src: String, + dst: String, + }, + Run { + script: String, + stdin: Option, + }, + Wait { + duration_secs: f64, + }, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct VmConfig { + pub image: PathBuf, + pub stdout: Option, + pub stderr: Option, + pub private_key: PathBuf, +} diff --git a/crates/rugpi-test/src/main.rs b/crates/rugpi-test/src/main.rs new file mode 100644 index 0000000..b33585d --- /dev/null +++ b/crates/rugpi-test/src/main.rs @@ -0,0 +1,65 @@ +use std::{path::PathBuf, time::Duration}; + +use case::{TestCase, TestStep}; +use clap::Parser; +use reportify::{Report, ResultExt}; +use rugpi_cli::info; +use tokio::fs; + +pub mod case; +pub mod qemu; + +reportify::new_whatever_type! { + RugpiTestError +} + +pub type RugpiTestResult = Result>; + +/// Command line arguments. +#[derive(Debug, Parser)] +pub struct Args { + /// Test case file. + case: PathBuf, +} + +#[tokio::main] +pub async fn main() -> RugpiTestResult<()> { + rugpi_cli::init(); + let args = Args::parse(); + + let case = toml::from_str::( + &fs::read_to_string(&args.case) + .await + .whatever("unable to read test case")?, + ) + .whatever("unable to parse test case")?; + + let vm = qemu::start(&case.vm).await?; + + info!("VM running and connected via SSH"); + + for step in &case.steps { + match step { + case::TestStep::Reboot => todo!(), + case::TestStep::Copy { .. } => todo!(), + case::TestStep::Run { script, stdin } => { + info!("running script"); + vm.wait_for_ssh() + .await + .whatever("unable to connect to VM via SSH")?; + if let Err(report) = vm + .run_script(script, stdin.as_ref().map(|p| p.as_ref())) + .await + .whatever::("unable to run script") + { + eprintln!("{:?}", report); + } + } + TestStep::Wait { duration_secs } => { + info!("waiting for {duration_secs} seconds"); + tokio::time::sleep(Duration::from_secs_f64(*duration_secs)).await; + } + } + } + Ok(()) +} diff --git a/crates/rugpi-test/src/qemu.rs b/crates/rugpi-test/src/qemu.rs new file mode 100644 index 0000000..296fa61 --- /dev/null +++ b/crates/rugpi-test/src/qemu.rs @@ -0,0 +1,264 @@ +use std::{path::Path, process::Stdio, sync::Arc, time::Duration}; + +use async_trait::async_trait; +use reportify::{bail, whatever, ErrorExt, Report, ResultExt, Whatever}; +use rugpi_cli::{error, info}; +use russh::{ + client::Handle, + keys::{key::PrivateKeyWithHashAlg, load_secret_key, ssh_key, PrivateKey}, + ChannelMsg, +}; +use russh_sftp::client::SftpSession; +use thiserror::Error; +use tokio::{ + fs, + io::{self, AsyncWriteExt}, + process::{Child, Command}, + sync::{oneshot, Mutex}, + time, +}; + +use crate::{case::VmConfig, RugpiTestResult}; + +pub struct Vm { + #[expect(dead_code, reason = "not currently used")] + child: Child, + ssh_session: Mutex>>, + sftp_session: Mutex>, + #[expect(dead_code, reason = "not currently used")] + vm_config: VmConfig, + private_key: Arc, +} + +impl Vm { + pub async fn run_script( + &self, + script: &str, + stdin: Option<&Path>, + ) -> Result<(), Report> { + if self.call(script, stdin).await.with_info(|_| "run script")? != 0 { + bail!("script failed"); + } + Ok(()) + } + + async fn call(&self, command: &str, stdin: Option<&Path>) -> Result> { + let mut channel = if let Some(ssh_session) = &mut *self.ssh_session.lock().await { + ssh_session.channel_open_session().await? + } else { + bail!("no SSH session"); + }; + channel.exec(true, command).await?; + + let mut code = None; + let mut stdout = tokio::io::stdout(); + let mut stderr = tokio::io::stderr(); + + let (eof_tx, mut eof_rx) = oneshot::channel(); + + if let Some(stdin) = stdin { + let mut stdin_writer = channel.make_writer(); + let mut stdin_file = tokio::fs::File::open(stdin) + .await + .whatever("error opening stdin file")?; + tokio::spawn(async move { + if let Err(err) = tokio::io::copy(&mut stdin_file, &mut stdin_writer).await { + error!("error writing stdin {:?}", err.report::()); + } + let _ = eof_tx.send(()); + }); + }; + + let mut eof_sent = false; + + loop { + tokio::select! { + _ = (&mut eof_rx), if !eof_sent => { + channel.eof().await?; + eof_sent = true; + } + msg = channel.wait() => { + let Some(msg) = msg else { + break; + }; + match msg { + ChannelMsg::ExtendedData { ref data, .. } => { + stderr + .write_all(data) + .await + .whatever("unable to write SSH stderr to terminal")?; + stderr.flush().await.whatever("unable to flush stderr")?; + } + ChannelMsg::Data { ref data } => { + stdout + .write_all(data) + .await + .whatever("unable to write SSH stdout to terminal")?; + stdout.flush().await.whatever("unable to flush stdout")?; + } + ChannelMsg::ExitStatus { exit_status } => { + code = Some(exit_status); + } + _ => {} + } + } + }; + } + if let Some(code) = code { + Ok(code) + } else { + bail!("program did not exit properly") + } + } + pub async fn wait_for_ssh(&self) -> Result<(), Report> { + if let Some(ssh_session) = &*self.ssh_session.lock().await { + if !ssh_session.is_closed() { + return Ok(()); + } + } + let config = Arc::new(russh::client::Config::default()); + let key = + PrivateKeyWithHashAlg::new(self.private_key.clone(), Some(ssh_key::HashAlg::Sha512)) + .whatever("unable to construct SSH key for SSH authentication")?; + time::timeout(Duration::from_secs(30), async { + loop { + info!("trying to connect to VM via SSH"); + if let Ok(Ok(mut ssh_session)) = time::timeout( + Duration::from_secs(1), + russh::client::connect(config.clone(), ("127.0.0.1", 2233), SshHandler), + ) + .await + { + if !ssh_session + .authenticate_publickey("root", key) + .await + .whatever("unable to authenticate via SSH")? + { + bail!("unable to authenticate with the provided private key"); + } + let channel = ssh_session.channel_open_session().await.unwrap(); + channel.request_subsystem(true, "sftp").await.unwrap(); + let sftp = SftpSession::new(channel.into_stream()).await.unwrap(); + info!( + "current SFTP path: {:?}", + sftp.canonicalize(".").await.unwrap() + ); + *self.ssh_session.lock().await = Some(ssh_session); + *self.sftp_session.lock().await = Some(sftp); + break; + } else { + time::sleep(Duration::from_millis(500)).await + } + } + Ok(()) + }) + .await + .map_err(|_| SshError::NotConnected.report()) + .and_then(|result| result) + } +} + +pub async fn start(config: &VmConfig) -> RugpiTestResult { + let private_key = load_secret_key(&config.private_key, None) + .whatever("unable to load private SSH key") + .with_info(|_| format!("path: {:?}", config.private_key))?; + let mut command = Command::new("qemu-system-aarch64"); + command.args(&[ + "-machine", + "virt,accel=hvf", + "-cpu", + "cortex-a72", + "-m", + "2G", + "-smp", + "cpus=2", + ]); + command.arg("-drive"); + command.arg(format!( + "file={},format=raw,if=virtio", + config.image.to_string_lossy() + )); + command.args(&["-device", "virtio-net-pci,netdev=net0", "-netdev"]); + command.arg("user,id=net0,hostfwd=tcp:127.0.0.1:2233-:22"); + command.args(&[ + "-device", + "virtio-rng-pci", + "-bios", + "/opt/homebrew/share/qemu/edk2-aarch64-code.fd", + "-nographic", + "-serial", + "mon:stdio", + ]); + command + .kill_on_drop(true) + .stdout(if config.stdout.is_some() { + Stdio::piped() + } else { + Stdio::null() + }) + .stderr(if config.stderr.is_some() { + Stdio::piped() + } else { + Stdio::null() + }) + .stdin(Stdio::null()); + let mut child = command.spawn().whatever("unable to spawn Qemu")?; + if let Some(stdout) = &config.stdout { + let mut stdout_log = fs::File::create(stdout) + .await + .whatever("unable to create stdout log file")?; + let mut stdout = child.stdout.take().expect("we used Stdio::piped"); + tokio::spawn(async move { io::copy(&mut stdout, &mut stdout_log).await }); + } + if let Some(stderr) = &config.stderr { + let mut stderr_log = fs::File::create(stderr) + .await + .whatever("unable to create stderr log file")?; + let mut stderr = child.stdout.take().expect("we used Stdio::piped"); + tokio::spawn(async move { io::copy(&mut stderr, &mut stderr_log).await }); + } + // We give Qemu some time to start before checking it's exit status. + time::sleep(Duration::from_millis(500)).await; + if let Ok(Some(status)) = child.try_wait() { + Err(whatever!("unable to start qemu") + .with_info(format!("status: {}", status.code().unwrap_or(1)))) + } else { + Ok(Vm { + child, + ssh_session: Mutex::default(), + sftp_session: Mutex::default(), + vm_config: config.clone(), + private_key: Arc::new(private_key), + }) + } +} + +struct SshHandler; + +#[derive(Debug, Error)] +pub enum SshError { + #[error("internal SSH error")] + Ssh(#[from] russh::Error), + #[error("internal SFTP error")] + Sftp(#[from] russh_sftp::client::error::Error), + #[error("SSH session is not connected")] + NotConnected, + #[error("other SSH connection error")] + Other, +} + +impl Whatever for SshError { + fn new() -> Self { + Self::Other + } +} + +#[async_trait] +impl russh::client::Handler for SshHandler { + type Error = SshError; + + async fn check_server_key(&mut self, _: &ssh_key::PublicKey) -> Result { + // We do not care about the identity of the server. + Ok(true) + } +} diff --git a/tests/layers/customized-efi.toml b/tests/layers/customized-efi.toml new file mode 100644 index 0000000..71471ad --- /dev/null +++ b/tests/layers/customized-efi.toml @@ -0,0 +1,26 @@ +parent = "core/debian-bookworm" + +recipes = [ + # Setup Debian for booting via Grub. + "core/debian-grub-setup", + # Set a static hostname. + "core/set-hostname", + # Persist `/root`. + "core/persist-root-home", + # Setup and enable SSH. + "core/ssh", + # Setup the network. + "setup-network", + # Enable discovery of the system in the local network. + "rugpi-extra/avahi", + # Install a static website. + "hello-world", +] + +[parameters."core/set-hostname"] +hostname = "rugpi-template" + +[parameters."core/ssh"] +root_authorized_keys = """ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2tN+ZL8lGnx8rW+vm9ukX1uhKE7GREHitIVxIN3fVh406ksaZzY4FB7JqMqor4SBpR/Eigm6mSSE6KdwSYYC99hakLVvFUG6b6xvB7gOgre8M0JuL9XwBfaUfNln6Hl2Xirlml61JwOWa8Lh+T8mquw9OUK20tkXNPrigVKH+RMQA2V0AQrHnzo9GXMT5HEdAfaVVhL8S1inlKixiPbnvt+nWUSoKGLo+I08w5ZKI88C+saP6VqFiinp57uF0F3oqwcupZe0j6vxGuN5hFg8YGcICFnjXUAVjds8pfcf7aImvYZdp192jC9JAfzx3LzJZLn+kY9hIQkqip/tfTtp56eBb+j9i07PhrDsGiZVNOWf+YG3Cw5Ix6ltOL0dvF1/xFG7O+CGz62w8Y925ytuGgzBkVJ090eznnCjpw+lhNiNFmoqUjiJFjs/VSrqmC5bqdRrqF7YIs61uKl/EyAZaEoHZJazUFFauOjjPK0ksVbAAfqxG4nFmOG0URemSvNE= koehlma@Zaylee +""" \ No newline at end of file diff --git a/tests/recipes/hello-world/html/index.html b/tests/recipes/hello-world/html/index.html new file mode 100644 index 0000000..37325a9 --- /dev/null +++ b/tests/recipes/hello-world/html/index.html @@ -0,0 +1,32 @@ + + + + + + Rugpi: Hello World! + + + + +

Hello World! 👋

+

This is an example static web site served from a customized Rugpi system.

+ + \ No newline at end of file diff --git a/tests/recipes/hello-world/recipe.toml b/tests/recipes/hello-world/recipe.toml new file mode 100644 index 0000000..af6da8e --- /dev/null +++ b/tests/recipes/hello-world/recipe.toml @@ -0,0 +1 @@ +description = "install static webpage" diff --git a/tests/recipes/hello-world/steps/00-packages b/tests/recipes/hello-world/steps/00-packages new file mode 100644 index 0000000..da70e20 --- /dev/null +++ b/tests/recipes/hello-world/steps/00-packages @@ -0,0 +1 @@ +nginx \ No newline at end of file diff --git a/tests/recipes/hello-world/steps/01-install.sh b/tests/recipes/hello-world/steps/01-install.sh new file mode 100755 index 0000000..f1bd2d5 --- /dev/null +++ b/tests/recipes/hello-world/steps/01-install.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -euo pipefail + +systemctl enable nginx + +rm -rf /var/www/html +cp -rTp "${RECIPE_DIR}/html" /var/www/html +chown -R www-data:www-data /var/www/html diff --git a/tests/recipes/setup-network/files/dhcp.network b/tests/recipes/setup-network/files/dhcp.network new file mode 100644 index 0000000..bbd8564 --- /dev/null +++ b/tests/recipes/setup-network/files/dhcp.network @@ -0,0 +1,5 @@ +[Match] +Name=en* + +[Network] +DHCP=yes \ No newline at end of file diff --git a/tests/recipes/setup-network/recipe.toml b/tests/recipes/setup-network/recipe.toml new file mode 100644 index 0000000..993bcbf --- /dev/null +++ b/tests/recipes/setup-network/recipe.toml @@ -0,0 +1 @@ +description = "setup network" diff --git a/tests/recipes/setup-network/steps/00-install.sh b/tests/recipes/setup-network/steps/00-install.sh new file mode 100755 index 0000000..c745201 --- /dev/null +++ b/tests/recipes/setup-network/steps/00-install.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -euo pipefail + +systemctl enable systemd-networkd.service + +install -m 644 "${RECIPE_DIR}/files/dhcp.network" "/etc/systemd/network/" + +# Setup `systemd-resolved`. +mkdir -p /run/systemd/resolve +cat /etc/resolv.conf > /run/systemd/resolve/stub-resolv.conf +apt-get install -y systemd-resolved +systemctl enable systemd-resolved.service +rm -f /etc/resolv.conf +ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf diff --git a/tests/recipes/setup-network/steps/01-packages b/tests/recipes/setup-network/steps/01-packages new file mode 100644 index 0000000..11641a4 --- /dev/null +++ b/tests/recipes/setup-network/steps/01-packages @@ -0,0 +1 @@ +pv \ No newline at end of file diff --git a/tests/rugpi-bakery.toml b/tests/rugpi-bakery.toml index 434449b..275907f 100644 --- a/tests/rugpi-bakery.toml +++ b/tests/rugpi-bakery.toml @@ -20,3 +20,27 @@ target = "rpi-uboot" layer = "customized" architecture = "armhf" target = "rpi-uboot" + +[images.customized-amd64] +layer = "customized-efi" +architecture = "amd64" +target = "generic-grub-efi" + +# This image has a larger size and can be directly used with QEMU. +[images.customized-amd64-vm] +layer = "customized-efi" +architecture = "amd64" +target = "generic-grub-efi" +size = "16G" + +[images.customized-arm64] +layer = "customized-efi" +architecture = "arm64" +target = "generic-grub-efi" + +# This image has a larger size and can be directly used with QEMU. +[images.customized-arm64-vm] +layer = "customized-efi" +architecture = "arm64" +target = "generic-grub-efi" +size = "16G" diff --git a/tests/tests/test-update.toml b/tests/tests/test-update.toml new file mode 100644 index 0000000..9a984d1 --- /dev/null +++ b/tests/tests/test-update.toml @@ -0,0 +1,24 @@ +[vm] +image = "./build/images/customized-arm64-vm.img" +stdout = "./build/stdout.log" +private-key = "/Users/koehlma/.ssh/id_rsa" + +[[steps]] +action = "run" +stdin = "./build/images/customized-arm64.img" +script = """ +rugpi-ctrl system info +pv -f - | rugpi-ctrl update install - +""" + +[[steps]] +action = "wait" +duration_secs = 10.0 + +[[steps]] +action = "run" +script = """ +rugpi-ctrl system info +rugpi-ctrl system commit +rugpi-ctrl system info +""" \ No newline at end of file