difftreelog
feat remowt integration
46 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,15 +3,6 @@
version = 4
[[package]]
-name = "abort-on-drop"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dd6d700ad9af641490c1f7d67980d2de4d1433016e5b12f819448d3c832142a"
-dependencies = [
- "tokio",
-]
-
-[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -23,54 +14,91 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
- "crypto-common",
- "generic-array",
+ "crypto-common 0.1.7",
+ "generic-array 0.14.7",
]
[[package]]
+name = "aead"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef60ac202874e574ce7a7158cc8bca7313dd344322482e4fadee288bf4a306b8"
+dependencies = [
+ "crypto-common 0.2.2",
+ "inout 0.2.2",
+]
+
+[[package]]
name = "aes"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
- "cipher",
+ "cipher 0.4.4",
"cpufeatures 0.2.17",
]
[[package]]
+name = "aes"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1fc76eaeac4c9164506c466d4ffdd8ec9d0c5bf57ee97177c4d8eceb3a0e138"
+dependencies = [
+ "cipher 0.5.2",
+ "cpubits",
+ "cpufeatures 0.3.0",
+ "zeroize",
+]
+
+[[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",
+ "aead 0.5.2",
+ "aes 0.8.4",
+ "cipher 0.4.4",
+ "ctr 0.9.2",
+ "ghash 0.5.1",
"subtle",
]
[[package]]
+name = "aes-gcm"
+version = "0.11.0-rc.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da8c919c118108f144adecad74b425b804ad075580d605d9b33c2d6d1c62a2f8"
+dependencies = [
+ "aead 0.6.0",
+ "aes 0.9.1",
+ "cipher 0.5.2",
+ "ctr 0.10.1",
+ "ghash 0.6.0",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "age"
-version = "0.11.2"
+version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf640be7658959746f1f0f2faab798f6098a9436a8e18e148d18bc9875e13c4b"
+checksum = "a07d86e4272c093c88caf7864a2d09af52a5159180848ca4832a3cdbd7d014d5"
dependencies = [
- "aes",
- "aes-gcm",
+ "aes 0.8.4",
+ "aes-gcm 0.10.3",
"age-core",
"base64 0.21.7",
- "bcrypt-pbkdf",
+ "bcrypt-pbkdf 0.10.0",
"bech32",
- "cbc",
+ "cbc 0.1.2",
"chacha20poly1305",
- "cipher",
+ "cipher 0.4.4",
"cookie-factory",
- "ctr",
- "curve25519-dalek",
- "hmac",
+ "ctr 0.9.2",
+ "curve25519-dalek 4.1.3",
+ "hmac 0.12.1",
"i18n-embed",
"i18n-embed-fl",
"lazy_static",
@@ -78,10 +106,10 @@
"num-traits",
"pin-project",
"rand 0.8.6",
- "rsa",
+ "rsa 0.9.10",
"rust-embed",
- "scrypt",
- "sha2",
+ "scrypt 0.11.0",
+ "sha2 0.10.9",
"subtle",
"which",
"wsl",
@@ -98,12 +126,12 @@
"base64 0.21.7",
"chacha20poly1305",
"cookie-factory",
- "hkdf",
+ "hkdf 0.12.4",
"io_tee",
"nom 7.1.3",
"rand 0.8.6",
"secrecy",
- "sha2",
+ "sha2 0.10.9",
"tempfile",
]
@@ -191,34 +219,144 @@
]
[[package]]
+name = "argon2"
+version = "0.6.0-rc.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7af50940b73bf4e16c15c448a2b121c63f2d68e3e54b6a8731673cb4aa0cdff5"
+dependencies = [
+ "base64ct",
+ "blake2",
+ "cpufeatures 0.3.0",
+ "password-hash",
+]
+
+[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
-name = "async-stream"
-version = "0.3.6"
+name = "async-broadcast"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
+dependencies = [
+ "event-listener",
+ "event-listener-strategy",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-channel"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
+checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
dependencies = [
- "async-stream-impl",
+ "concurrent-queue",
+ "event-listener-strategy",
"futures-core",
"pin-project-lite",
]
[[package]]
-name = "async-stream-impl"
-version = "0.3.6"
+name = "async-executor"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a"
+dependencies = [
+ "async-task",
+ "concurrent-queue",
+ "fastrand",
+ "futures-lite",
+ "pin-project-lite",
+ "slab",
+]
+
+[[package]]
+name = "async-io"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "concurrent-queue",
+ "futures-io",
+ "futures-lite",
+ "parking",
+ "polling",
+ "rustix 1.1.4",
+ "slab",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "async-lock"
+version = "3.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311"
+dependencies = [
+ "event-listener",
+ "event-listener-strategy",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-process"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
+dependencies = [
+ "async-channel",
+ "async-io",
+ "async-lock",
+ "async-signal",
+ "async-task",
+ "blocking",
+ "cfg-if",
+ "event-listener",
+ "futures-lite",
+ "rustix 1.1.4",
+]
+
+[[package]]
+name = "async-recursion"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
+checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "async-signal"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485"
+dependencies = [
+ "async-io",
+ "async-lock",
+ "atomic-waker",
+ "cfg-if",
+ "futures-core",
+ "futures-io",
+ "rustix 1.1.4",
+ "signal-hook-registry",
+ "slab",
+ "windows-sys 0.61.2",
]
[[package]]
+name = "async-task"
+version = "4.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
+
+[[package]]
name = "async-trait"
version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -226,10 +364,19 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
+name = "async_fn_traits"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc58d489c5f2d2c5be31b9004cec7af25a70d23df4d8111715eee736234cf217"
+dependencies = [
+ "paste",
+]
+
+[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -237,56 +384,15 @@
[[package]]
name = "autocfg"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
-
-[[package]]
-name = "axum"
-version = "0.7.9"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
-dependencies = [
- "async-trait",
- "axum-core",
- "bytes",
- "futures-util",
- "http",
- "http-body",
- "http-body-util",
- "itoa",
- "matchit",
- "memchr",
- "mime",
- "percent-encoding",
- "pin-project-lite",
- "rustversion",
- "serde",
- "sync_wrapper",
- "tower 0.5.3",
- "tower-layer",
- "tower-service",
-]
+checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
-name = "axum-core"
-version = "0.4.5"
+name = "base16ct"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
-dependencies = [
- "async-trait",
- "bytes",
- "futures-util",
- "http",
- "http-body",
- "http-body-util",
- "mime",
- "pin-project-lite",
- "rustversion",
- "sync_wrapper",
- "tower-layer",
- "tower-service",
-]
+checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6"
[[package]]
name = "base64"
@@ -321,9 +427,20 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2"
dependencies = [
- "blowfish",
- "pbkdf2",
- "sha2",
+ "blowfish 0.9.1",
+ "pbkdf2 0.12.2",
+ "sha2 0.10.9",
+]
+
+[[package]]
+name = "bcrypt-pbkdf"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "144e573728da132683b9488acd528274c790e07fc06ff81ee29f9d8f8b1041e0"
+dependencies = [
+ "blowfish 0.10.0",
+ "pbkdf2 0.13.0",
+ "sha2 0.11.0",
]
[[package]]
@@ -333,14 +450,45 @@
checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
[[package]]
-name = "better-command"
-version = "0.1.0"
+name = "bifrostlink"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fb01af731c11dd31b23783a83a36a29f644cc1972481f6fa4f4fabc709079eb"
dependencies = [
- "regex",
+ "async-trait",
+ "async_fn_traits",
+ "bifrostlink-macros",
+ "bytes",
+ "derivative",
+ "futures",
"serde",
"serde_json",
+ "tokio",
+ "tracing",
+ "uuid",
+]
+
+[[package]]
+name = "bifrostlink-macros"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c4b7a5fb38b36bd81910c17ebf369f9296e508d92b1277a768a63c8a2254fdb"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "bifrostlink-ports"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "977acfcb8ed3c24ab7c2f76fb3eeebff1533c72708733ce6020f2501980b7cf2"
+dependencies = [
+ "bifrostlink",
+ "bytes",
+ "tokio",
"tracing",
- "tracing-indicatif",
]
[[package]]
@@ -359,15 +507,24 @@
"quote",
"regex",
"rustc-hash 2.1.2",
- "shlex",
- "syn",
+ "shlex 1.3.0",
+ "syn 2.0.117",
]
[[package]]
name = "bitflags"
-version = "2.11.1"
+version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
+checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
+
+[[package]]
+name = "blake2"
+version = "0.11.0-rc.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "061f1a09225e328e1ffbb378d2d49923c0ca5fee19fb5ac1cc9c1e9d52b93690"
+dependencies = [
+ "digest 0.11.3",
+]
[[package]]
name = "block-buffer"
@@ -375,33 +532,85 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
- "generic-array",
+ "generic-array 0.14.7",
]
[[package]]
+name = "block-buffer"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
+dependencies = [
+ "hybrid-array",
+ "zeroize",
+]
+
+[[package]]
name = "block-padding"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
dependencies = [
- "generic-array",
+ "generic-array 0.14.7",
]
[[package]]
+name = "block-padding"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b"
+dependencies = [
+ "hybrid-array",
+]
+
+[[package]]
+name = "blocking"
+version = "1.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21"
+dependencies = [
+ "async-channel",
+ "async-task",
+ "futures-io",
+ "futures-lite",
+ "piper",
+]
+
+[[package]]
name = "blowfish"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
dependencies = [
"byteorder",
- "cipher",
+ "cipher 0.4.4",
+]
+
+[[package]]
+name = "blowfish"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62ce3946557b35e71d1bbe07ec385073ce9eda05043f95de134eb578fcf1a298"
+dependencies = [
+ "byteorder",
+ "cipher 0.5.2",
+]
+
+[[package]]
+name = "bstr"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
+dependencies = [
+ "memchr",
+ "serde",
]
[[package]]
name = "bumpalo"
-version = "3.20.2"
+version = "3.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
+checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
[[package]]
name = "bytecount"
@@ -422,22 +631,40 @@
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
+name = "camino"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
name = "cbc"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
dependencies = [
- "cipher",
+ "cipher 0.4.4",
]
[[package]]
+name = "cbc"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896"
+dependencies = [
+ "cipher 0.5.2",
+]
+
+[[package]]
name = "cc"
-version = "1.2.60"
+version = "1.2.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
+checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
dependencies = [
"find-msvc-tools",
- "shlex",
+ "shlex 2.0.1",
]
[[package]]
@@ -468,7 +695,7 @@
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
dependencies = [
"cfg-if",
- "cipher",
+ "cipher 0.4.4",
"cpufeatures 0.2.17",
]
@@ -479,8 +706,10 @@
checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
dependencies = [
"cfg-if",
+ "cipher 0.5.2",
"cpufeatures 0.3.0",
"rand_core 0.10.1",
+ "zeroize",
]
[[package]]
@@ -489,18 +718,18 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
- "aead",
+ "aead 0.5.2",
"chacha20 0.9.1",
- "cipher",
- "poly1305",
+ "cipher 0.4.4",
+ "poly1305 0.8.0",
"zeroize",
]
[[package]]
name = "chrono"
-version = "0.4.44"
+version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
+checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
dependencies = [
"iana-time-zone",
"js-sys",
@@ -516,8 +745,20 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
- "crypto-common",
- "inout",
+ "crypto-common 0.1.7",
+ "inout 0.1.4",
+ "zeroize",
+]
+
+[[package]]
+name = "cipher"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c"
+dependencies = [
+ "block-buffer 0.12.1",
+ "crypto-common 0.2.2",
+ "inout 0.2.2",
"zeroize",
]
@@ -559,9 +800,9 @@
[[package]]
name = "clap_complete"
-version = "4.6.2"
+version = "4.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ff7a1dccbdd8b078c2bdebff47e404615151534d5043da397ec50286816f9cb"
+checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772"
dependencies = [
"clap",
]
@@ -575,7 +816,7 @@
"heck",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -585,6 +826,12 @@
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]]
+name = "cmov"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
+
+[[package]]
name = "codespan-reporting"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -602,6 +849,15 @@
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
+name = "concurrent-queue"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
name = "console"
version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -615,9 +871,9 @@
[[package]]
name = "const-hex"
-version = "1.18.1"
+version = "1.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "531185e432bb31db1ecda541e9e7ab21468d4d844ad7505e0546a49b4945d49b"
+checksum = "33e2a781ebdf4467d1428dc4593067825fb646f6871475098d8577421af73558"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
@@ -632,6 +888,12 @@
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
+name = "const-oid"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
+
+[[package]]
name = "cookie-factory"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -657,6 +919,12 @@
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
+name = "cpubits"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae"
+
+[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -684,23 +952,86 @@
]
[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
+name = "crypto-bigint"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42a0d26b245348befa0c121944541476763dcc46ede886c88f9d12e1697d27c3"
+dependencies = [
+ "cpubits",
+ "ctutils",
+ "getrandom 0.4.2",
+ "hybrid-array",
+ "num-traits",
+ "rand_core 0.10.1",
+ "serdect",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "crypto-common"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
- "generic-array",
+ "generic-array 0.14.7",
"rand_core 0.6.4",
"typenum",
]
[[package]]
+name = "crypto-common"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
+dependencies = [
+ "getrandom 0.4.2",
+ "hybrid-array",
+ "rand_core 0.10.1",
+]
+
+[[package]]
+name = "crypto-primes"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3633a51a39c69ebbaa4feaa694bd83d241e4093901c84a0963b19d9bb3f0cf8f"
+dependencies = [
+ "crypto-bigint",
+ "rand_core 0.10.1",
+]
+
+[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
- "cipher",
+ "cipher 0.4.4",
+]
+
+[[package]]
+name = "ctr"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baaca1c4b237092596f64d571e9db6ce4109c4ef9742e27590f1709594461f21"
+dependencies = [
+ "cipher 0.5.2",
+]
+
+[[package]]
+name = "ctutils"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
+dependencies = [
+ "cmov",
+ "subtle",
]
[[package]]
@@ -718,14 +1049,30 @@
"cfg-if",
"cpufeatures 0.2.17",
"curve25519-dalek-derive",
- "digest",
- "fiat-crypto",
+ "digest 0.10.7",
+ "fiat-crypto 0.2.9",
"rustc_version",
"subtle",
"zeroize",
]
[[package]]
+name = "curve25519-dalek"
+version = "5.0.0-rc.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f359e08ca85e7bd759e1fd933ff2bccd81864c60a8fba0e259c7f822b0924bf"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.0",
+ "curve25519-dalek-derive",
+ "digest 0.11.3",
+ "fiat-crypto 0.3.0",
+ "rustc_version",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "curve25519-dalek-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -733,7 +1080,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -759,11 +1106,11 @@
dependencies = [
"cc",
"codespan-reporting",
- "indexmap 2.14.0",
+ "indexmap",
"proc-macro2",
"quote",
"scratch",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -774,10 +1121,10 @@
dependencies = [
"clap",
"codespan-reporting",
- "indexmap 2.14.0",
+ "indexmap",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -792,10 +1139,27 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6acc6b5822b9526adfb4fc377b67128fdd60aac757cc4a741a6278603f763cf"
dependencies = [
- "indexmap 2.14.0",
+ "indexmap",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "data-encoding"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8"
+
+[[package]]
+name = "delegate"
+version = "0.13.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370"
+dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -804,7 +1168,18 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [
- "const-oid",
+ "const-oid 0.9.6",
+ "zeroize",
+]
+
+[[package]]
+name = "der"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b"
+dependencies = [
+ "const-oid 0.10.2",
+ "pem-rfc7468",
"zeroize",
]
@@ -813,9 +1188,25 @@
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
+
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "des"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "916a94e407b54f9034d71dd748234cd1e516ced6284009906ae246f177eafe5a"
dependencies = [
- "powerfmt",
- "serde_core",
+ "cipher 0.5.2",
]
[[package]]
@@ -824,21 +1215,48 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
- "block-buffer",
- "const-oid",
- "crypto-common",
+ "block-buffer 0.10.4",
+ "const-oid 0.9.6",
+ "crypto-common 0.1.7",
"subtle",
]
[[package]]
+name = "digest"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
+dependencies = [
+ "block-buffer 0.12.1",
+ "const-oid 0.10.2",
+ "crypto-common 0.2.2",
+ "ctutils",
+]
+
+[[package]]
name = "displaydoc"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "ecdsa"
+version = "0.17.0-rc.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54fb064faabbee66e1fc8e5c5a9458d4269dc2d8b638fe86a425adb2510d1a96"
+dependencies = [
+ "der 0.8.0",
+ "digest 0.11.3",
+ "elliptic-curve",
+ "rfc6979",
+ "signature 3.0.0",
+ "spki 0.8.0",
+ "zeroize",
]
[[package]]
@@ -847,29 +1265,78 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
- "pkcs8",
- "signature",
+ "pkcs8 0.10.2",
+ "signature 2.2.0",
]
[[package]]
+name = "ed25519"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29fcf32e6c73d1079f83ab4d782de2d81620346a5f38c6237a86a22f8368980a"
+dependencies = [
+ "pkcs8 0.11.0",
+ "signature 3.0.0",
+]
+
+[[package]]
name = "ed25519-dalek"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
dependencies = [
- "curve25519-dalek",
- "ed25519",
+ "curve25519-dalek 4.1.3",
+ "ed25519 2.2.3",
"serde",
- "sha2",
+ "sha2 0.10.9",
"subtle",
"zeroize",
]
[[package]]
+name = "ed25519-dalek"
+version = "3.0.0-rc.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60"
+dependencies = [
+ "curve25519-dalek 5.0.0-rc.0",
+ "ed25519 3.0.0",
+ "rand_core 0.10.1",
+ "serde",
+ "sha2 0.11.0",
+ "signature 3.0.0",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "either"
-version = "1.15.0"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
+
+[[package]]
+name = "elliptic-curve"
+version = "0.14.0-rc.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+checksum = "102d3643d30dd8b559613c5cced68317199597fffb278cdc88daa2ef7fafc935"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "crypto-common 0.2.2",
+ "digest 0.11.3",
+ "ff",
+ "group",
+ "hkdf 0.13.0",
+ "hybrid-array",
+ "once_cell",
+ "pem-rfc7468",
+ "pkcs8 0.11.0",
+ "rand_core 0.10.1",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
[[package]]
name = "encode_unicode"
@@ -878,6 +1345,45 @@
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
[[package]]
+name = "endi"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
+
+[[package]]
+name = "enum_dispatch"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd"
+dependencies = [
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "enumflags2"
+version = "0.7.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef"
+dependencies = [
+ "enumflags2_derive",
+ "serde",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.7.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
name = "env_filter"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -915,18 +1421,55 @@
]
[[package]]
+name = "event-listener"
+version = "5.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
+dependencies = [
+ "concurrent-queue",
+ "parking",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "event-listener-strategy"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
+dependencies = [
+ "event-listener",
+ "pin-project-lite",
+]
+
+[[package]]
name = "fastrand"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
+name = "ff"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f"
+dependencies = [
+ "rand_core 0.10.1",
+ "subtle",
+]
+
+[[package]]
name = "fiat-crypto"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
+name = "fiat-crypto"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24"
+
+[[package]]
name = "find-crate"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -940,12 +1483,6 @@
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
-
-[[package]]
-name = "fixedbitset"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]]
name = "flate2"
@@ -961,42 +1498,27 @@
name = "fleet"
version = "0.2.0"
dependencies = [
- "abort-on-drop",
- "age",
- "age-core",
"anyhow",
- "async-trait",
- "base64 0.22.1",
- "better-command",
- "chrono",
+ "camino",
"clap",
"clap_complete",
"fleet-base",
- "fleet-shared",
"futures",
- "hostname",
"human-repr",
"indicatif",
"itertools 0.14.0",
"nix-eval",
- "nixlike",
- "nom 8.0.0",
- "openssh",
"opentelemetry",
"opentelemetry-appender-tracing",
"opentelemetry-exporter-env",
"opentelemetry_sdk",
- "peg",
- "regex",
+ "remowt-fleet",
"serde",
"serde_json",
- "shlex",
+ "shlex 1.3.0",
"tabled",
"tempfile",
- "thiserror 2.0.18",
- "time",
"tokio",
- "tokio-util",
"tracing",
"tracing-indicatif",
"tracing-opentelemetry",
@@ -1009,7 +1531,7 @@
dependencies = [
"age",
"anyhow",
- "better-command",
+ "camino",
"chrono",
"clap",
"fleet-shared",
@@ -1020,17 +1542,18 @@
"nix-eval",
"nixlike",
"nom 8.0.0",
- "openssh",
"rand 0.10.1",
+ "remowt-client",
+ "remowt-endpoints",
+ "remowt-fleet",
+ "remowt-link-shared",
+ "remowt-ui-prompt",
"serde",
"serde_json",
"tabled",
"tempfile",
- "thiserror 2.0.18",
"time",
"tokio",
- "tokio-util",
- "toml_edit",
"tracing",
]
@@ -1042,13 +1565,13 @@
"anyhow",
"base64 0.22.1",
"clap",
- "ed25519-dalek",
+ "ed25519-dalek 2.2.0",
"fleet-shared",
"hex",
- "hmac",
- "pbkdf2",
+ "hmac 0.12.1",
+ "pbkdf2 0.12.2",
"rand 0.10.1",
- "sha2",
+ "sha2 0.10.9",
"x25519-dalek",
]
@@ -1197,6 +1720,19 @@
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
[[package]]
+name = "futures-lite"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "parking",
+ "pin-project-lite",
+]
+
+[[package]]
name = "futures-macro"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1204,7 +1740,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -1247,6 +1783,17 @@
]
[[package]]
+name = "generic-array"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2e55f16dcf0e9c00efbe2e655ffe45fc98e7066b52bc92f8a79e64060a79351"
+dependencies = [
+ "generic-array 0.14.7",
+ "rustversion",
+ "typenum",
+]
+
+[[package]]
name = "getrandom"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1280,11 +1827,13 @@
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
+ "js-sys",
"libc",
"r-efi 6.0.0",
"rand_core 0.10.1",
"wasip2",
"wasip3",
+ "wasm-bindgen",
]
[[package]]
@@ -1294,20 +1843,53 @@
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
dependencies = [
"opaque-debug",
- "polyval",
+ "polyval 0.6.2",
]
[[package]]
+name = "ghash"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eecf2d5dc9b66b732b97707a0210906b1d30523eb773193ab777c0c84b3e8d5"
+dependencies = [
+ "polyval 0.7.1",
+]
+
+[[package]]
name = "glob"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
+name = "globset"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "group"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4"
+dependencies = [
+ "ff",
+ "rand_core 0.10.1",
+ "subtle",
+]
+
+[[package]]
name = "h2"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
+checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733"
dependencies = [
"atomic-waker",
"bytes",
@@ -1315,7 +1897,7 @@
"futures-core",
"futures-sink",
"http",
- "indexmap 2.14.0",
+ "indexmap",
"slab",
"tokio",
"tokio-util",
@@ -1324,12 +1906,6 @@
[[package]]
name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
-[[package]]
-name = "hashbrown"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
@@ -1339,9 +1915,9 @@
[[package]]
name = "hashbrown"
-version = "0.17.0"
+version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
@@ -1350,27 +1926,57 @@
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
+name = "hermit-abi"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
+
+[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
+name = "hex-literal"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1"
+
+[[package]]
name = "hkdf"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
- "hmac",
+ "hmac 0.12.1",
]
[[package]]
+name = "hkdf"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018"
+dependencies = [
+ "hmac 0.13.0",
+]
+
+[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
- "digest",
+ "digest 0.10.7",
+]
+
+[[package]]
+name = "hmac"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f"
+dependencies = [
+ "digest 0.11.3",
]
[[package]]
@@ -1395,9 +2001,9 @@
[[package]]
name = "http"
-version = "1.4.0"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
+checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"
dependencies = [
"bytes",
"itoa",
@@ -1433,22 +2039,28 @@
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
-name = "httpdate"
-version = "1.0.3"
+name = "human-repr"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+checksum = "f58b778a5761513caf593693f8951c97a5b610841e754788400f32102eefdff1"
[[package]]
-name = "human-repr"
-version = "1.1.0"
+name = "hybrid-array"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f58b778a5761513caf593693f8951c97a5b610841e754788400f32102eefdff1"
+checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
+dependencies = [
+ "ctutils",
+ "subtle",
+ "typenum",
+ "zeroize",
+]
[[package]]
name = "hyper"
-version = "1.9.0"
+version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca"
+checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
dependencies = [
"atomic-waker",
"bytes",
@@ -1458,7 +2070,6 @@
"http",
"http-body",
"httparse",
- "httpdate",
"itoa",
"pin-project-lite",
"smallvec",
@@ -1512,7 +2123,7 @@
"libc",
"percent-encoding",
"pin-project-lite",
- "socket2 0.6.3",
+ "socket2",
"tokio",
"tower-service",
"tracing",
@@ -1567,7 +2178,7 @@
"proc-macro2",
"quote",
"strsim",
- "syn",
+ "syn 2.0.117",
"unic-langid",
]
@@ -1581,7 +2192,7 @@
"i18n-config",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -1709,9 +2320,9 @@
[[package]]
name = "idna_adapter"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714"
dependencies = [
"icu_normalizer",
"icu_properties",
@@ -1719,22 +2330,12 @@
[[package]]
name = "indexmap"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown 0.12.3",
-]
-
-[[package]]
-name = "indexmap"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
- "hashbrown 0.17.0",
+ "hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -1768,11 +2369,33 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
dependencies = [
- "block-padding",
- "generic-array",
+ "block-padding 0.3.3",
+ "generic-array 0.14.7",
]
[[package]]
+name = "inout"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
+dependencies = [
+ "block-padding 0.4.2",
+ "hybrid-array",
+]
+
+[[package]]
+name = "internal-russh-num-bigint"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae8e22120c32fb4d19ec55fba35015f57095cd95a2e3b732e44457f5915b2ee8"
+dependencies = [
+ "num-integer",
+ "num-traits",
+ "rand 0.10.1",
+ "rand_core 0.10.1",
+]
+
+[[package]]
name = "intl-memoizer"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1802,16 +2425,6 @@
version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
-
-[[package]]
-name = "iri-string"
-version = "0.7.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20"
-dependencies = [
- "memchr",
- "serde",
-]
[[package]]
name = "is_terminal_polyfill"
@@ -1845,17 +2458,36 @@
[[package]]
name = "js-sys"
-version = "0.3.95"
+version = "0.3.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca"
+checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
dependencies = [
"cfg-if",
"futures-util",
- "once_cell",
"wasm-bindgen",
]
[[package]]
+name = "keccak"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.0",
+]
+
+[[package]]
+name = "kem"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd"
+dependencies = [
+ "crypto-common 0.2.2",
+ "rand_core 0.10.1",
+]
+
+[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1872,9 +2504,9 @@
[[package]]
name = "libc"
-version = "0.2.185"
+version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "libloading"
@@ -1893,6 +2525,18 @@
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]]
+name = "libredox"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3"
+dependencies = [
+ "bitflags",
+ "libc",
+ "plain",
+ "redox_syscall 0.8.1",
+]
+
+[[package]]
name = "link-cplusplus"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1936,9 +2580,9 @@
[[package]]
name = "log"
-version = "0.4.29"
+version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
[[package]]
name = "lru-slab"
@@ -1956,22 +2600,25 @@
]
[[package]]
-name = "matchit"
-version = "0.7.3"
+name = "md5"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
+checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0"
[[package]]
name = "memchr"
-version = "2.8.0"
+version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
[[package]]
-name = "mime"
-version = "0.3.17"
+name = "memoffset"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
+dependencies = [
+ "autocfg",
+]
[[package]]
name = "minimal-lexical"
@@ -1991,9 +2638,9 @@
[[package]]
name = "mio"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
+checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
dependencies = [
"libc",
"wasi",
@@ -2001,16 +2648,35 @@
]
[[package]]
-name = "multimap"
-version = "0.10.1"
+name = "ml-kem"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e15f3e5b957493873e396a66914e83e616b6afe335cdef7efe5c6e1216aba66"
+dependencies = [
+ "hybrid-array",
+ "kem",
+ "module-lattice",
+ "pkcs8 0.11.0",
+ "rand_core 0.10.1",
+ "sha3",
+]
+
+[[package]]
+name = "module-lattice"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
+checksum = "0c61b87c9683ab7cb1c6871d261ad5479b6b10ceb52c4352aaca3b5d35a8febe"
+dependencies = [
+ "ctutils",
+ "hybrid-array",
+ "num-traits",
+]
[[package]]
name = "nix"
-version = "0.31.2"
+version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3"
+checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
dependencies = [
"bitflags",
"cfg-if",
@@ -2024,15 +2690,16 @@
dependencies = [
"anyhow",
"bindgen",
+ "camino",
"cxx",
"cxx-build",
+ "futures",
"itertools 0.14.0",
"nixlike",
"pkg-config",
"serde",
"serde_json",
"test-log",
- "thiserror 2.0.18",
"tokio",
"tracing",
"tracing-indicatif",
@@ -2040,6 +2707,13 @@
]
[[package]]
+name = "nix-plugin-fleet"
+version = "0.1.0"
+dependencies = [
+ "fleet-base",
+]
+
+[[package]]
name = "nixlike"
version = "0.1.0"
dependencies = [
@@ -2047,8 +2721,6 @@
"linked-hash-map",
"peg",
"serde",
- "serde-transcode",
- "serde_json",
"thiserror 2.0.18",
]
@@ -2081,6 +2753,16 @@
]
[[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",
+]
+
+[[package]]
name = "num-bigint-dig"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2098,9 +2780,9 @@
[[package]]
name = "num-conv"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967"
+checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
[[package]]
name = "num-integer"
@@ -2151,20 +2833,6 @@
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
-name = "openssh"
-version = "0.11.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d534c4bfecb0ed71dea4db444a5922a294d15cf40e700548f27295e1feb0ef18"
-dependencies = [
- "libc",
- "once_cell",
- "shell-escape",
- "tempfile",
- "thiserror 2.0.18",
- "tokio",
-]
-
-[[package]]
name = "openssl-probe"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2229,12 +2897,12 @@
"opentelemetry-http",
"opentelemetry-proto",
"opentelemetry_sdk",
- "prost 0.14.3",
+ "prost",
"reqwest",
"serde_json",
"thiserror 2.0.18",
"tokio",
- "tonic 0.14.5",
+ "tonic",
"tracing",
]
@@ -2248,10 +2916,10 @@
"const-hex",
"opentelemetry",
"opentelemetry_sdk",
- "prost 0.14.3",
+ "prost",
"serde",
"serde_json",
- "tonic 0.14.5",
+ "tonic",
"tonic-prost",
]
@@ -2271,6 +2939,77 @@
]
[[package]]
+name = "ordered-stream"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "p256"
+version = "0.14.0-rc.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41adc63effe99d48837a8cc0e6d7a77e32ae6a07f6000df466178dbc2193093e"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "primefield",
+ "primeorder",
+ "sha2 0.11.0",
+]
+
+[[package]]
+name = "p384"
+version = "0.14.0-rc.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bd5333afa5ae0347f39e6a0f2c9c155da431583fd71fe5555bd0521b4ccaf02"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "fiat-crypto 0.3.0",
+ "primefield",
+ "primeorder",
+ "sha2 0.11.0",
+]
+
+[[package]]
+name = "p521"
+version = "0.14.0-rc.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3a5297f53dc16d35909060ba3032cff7867e8809f01e273ff325579d5f0ceae"
+dependencies = [
+ "base16ct",
+ "ecdsa",
+ "elliptic-curve",
+ "primefield",
+ "primeorder",
+ "sha2 0.11.0",
+]
+
+[[package]]
+name = "pageant"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f3a5ae18f65a85c67a77d18d42d3606c07948e3c17c1e5f74852b26589e88a5"
+dependencies = [
+ "base16ct",
+ "byteorder",
+ "bytes",
+ "delegate",
+ "futures",
+ "log",
+ "rand 0.10.1",
+ "sha2 0.11.0",
+ "thiserror 2.0.18",
+ "tokio",
+ "windows",
+ "windows-strings",
+]
+
+[[package]]
name = "papergrid"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2282,6 +3021,12 @@
]
[[package]]
+name = "parking"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
+
+[[package]]
name = "parking_lot"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2299,26 +3044,51 @@
dependencies = [
"cfg-if",
"libc",
- "redox_syscall",
+ "redox_syscall 0.5.18",
"smallvec",
"windows-link",
]
[[package]]
+name = "password-hash"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aab41826031698d6ffcd9cff78ef56ef998e39dc7e5067cdfebe373842d4723b"
+dependencies = [
+ "phc",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
name = "pbkdf2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
- "digest",
- "hmac",
+ "digest 0.10.7",
+ "hmac 0.12.1",
+]
+
+[[package]]
+name = "pbkdf2"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629"
+dependencies = [
+ "digest 0.11.3",
+ "hmac 0.13.0",
]
[[package]]
name = "peg"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9928cfca101b36ec5163e70049ee5368a8a1c3c6efc9ca9c5f9cc2f816152477"
+checksum = "0aad070be5b63aa72103f2fcdd70a83adbd5e90112ce5b574171ff1c65501773"
dependencies = [
"peg-macros",
"peg-runtime",
@@ -2326,9 +3096,9 @@
[[package]]
name = "peg-macros"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6298ab04c202fa5b5d52ba03269fb7b74550b150323038878fe6c372d8280f71"
+checksum = "ddd8ef6825cae95355031ae26a99b616a2a21f22ba2de0197c43dfb05acbe7ee"
dependencies = [
"peg-runtime",
"proc-macro2",
@@ -2337,18 +3107,17 @@
[[package]]
name = "peg-runtime"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "132dca9b868d927b35b5dd728167b2dee150eb1ad686008fc71ccb298b776fca"
+checksum = "7011d97b484a5ebdc4b1fdb3b12d5e4bbbea56e9d22b688f2e79e04b65a7d8a6"
[[package]]
-name = "pem"
-version = "3.0.6"
+name = "pem-rfc7468"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be"
+checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9"
dependencies = [
- "base64 0.22.1",
- "serde_core",
+ "base64ct",
]
[[package]]
@@ -2358,33 +3127,33 @@
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
-name = "petgraph"
-version = "0.7.1"
+name = "phc"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772"
+checksum = "44dc769b75f93afdddd8c7fa12d685292ddeff1e66f7f0f3a234cf1818afe892"
dependencies = [
- "fixedbitset",
- "indexmap 2.14.0",
+ "base64ct",
+ "ctutils",
]
[[package]]
name = "pin-project"
-version = "1.1.11"
+version = "1.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517"
+checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.1.11"
+version = "1.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6"
+checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -2394,33 +3163,102 @@
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
+name = "piper"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1"
+dependencies = [
+ "atomic-waker",
+ "fastrand",
+ "futures-io",
+]
+
+[[package]]
name = "pkcs1"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
dependencies = [
- "der",
- "pkcs8",
- "spki",
+ "der 0.7.10",
+ "pkcs8 0.10.2",
+ "spki 0.7.3",
]
[[package]]
+name = "pkcs1"
+version = "0.8.0-rc.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e"
+dependencies = [
+ "der 0.8.0",
+ "spki 0.8.0",
+]
+
+[[package]]
+name = "pkcs5"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "279a91971a1d8eb1260a30938eae3be9cb67b472dffecb222fbbbe2fd2dc1453"
+dependencies = [
+ "aes 0.9.1",
+ "cbc 0.2.1",
+ "der 0.8.0",
+ "pbkdf2 0.13.0",
+ "rand_core 0.10.1",
+ "scrypt 0.12.0",
+ "sha2 0.11.0",
+ "spki 0.8.0",
+]
+
+[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
- "der",
- "spki",
+ "der 0.7.10",
+ "spki 0.7.3",
]
[[package]]
+name = "pkcs8"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7"
+dependencies = [
+ "der 0.8.0",
+ "pkcs5",
+ "rand_core 0.10.1",
+ "spki 0.8.0",
+]
+
+[[package]]
name = "pkg-config"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
[[package]]
+name = "plain"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
+
+[[package]]
+name = "polling"
+version = "3.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
+dependencies = [
+ "cfg-if",
+ "concurrent-queue",
+ "hermit-abi",
+ "pin-project-lite",
+ "rustix 1.1.4",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
name = "poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2428,7 +3266,18 @@
dependencies = [
"cpufeatures 0.2.17",
"opaque-debug",
- "universal-hash",
+ "universal-hash 0.5.1",
+]
+
+[[package]]
+name = "poly1305"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a00baa632505d05512f48a963e16051c54fda9a95cc9acea1a4e3c90991c4a2e"
+dependencies = [
+ "cpufeatures 0.3.0",
+ "universal-hash 0.6.1",
+ "zeroize",
]
[[package]]
@@ -2440,7 +3289,18 @@
"cfg-if",
"cpufeatures 0.2.17",
"opaque-debug",
- "universal-hash",
+ "universal-hash 0.5.1",
+]
+
+[[package]]
+name = "polyval"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dfc63250416fea14f5749b90725916a6c903f599d51cb635aa7a52bfd03eede"
+dependencies = [
+ "cpubits",
+ "cpufeatures 0.3.0",
+ "universal-hash 0.6.1",
]
[[package]]
@@ -2480,10 +3340,42 @@
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
- "syn",
+ "syn 2.0.117",
+]
+
+[[package]]
+name = "primefield"
+version = "0.14.0-rc.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1d7e42f46a29abc16fb621a3466ee453358ebaae48a9e515f287e0af052ed8f"
+dependencies = [
+ "crypto-bigint",
+ "crypto-common 0.2.2",
+ "ff",
+ "rand_core 0.10.1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "primeorder"
+version = "0.14.0-rc.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d2793f22b9b6fd11ef3ac1d59bf003c2573593e4968702341605c2748fd90bf"
+dependencies = [
+ "elliptic-curve",
]
[[package]]
+name = "proc-macro-crate"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
+dependencies = [
+ "toml_edit",
+]
+
+[[package]]
name = "proc-macro-error-attr2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2502,7 +3394,7 @@
"proc-macro-error-attr2",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -2531,77 +3423,25 @@
[[package]]
name = "prost"
-version = "0.13.5"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
+checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1"
dependencies = [
"bytes",
- "prost-derive 0.13.5",
-]
-
-[[package]]
-name = "prost"
-version = "0.14.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
-dependencies = [
- "bytes",
- "prost-derive 0.14.3",
+ "prost-derive",
]
[[package]]
-name = "prost-build"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf"
-dependencies = [
- "heck",
- "itertools 0.14.0",
- "log",
- "multimap",
- "once_cell",
- "petgraph",
- "prettyplease",
- "prost 0.13.5",
- "prost-types",
- "regex",
- "syn",
- "tempfile",
-]
-
-[[package]]
name = "prost-derive"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
-dependencies = [
- "anyhow",
- "itertools 0.14.0",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "prost-derive"
-version = "0.14.3"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
+checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf"
dependencies = [
"anyhow",
"itertools 0.14.0",
"proc-macro2",
"quote",
- "syn",
-]
-
-[[package]]
-name = "prost-types"
-version = "0.13.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16"
-dependencies = [
- "prost 0.13.5",
+ "syn 2.0.117",
]
[[package]]
@@ -2617,7 +3457,7 @@
"quinn-udp",
"rustc-hash 2.1.2",
"rustls",
- "socket2 0.6.3",
+ "socket2",
"thiserror 2.0.18",
"tokio",
"tracing",
@@ -2654,7 +3494,7 @@
"cfg_aliases",
"libc",
"once_cell",
- "socket2 0.6.3",
+ "socket2",
"tracing",
"windows-sys 0.60.2",
]
@@ -2766,32 +3606,28 @@
]
[[package]]
-name = "rcgen"
-version = "0.13.2"
+name = "redox_syscall"
+version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
- "pem",
- "ring",
- "rustls-pki-types",
- "time",
- "yasna",
+ "bitflags",
]
[[package]]
name = "redox_syscall"
-version = "0.5.18"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+checksum = "5b44b894f2a6e36457d665d1e08c3866add6ed5e70050c1b4ba8a8ddedb02ce7"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
-version = "1.12.3"
+version = "1.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
+checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba"
dependencies = [
"aho-corasick",
"memchr",
@@ -2812,18 +3648,131 @@
[[package]]
name = "regex-syntax"
-version = "0.8.10"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
+
+[[package]]
+name = "remowt-client"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34d59c0ce311b4b3c094b0b196a1004aa438b9947c3eace2ca4d2a0ac08fac59"
+dependencies = [
+ "anyhow",
+ "bifrostlink",
+ "bifrostlink-ports",
+ "bytes",
+ "camino",
+ "futures",
+ "remowt-endpoints",
+ "remowt-link-shared",
+ "russh",
+ "russh-config",
+ "serde",
+ "serde_json",
+ "tempfile",
+ "tokio",
+ "tokio-util",
+ "tracing",
+ "uuid",
+]
+
+[[package]]
+name = "remowt-endpoints"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb203856cd5cff27504bd2023c59195b1f1ce1cf5d8ea836598993894eb1b9c0"
+dependencies = [
+ "anyhow",
+ "bifrostlink",
+ "bifrostlink-macros",
+ "camino",
+ "nix",
+ "serde",
+ "tempfile",
+ "thiserror 2.0.18",
+ "tokio",
+ "tracing",
+ "uuid",
+ "zbus",
+]
+
+[[package]]
+name = "remowt-fleet"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "bifrostlink",
+ "camino",
+ "nix-eval",
+ "remowt-client",
+ "remowt-endpoints",
+ "serde",
+ "thiserror 2.0.18",
+ "tokio",
+ "tracing",
+ "uuid",
+]
+
+[[package]]
+name = "remowt-link-shared"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98ebba5be028a2dfb7f1858bb0ff74037262753eaae4dc6e5d9ae241c4567668"
+dependencies = [
+ "bifrostlink",
+ "bytes",
+ "remowt-ui-prompt",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.18",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "remowt-plugin"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
+checksum = "ef73ef3eea5bb6152d01019b5062e51ef258a1ac1c7a6f8cdcdf6fe1eb192cdd"
+dependencies = [
+ "anyhow",
+ "bifrostlink",
+ "bifrostlink-ports",
+ "remowt-link-shared",
+ "serde_json",
+ "tokio",
+ "tracing",
+ "tracing-subscriber",
+]
[[package]]
-name = "repl-plugin-unstable"
+name = "remowt-plugin-fleet"
version = "0.1.0"
dependencies = [
- "fleet-base",
+ "anyhow",
+ "remowt-fleet",
+ "remowt-plugin",
]
[[package]]
+name = "remowt-ui-prompt"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf28ba68e6f8087657157695e9ab42b82a21130e77f6dffd27781062109325d"
+dependencies = [
+ "anyhow",
+ "bifrostlink",
+ "bifrostlink-macros",
+ "serde",
+ "serde_json",
+ "thiserror 2.0.18",
+ "tokio",
+ "tracing",
+ "zbus",
+]
+
+[[package]]
name = "reqwest"
version = "0.12.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2854,8 +3803,8 @@
"sync_wrapper",
"tokio",
"tokio-rustls",
- "tower 0.5.3",
- "tower-http 0.6.8",
+ "tower",
+ "tower-http",
"tower-service",
"url",
"wasm-bindgen",
@@ -2864,6 +3813,16 @@
]
[[package]]
+name = "rfc6979"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5236ce872cac07e0fb3969b0cbf468c7d2f37d432f1b627dcb7b8d34563fb0c3"
+dependencies = [
+ "hmac 0.13.0",
+ "subtle",
+]
+
+[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2878,45 +3837,155 @@
]
[[package]]
-name = "rmp"
-version = "0.8.15"
+name = "rsa"
+version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c"
+checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d"
dependencies = [
+ "const-oid 0.9.6",
+ "digest 0.10.7",
+ "num-bigint-dig",
+ "num-integer",
"num-traits",
+ "pkcs1 0.7.5",
+ "pkcs8 0.10.2",
+ "rand_core 0.6.4",
+ "signature 2.2.0",
+ "spki 0.7.3",
+ "subtle",
+ "zeroize",
]
[[package]]
-name = "rmp-serde"
-version = "1.3.1"
+name = "rsa"
+version = "0.10.0-rc.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155"
+checksum = "30b2aa4ba0d89f73d1e332df05be0eeab8840351c36ca5654341dfdb57bb3caf"
dependencies = [
- "rmp",
- "serde",
+ "const-oid 0.10.2",
+ "crypto-bigint",
+ "crypto-primes",
+ "digest 0.11.3",
+ "pkcs1 0.8.0-rc.4",
+ "pkcs8 0.11.0",
+ "rand_core 0.10.1",
+ "sha2 0.11.0",
+ "signature 3.0.0",
+ "spki 0.8.0",
+ "zeroize",
]
[[package]]
-name = "rsa"
-version = "0.9.10"
+name = "russh"
+version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d"
+checksum = "bbf893f64684e58da8a68d56a5e84d1cf0440226274c515770fe267707a7d0b0"
dependencies = [
- "const-oid",
- "digest",
- "num-bigint-dig",
- "num-integer",
- "num-traits",
- "pkcs1",
- "pkcs8",
- "rand_core 0.6.4",
- "signature",
- "spki",
+ "aes 0.9.1",
+ "bitflags",
+ "block-padding 0.4.2",
+ "byteorder",
+ "bytes",
+ "cbc 0.2.1",
+ "cipher 0.5.2",
+ "crypto-bigint",
+ "ctr 0.10.1",
+ "curve25519-dalek 5.0.0-rc.0",
+ "data-encoding",
+ "delegate",
+ "der 0.8.0",
+ "digest 0.11.3",
+ "ecdsa",
+ "ed25519-dalek 3.0.0-rc.0",
+ "elliptic-curve",
+ "enum_dispatch",
+ "flate2",
+ "futures",
+ "generic-array 1.4.3",
+ "getrandom 0.4.2",
+ "ghash 0.6.0",
+ "hex-literal",
+ "hmac 0.13.0",
+ "inout 0.2.2",
+ "internal-russh-num-bigint",
+ "keccak",
+ "log",
+ "md5",
+ "ml-kem",
+ "module-lattice",
+ "num-bigint",
+ "p256",
+ "p384",
+ "p521",
+ "pageant",
+ "pbkdf2 0.13.0",
+ "pkcs1 0.8.0-rc.4",
+ "pkcs5",
+ "pkcs8 0.11.0",
+ "polyval 0.7.1",
+ "rand 0.10.1",
+ "rand_core 0.10.1",
+ "ring",
+ "rsa 0.10.0-rc.18",
+ "russh-cryptovec",
+ "russh-util",
+ "salsa20 0.11.0",
+ "scrypt 0.12.0",
+ "sec1",
+ "sha1",
+ "sha2 0.11.0",
+ "sha3",
+ "signature 3.0.0",
+ "spki 0.8.0",
+ "ssh-encoding",
+ "ssh-key",
"subtle",
+ "thiserror 2.0.18",
+ "tokio",
+ "typenum",
+ "universal-hash 0.6.1",
"zeroize",
]
[[package]]
+name = "russh-config"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "993346101d4741a59c82bafc6b645c52ce3e7b0820f13e4b5d48cdb591e3d955"
+dependencies = [
+ "futures",
+ "globset",
+ "log",
+ "thiserror 2.0.18",
+ "tokio",
+ "whoami",
+]
+
+[[package]]
+name = "russh-cryptovec"
+version = "0.61.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "443f6bbcfacb34a1aab2b12b99bf08e0c63abdc5a0db261901365df9d57fff51"
+dependencies = [
+ "log",
+ "nix",
+ "ssh-encoding",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "russh-util"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "668424a5dde0bcb45b55ba7de8476b93831b4aa2fa6947e145f3b053e22c60b6"
+dependencies = [
+ "chrono",
+ "tokio",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+]
+
+[[package]]
name = "rust-embed"
version = "8.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2936,7 +4005,7 @@
"proc-macro2",
"quote",
"rust-embed-utils",
- "syn",
+ "syn 2.0.117",
"walkdir",
]
@@ -2946,7 +4015,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bcdef0be6fe7f6fa333b1073c949729274b05f123a0ad7efcb8efd878e5c3b1"
dependencies = [
- "sha2",
+ "sha2 0.10.9",
"walkdir",
]
@@ -2999,11 +4068,10 @@
[[package]]
name = "rustls"
-version = "0.23.38"
+version = "0.23.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21"
+checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
dependencies = [
- "log",
"once_cell",
"ring",
"rustls-pki-types",
@@ -3014,30 +4082,21 @@
[[package]]
name = "rustls-native-certs"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63"
+checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d"
dependencies = [
"openssl-probe",
"rustls-pki-types",
"schannel",
"security-framework",
-]
-
-[[package]]
-name = "rustls-pemfile"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
-dependencies = [
- "rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
-version = "1.14.0"
+version = "1.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
+checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
dependencies = [
"web-time",
"zeroize",
@@ -3072,7 +4131,17 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
dependencies = [
- "cipher",
+ "cipher 0.4.4",
+]
+
+[[package]]
+name = "salsa20"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f874456e72520ff1375a06c588eaf074b0f01f9e9e1aada45bd9b7954a6e42c"
+dependencies = [
+ "cfg-if",
+ "cipher 0.5.2",
]
[[package]]
@@ -3111,12 +4180,38 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
dependencies = [
- "pbkdf2",
- "salsa20",
- "sha2",
+ "pbkdf2 0.12.2",
+ "salsa20 0.10.2",
+ "sha2 0.10.9",
]
[[package]]
+name = "scrypt"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d87af57419b594aa23fa95f09f0e06d80d84ba01c26148c43844cad6ff4485f0"
+dependencies = [
+ "cfg-if",
+ "pbkdf2 0.13.0",
+ "salsa20 0.11.0",
+ "sha2 0.11.0",
+]
+
+[[package]]
+name = "sec1"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d"
+dependencies = [
+ "base16ct",
+ "ctutils",
+ "der 0.8.0",
+ "hybrid-array",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "secrecy"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3177,28 +4272,9 @@
dependencies = [
"serde_core",
"serde_derive",
-]
-
-[[package]]
-name = "serde-transcode"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "590c0e25c2a5bb6e85bf5c1bce768ceb86b316e7a01bdf07d2cb4ec2271990e2"
-dependencies = [
- "serde",
]
[[package]]
-name = "serde_bytes"
-version = "0.11.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
-dependencies = [
- "serde",
- "serde_core",
-]
-
-[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3215,14 +4291,14 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
name = "serde_json"
-version = "1.0.149"
+version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
dependencies = [
"itoa",
"memchr",
@@ -3232,6 +4308,17 @@
]
[[package]]
+name = "serde_repr"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3244,6 +4331,27 @@
]
[[package]]
+name = "serdect"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e"
+dependencies = [
+ "base16ct",
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.0",
+ "digest 0.11.3",
+]
+
+[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3251,10 +4359,31 @@
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
- "digest",
+ "digest 0.10.7",
]
[[package]]
+name = "sha2"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.0",
+ "digest 0.11.3",
+]
+
+[[package]]
+name = "sha3"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1"
+dependencies = [
+ "digest 0.11.3",
+ "keccak",
+]
+
+[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3264,16 +4393,16 @@
]
[[package]]
-name = "shell-escape"
-version = "0.1.5"
+name = "shlex"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "shlex"
-version = "1.3.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]]
name = "signal-hook-registry"
@@ -3291,11 +4420,21 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
- "digest",
+ "digest 0.10.7",
"rand_core 0.6.4",
]
[[package]]
+name = "signature"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5"
+dependencies = [
+ "digest 0.11.3",
+ "rand_core 0.10.1",
+]
+
+[[package]]
name = "simd-adler32"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3309,25 +4448,15 @@
[[package]]
name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "socket2"
-version = "0.5.10"
+version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
-dependencies = [
- "libc",
- "windows-sys 0.52.0",
-]
+checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
[[package]]
name = "socket2"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
+checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
dependencies = [
"libc",
"windows-sys 0.61.2",
@@ -3346,10 +4475,81 @@
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
- "der",
+ "der 0.7.10",
+]
+
+[[package]]
+name = "spki"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f"
+dependencies = [
+ "base64ct",
+ "der 0.8.0",
+]
+
+[[package]]
+name = "ssh-cipher"
+version = "0.3.0-rc.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10db6f219196a8528f9ec904d9d45cdad692d65b0e57e72be4dedd1c5fddce36"
+dependencies = [
+ "aead 0.6.0",
+ "aes 0.9.1",
+ "aes-gcm 0.11.0-rc.4",
+ "cbc 0.2.1",
+ "chacha20 0.10.0",
+ "cipher 0.5.2",
+ "ctr 0.10.1",
+ "ctutils",
+ "des",
+ "poly1305 0.9.0",
+ "ssh-encoding",
+ "zeroize",
]
[[package]]
+name = "ssh-encoding"
+version = "0.3.0-rc.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7abf34aa716da5d5b4c496936d042ea282ab392092cd68a72ef6a8863ff8c96a"
+dependencies = [
+ "base64ct",
+ "bytes",
+ "crypto-bigint",
+ "ctutils",
+ "digest 0.11.3",
+ "pem-rfc7468",
+ "zeroize",
+]
+
+[[package]]
+name = "ssh-key"
+version = "0.7.0-rc.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45735ce3dea95690e4a9e414c4cfde7f79835063c3dcd35881df85a84118e74b"
+dependencies = [
+ "argon2",
+ "bcrypt-pbkdf 0.11.0",
+ "ctutils",
+ "ed25519-dalek 3.0.0-rc.0",
+ "hex",
+ "hmac 0.13.0",
+ "p256",
+ "p384",
+ "p521",
+ "rand_core 0.10.1",
+ "rsa 0.10.0-rc.18",
+ "sec1",
+ "sha1",
+ "sha2 0.11.0",
+ "signature 3.0.0",
+ "ssh-cipher",
+ "ssh-encoding",
+ "zeroize",
+]
+
+[[package]]
name = "stable_deref_trait"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3369,6 +4569,17 @@
[[package]]
name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
@@ -3395,7 +4606,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -3419,7 +4630,7 @@
"proc-macro-error2",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -3452,24 +4663,13 @@
dependencies = [
"rustix 1.1.4",
"windows-sys 0.61.2",
-]
-
-[[package]]
-name = "terraform-provider-fleet"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "async-trait",
- "serde",
- "tf-provider",
- "tokio",
]
[[package]]
name = "test-log"
-version = "0.2.20"
+version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f46bf474f0a4afebf92f076d54fd5e63423d9438b8c278a3d2ccb0f47f7cdb3"
+checksum = "9b9c218384242b5c89b68303ab6f6fc53a312d923f0c14dc6bb860c6aeee40f1"
dependencies = [
"env_logger",
"test-log-macros",
@@ -3478,22 +4678,22 @@
[[package]]
name = "test-log-core"
-version = "0.2.20"
+version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d4d41320b48bc4a211a9021678fcc0c99569b594ea31c93735b8e517102b4c"
+checksum = "c26ef8b00e4d382e59f6a8ddb3cd790b3a5bb29f21a358a9a69ea2f29f13f27b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
name = "test-log-macros"
-version = "0.2.20"
+version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9beb9249a81e430dffd42400a49019bcf548444f1968ff23080a625de0d4d320"
+checksum = "944ad38adcbb71eaa682c56bceeb079e4ca82b4b3edc2a0fde5cb297b77dac8d"
dependencies = [
- "syn",
+ "syn 2.0.117",
"test-log-core",
]
@@ -3504,34 +4704,6 @@
checksum = "0f8daae29995a24f65619e19d8d31dea5b389f3d853d8bf297bbf607cd0014cc"
dependencies = [
"unicode-width",
-]
-
-[[package]]
-name = "tf-provider"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d80ea2e5f9f54717952d199888aab7e607dc99275ec5221f1259ce7a5f55f5a6"
-dependencies = [
- "anyhow",
- "async-stream",
- "async-trait",
- "base64 0.22.1",
- "futures",
- "prost 0.13.5",
- "rcgen",
- "rmp-serde",
- "serde",
- "serde_bytes",
- "serde_json",
- "time",
- "tokio",
- "tokio-stream",
- "tokio-util",
- "tonic 0.12.3",
- "tonic-build",
- "tower-http 0.5.2",
- "tracing",
- "tracing-subscriber",
]
[[package]]
@@ -3560,7 +4732,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -3571,7 +4743,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -3585,9 +4757,9 @@
[[package]]
name = "time"
-version = "0.3.47"
+version = "0.3.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
+checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469"
dependencies = [
"deranged",
"num-conv",
@@ -3599,15 +4771,15 @@
[[package]]
name = "time-core"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
+checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]]
name = "time-macros"
-version = "0.2.27"
+version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
+checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d"
dependencies = [
"num-conv",
"time-core",
@@ -3641,16 +4813,16 @@
[[package]]
name = "tokio"
-version = "1.52.1"
+version = "1.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6"
+checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
dependencies = [
"bytes",
"libc",
"mio",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.6.3",
+ "socket2",
"tokio-macros",
"windows-sys 0.61.2",
]
@@ -3663,7 +4835,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -3685,7 +4857,6 @@
"futures-core",
"pin-project-lite",
"tokio",
- "tokio-util",
]
[[package]]
@@ -3712,24 +4883,23 @@
[[package]]
name = "toml_datetime"
-version = "0.7.5+spec-1.1.0"
+version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
+checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_edit"
-version = "0.23.10+spec-1.0.0"
+version = "0.25.12+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269"
+checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7"
dependencies = [
- "indexmap 2.14.0",
+ "indexmap",
"toml_datetime",
"toml_parser",
- "toml_writer",
- "winnow 0.7.15",
+ "winnow",
]
[[package]]
@@ -3738,52 +4908,14 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
- "winnow 1.0.2",
-]
-
-[[package]]
-name = "toml_writer"
-version = "1.1.1+spec-1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
-
-[[package]]
-name = "tonic"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52"
-dependencies = [
- "async-stream",
- "async-trait",
- "axum",
- "base64 0.22.1",
- "bytes",
- "h2",
- "http",
- "http-body",
- "http-body-util",
- "hyper",
- "hyper-timeout",
- "hyper-util",
- "percent-encoding",
- "pin-project",
- "prost 0.13.5",
- "rustls-pemfile",
- "socket2 0.5.10",
- "tokio",
- "tokio-rustls",
- "tokio-stream",
- "tower 0.4.13",
- "tower-layer",
- "tower-service",
- "tracing",
+ "winnow",
]
[[package]]
name = "tonic"
-version = "0.14.5"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec"
+checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef"
dependencies = [
"async-trait",
"base64 0.22.1",
@@ -3800,55 +4932,21 @@
"sync_wrapper",
"tokio",
"tokio-stream",
- "tower 0.5.3",
+ "tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
-name = "tonic-build"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11"
-dependencies = [
- "prettyplease",
- "proc-macro2",
- "prost-build",
- "prost-types",
- "quote",
- "syn",
-]
-
-[[package]]
name = "tonic-prost"
-version = "0.14.5"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309"
+checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0"
dependencies = [
"bytes",
- "prost 0.14.3",
- "tonic 0.14.5",
-]
-
-[[package]]
-name = "tower"
-version = "0.4.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
-dependencies = [
- "futures-core",
- "futures-util",
- "indexmap 1.9.3",
- "pin-project",
- "pin-project-lite",
- "rand 0.8.6",
- "slab",
- "tokio",
- "tokio-util",
- "tower-layer",
- "tower-service",
- "tracing",
+ "prost",
+ "tonic",
]
[[package]]
@@ -3859,7 +4957,7 @@
dependencies = [
"futures-core",
"futures-util",
- "indexmap 2.14.0",
+ "indexmap",
"pin-project-lite",
"slab",
"sync_wrapper",
@@ -3872,37 +4970,20 @@
[[package]]
name = "tower-http"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
-dependencies = [
- "bitflags",
- "bytes",
- "http",
- "http-body",
- "http-body-util",
- "pin-project-lite",
- "tower-layer",
- "tower-service",
- "tracing",
-]
-
-[[package]]
-name = "tower-http"
-version = "0.6.8"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
+checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
dependencies = [
"bitflags",
"bytes",
"futures-util",
"http",
"http-body",
- "iri-string",
"pin-project-lite",
- "tower 0.5.3",
+ "tower",
"tower-layer",
"tower-service",
+ "url",
]
[[package]]
@@ -3936,7 +5017,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -3989,16 +5070,6 @@
]
[[package]]
-name = "tracing-serde"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
-dependencies = [
- "serde",
- "tracing-core",
-]
-
-[[package]]
name = "tracing-subscriber"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4008,15 +5079,12 @@
"nu-ansi-term",
"once_cell",
"regex-automata",
- "serde",
- "serde_json",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
- "tracing-serde",
]
[[package]]
@@ -4036,11 +5104,22 @@
[[package]]
name = "typenum"
-version = "1.20.0"
+version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
+checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
[[package]]
+name = "uds_windows"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
+dependencies = [
+ "memoffset",
+ "tempfile",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
name = "unarray"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4107,11 +5186,21 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
- "crypto-common",
+ "crypto-common 0.1.7",
"subtle",
]
[[package]]
+name = "universal-hash"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96"
+dependencies = [
+ "crypto-common 0.2.2",
+ "ctutils",
+]
+
+[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4142,6 +5231,18 @@
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
+name = "uuid"
+version = "1.23.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7"
+dependencies = [
+ "getrandom 0.4.2",
+ "js-sys",
+ "serde_core",
+ "wasm-bindgen",
+]
+
+[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4204,9 +5305,9 @@
[[package]]
name = "wasip2"
-version = "1.0.3+wasi-0.2.9"
+version = "1.0.4+wasi-0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
+checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
dependencies = [
"wit-bindgen 0.57.1",
]
@@ -4221,10 +5322,16 @@
]
[[package]]
+name = "wasite"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
+
+[[package]]
name = "wasm-bindgen"
-version = "0.2.118"
+version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89"
+checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
dependencies = [
"cfg-if",
"once_cell",
@@ -4235,9 +5342,9 @@
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.68"
+version = "0.4.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8"
+checksum = "503b14d284f2c8dac03b819967e155ea753f573586193b2b2c95990cb5d69280"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -4245,9 +5352,9 @@
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.118"
+version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed"
+checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -4255,22 +5362,22 @@
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.118"
+version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904"
+checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.118"
+version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129"
+checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
dependencies = [
"unicode-ident",
]
@@ -4292,7 +5399,7 @@
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
dependencies = [
"anyhow",
- "indexmap 2.14.0",
+ "indexmap",
"wasm-encoder",
"wasmparser",
]
@@ -4305,15 +5412,15 @@
dependencies = [
"bitflags",
"hashbrown 0.15.5",
- "indexmap 2.14.0",
+ "indexmap",
"semver",
]
[[package]]
name = "web-sys"
-version = "0.3.95"
+version = "0.3.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d"
+checksum = "a6430a72df5eb332242960fe84b3002a241163998241eb596d4f739b9757061d"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -4342,6 +5449,17 @@
]
[[package]]
+name = "whoami"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"
+dependencies = [
+ "libredox",
+ "wasite",
+ "web-sys",
+]
+
+[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4351,6 +5469,27 @@
]
[[package]]
+name = "windows"
+version = "0.62.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
+dependencies = [
+ "windows-collections",
+ "windows-core",
+ "windows-future",
+ "windows-numerics",
+]
+
+[[package]]
+name = "windows-collections"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
+dependencies = [
+ "windows-core",
+]
+
+[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4364,6 +5503,17 @@
]
[[package]]
+name = "windows-future"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
+dependencies = [
+ "windows-core",
+ "windows-link",
+ "windows-threading",
+]
+
+[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4371,7 +5521,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -4382,7 +5532,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -4392,6 +5542,16 @@
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
+name = "windows-numerics"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
+dependencies = [
+ "windows-core",
+ "windows-link",
+]
+
+[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4479,6 +5639,15 @@
]
[[package]]
+name = "windows-threading"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4576,20 +5745,14 @@
[[package]]
name = "winnow"
-version = "0.7.15"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
dependencies = [
"memchr",
]
[[package]]
-name = "winnow"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0"
-
-[[package]]
name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4623,9 +5786,9 @@
dependencies = [
"anyhow",
"heck",
- "indexmap 2.14.0",
+ "indexmap",
"prettyplease",
- "syn",
+ "syn 2.0.117",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
@@ -4641,7 +5804,7 @@
"prettyplease",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
"wit-bindgen-core",
"wit-bindgen-rust",
]
@@ -4654,7 +5817,7 @@
dependencies = [
"anyhow",
"bitflags",
- "indexmap 2.14.0",
+ "indexmap",
"log",
"serde",
"serde_derive",
@@ -4673,7 +5836,7 @@
dependencies = [
"anyhow",
"id-arena",
- "indexmap 2.14.0",
+ "indexmap",
"log",
"semver",
"serde",
@@ -4701,26 +5864,17 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
- "curve25519-dalek",
+ "curve25519-dalek 4.1.3",
"rand_core 0.6.4",
"serde",
"zeroize",
]
[[package]]
-name = "yasna"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
-dependencies = [
- "time",
-]
-
-[[package]]
name = "yoke"
-version = "0.8.2"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca"
+checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5"
dependencies = [
"stable_deref_trait",
"yoke-derive",
@@ -4735,35 +5889,96 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
"synstructure",
]
[[package]]
+name = "zbus"
+version = "5.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eee682d202a77e4a9f3b2c2bdf48a7b28af5c08c34ddf66f98c93e5e39464285"
+dependencies = [
+ "async-broadcast",
+ "async-executor",
+ "async-io",
+ "async-lock",
+ "async-process",
+ "async-recursion",
+ "async-task",
+ "async-trait",
+ "blocking",
+ "enumflags2",
+ "event-listener",
+ "futures-core",
+ "futures-lite",
+ "hex",
+ "libc",
+ "ordered-stream",
+ "rustix 1.1.4",
+ "serde",
+ "serde_repr",
+ "tracing",
+ "uds_windows",
+ "uuid",
+ "windows-sys 0.61.2",
+ "winnow",
+ "zbus_macros",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus_macros"
+version = "5.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adf1bd45a81a103745b1757754762a26e8cd01e4532e4d6c8ec431624b80d1d6"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+ "zbus_names",
+ "zvariant",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zbus_names"
+version = "4.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d"
+dependencies = [
+ "serde",
+ "winnow",
+ "zvariant",
+]
+
+[[package]]
name = "zerocopy"
-version = "0.8.48"
+version = "0.8.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
+checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.8.48"
+version = "0.8.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
+checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
name = "zerofrom"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
+checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
dependencies = [
"zerofrom-derive",
]
@@ -4776,28 +5991,28 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
"synstructure",
]
[[package]]
name = "zeroize"
-version = "1.8.2"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
+checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
-version = "1.4.3"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
+checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -4831,7 +6046,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.117",
]
[[package]]
@@ -4839,3 +6054,43 @@
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+
+[[package]]
+name = "zvariant"
+version = "5.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a192a0bde63360d77a7523c833d4b4ce6070a927e2c53246e4c540b1a3e27be0"
+dependencies = [
+ "endi",
+ "enumflags2",
+ "serde",
+ "winnow",
+ "zvariant_derive",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zvariant_derive"
+version = "5.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bc6cde9c01c511074be97f7ccb6c19d0da89e3f8662e812e999dcfd4638737"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zvariant_utils"
+version = "3.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e8535915cfa75547e559d8c68e8139909a4aeee076831e4ef7fc59d8172c4d6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde",
+ "syn 2.0.117",
+ "winnow",
+]
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,22 +6,28 @@
package.rust-version = "1.89.0"
[workspace.dependencies]
-better-command = { path = "./crates/better-command" }
fleet-base = { path = "./crates/fleet-base" }
fleet-shared = { path = "./crates/fleet-shared" }
nix-eval = { path = "./crates/nix-eval" }
nixlike = { path = "./crates/nixlike" }
opentelemetry-exporter-env = { path = "./crates/opentelemetry-exporter-env" }
+remowt-fleet = { path = "./crates/remowt-fleet" }
-abort-on-drop = "0.2"
+remowt-client = "0.1.3"
+remowt-endpoints = "0.1.3"
+remowt-link-shared = "0.1.3"
+remowt-plugin = "0.1.3"
+remowt-ui-prompt = "0.1.3"
+
+bifrostlink = "0.2.3"
+
+uuid = { version = "1", features = ["v4"] }
+
age = { version = "0.11", features = ["plugin", "ssh"] }
-age-core = "0.11"
anyhow = "1.0"
-async-trait = "0.1.88"
-axum = { version = "0.8.7", features = ["http2", "macros", "ws"] }
-axum-extra = { version = "0.12.2", features = ["typed-header"] }
base64 = "0.22.1"
bindgen = "0.72.0"
+camino = "1.2.2"
chrono = { version = "0.4.41", features = ["serde"] }
clap = { version = "4.5", features = ["derive", "env", "unicode", "wrap_help"] }
clap_complete = "4.5"
@@ -29,19 +35,16 @@
cxx-build = "1.0.168"
ed25519-dalek = "2.1"
futures = "0.3.31"
-futures-util = { version = "0.3.31", features = ["sink"] }
hex = "0.4.3"
hmac = "0.12"
hostname = "0.4.1"
human-repr = "1.1"
-hyper = "1.8.1"
indicatif = "0.18"
indoc = "2.0.6"
itertools = "0.14.0"
linked-hash-map = "0.5.6"
nix = { version = "0.31.2", features = ["fs", "user"] }
nom = "8.0.0"
-openssh = "0.11.5"
opentelemetry = "0.31.0"
opentelemetry-appender-tracing = "0.31.1"
opentelemetry-otlp = { version = "0.31.0", features = ["grpc-tonic", "gzip-tonic", "http-json", "reqwest-rustls"] }
@@ -50,21 +53,16 @@
peg = "0.8.5"
pkg-config = "0.3.30"
rand = "0.10.0"
-regex = "1.11"
serde = { version = "1.0", features = ["derive"] }
-serde-transcode = "1.1.1"
serde_json = "1.0"
sha2 = "0.10"
shlex = "1.3"
tabled = "0.20.0"
tempfile = "3.20"
test-log = { version = "0.2.19", features = ["trace"] }
-tf-provider = "0.2.2"
thiserror = "2.0.12"
time = "0.3.41"
tokio = { version = "1.45.1", features = ["fs", "macros", "rt", "rt-multi-thread", "sync", "time"] }
-tokio-util = "0.7.17"
-toml_edit = "0.23.10"
tracing = "0.1"
tracing-indicatif = "0.3.13"
tracing-opentelemetry = "0.32.1"
cmds/fleet/Cargo.tomldiffbeforeafterboth--- a/cmds/fleet/Cargo.toml
+++ b/cmds/fleet/Cargo.toml
@@ -8,15 +8,13 @@
default-run = "fleet"
[dependencies]
-age = { workspace = true, features = ["armor"] }
anyhow.workspace = true
-better-command.workspace = true
+camino.workspace = true
clap.workspace = true
clap_complete.workspace = true
fleet-base.workspace = true
-fleet-shared.workspace = true
nix-eval.workspace = true
-nixlike.workspace = true
+remowt-fleet.workspace = true
serde.workspace = true
serde_json.workspace = true
tempfile.workspace = true
@@ -24,30 +22,17 @@
tracing.workspace = true
tracing-subscriber.workspace = true
-abort-on-drop.workspace = true
-age-core.workspace = true
-async-trait.workspace = true
-base64.workspace = true
-chrono.workspace = true
futures.workspace = true
-hostname.workspace = true
itertools.workspace = true
-openssh.workspace = true
-peg.workspace = true
-regex.workspace = true
shlex.workspace = true
tabled.workspace = true
-time = { workspace = true, features = ["serde"] }
-tokio-util = { workspace = true, features = ["codec"] }
human-repr = { workspace = true, optional = true }
indicatif = { workspace = true, optional = true }
-nom.workspace = true
opentelemetry.workspace = true
opentelemetry-appender-tracing.workspace = true
opentelemetry-exporter-env.workspace = true
opentelemetry_sdk.workspace = true
-thiserror.workspace = true
tracing-indicatif = { workspace = true, optional = true }
tracing-opentelemetry.workspace = true
@@ -58,6 +43,5 @@
"dep:tracing-indicatif",
"dep:indicatif",
"dep:human-repr",
- "better-command/indicatif",
"nix-eval/indicatif",
]
cmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/build_systems.rs
+++ b/cmds/fleet/src/cmds/build_systems.rs
@@ -1,6 +1,7 @@
use std::{env::current_dir, os::unix::fs::symlink, path::PathBuf};
use anyhow::Result;
+use camino::Utf8PathBuf;
use clap::Parser;
use fleet_base::{
deploy::{DeployAction, deploy_task, upload_task},
@@ -29,7 +30,7 @@
build_attr: String,
}
-async fn build_task(config: Config, hostname: String, build_attr: &str) -> Result<PathBuf> {
+async fn build_task(config: Config, hostname: String, build_attr: &str) -> Result<Utf8PathBuf> {
info!("building");
let host = config.host(&hostname)?;
// let action = Action::from(self.subcommand.clone());
@@ -42,17 +43,20 @@
// We already have system profiles for backups.
if !host.local {
info!("adding gc root");
- let mut cmd = config.local_host().cmd("nix").await?;
- cmd.arg("build")
- .comparg(
- "--profile",
- format!(
- "/nix/var/nix/profiles/{}-{hostname}",
- config.data.gc_root_prefix
- ),
- )
- .arg(&out_output);
- cmd.sudo().run_nix().await?;
+ let local = config.local_host();
+ let plugin_id = local.ensure_nix_plugin().await?;
+ let nix = local
+ .remowt()
+ .await?
+ .plugin_endpoints::<remowt_fleet::NixClient<_>>(plugin_id);
+ let profile = format!(
+ "/nix/var/nix/profiles/{}-{hostname}",
+ config.data.gc_root_prefix
+ );
+ nix.switch_profile(profile, out_output.clone())
+ .await
+ .map_err(|e| anyhow::anyhow!("{e:?}"))?
+ .map_err(|e| anyhow::anyhow!("{e}"))?;
}
Ok(out_output)
cmds/fleet/src/cmds/tf.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/tf.rs
+++ b/cmds/fleet/src/cmds/tf.rs
@@ -1,6 +1,7 @@
-use std::{collections::BTreeMap, ffi::OsString, path::PathBuf};
+use std::{collections::BTreeMap, ffi::OsString};
use anyhow::{Context, Result};
+use camino::Utf8PathBuf;
use clap::Parser;
use fleet_base::host::Config;
use nix_eval::nix_go;
@@ -40,7 +41,7 @@
let system = &config.local_system;
let config = &config.flake_outputs;
let data = nix_go!(config.tf({ system }));
- let data: PathBuf = spawn_blocking(move || data.build("out"))
+ let data: Utf8PathBuf = spawn_blocking(move || data.build("out"))
.await
.expect("tf.json derivation should not fail")?;
let data = fs::read(&data).await?;
cmds/fleet/src/main.rsdiffbeforeafterboth--- a/cmds/fleet/src/main.rs
+++ b/cmds/fleet/src/main.rs
@@ -4,9 +4,10 @@
// pub(crate) mod command;
pub(crate) mod extra_args;
-use std::{env, ffi::OsString, process::ExitCode, sync::Arc};
+use std::{process::ExitCode, sync::Arc};
-use anyhow::{Result, bail};
+use anyhow::{Context as _, Result, bail};
+use camino::Utf8PathBuf;
use clap::{CommandFactory, Parser};
use cmds::{
build_systems::{BuildSystems, Deploy},
@@ -23,7 +24,8 @@
#[cfg(feature = "indicatif")]
use indicatif::{ProgressState, ProgressStyle};
use nix_eval::{
- gc_register_my_thread, gc_unregister_my_thread, init_libraries, init_tokio_for_nix,
+ add_file_to_store, gc_register_my_thread, gc_unregister_my_thread, init_libraries,
+ init_tokio_for_nix,
};
use opentelemetry::trace::TracerProvider;
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
@@ -48,24 +50,21 @@
}
let tasks = FuturesUnordered::new();
for entry in std::fs::read_dir(&prefetch_dir)? {
- tasks.push(async {
- let entry = entry?;
- if !entry.metadata()?.is_file() {
- bail!("only files should exist in prefetch directory");
- }
- let span = info_span!(
- "prefetching",
- name = entry.file_name().to_string_lossy().as_ref()
- );
- let mut path = OsString::new();
- path.push("file://");
- path.push(entry.path());
-
- let mut status = config.local_host().cmd("nix").await?;
- status.args(&config.nix_args);
- status.arg("store").arg("prefetch-file").arg(path);
- status.run_nix_string().instrument(span).await?;
- Ok(())
+ let entry = entry?;
+ if !entry.metadata()?.is_file() {
+ bail!("only files should exist in prefetch directory");
+ }
+ let name = entry.file_name().to_string_lossy().into_owned();
+ let path =
+ Utf8PathBuf::try_from(entry.path()).context("prefetch path should be utf8")?;
+ let span = info_span!("prefetching", name = %name);
+ tasks.push(async move {
+ let added = tokio::task::spawn_blocking(move || add_file_to_store(&name, &path))
+ .instrument(span.clone())
+ .await??;
+ let _g = span.enter();
+ info!("{} -> {}", added.hash, added.store_path);
+ anyhow::Ok(())
});
}
tasks.try_collect::<Vec<()>>().await?;
@@ -179,9 +178,7 @@
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
let reg = tracing_subscriber::registry().with({
- let sub = tracing_subscriber::fmt::layer()
- .without_time()
- .with_target(false);
+ let sub = tracing_subscriber::fmt::layer().without_time();
#[cfg(feature = "indicatif")]
let sub = sub.with_writer(indicatif_layer.get_stderr_writer());
sub.with_filter(filter) // .without,
@@ -262,14 +259,10 @@
}
async fn main_real(opts: RootOpts) -> Result<()> {
- let nix_args = std::env::var_os("NIX_ARGS")
- .map(|a| extra_args::parse_os(&a))
- .transpose()?
- .unwrap_or_default();
- let config = opts.fleet_opts.build(
- nix_args,
- matches!(opts.command, Opts::Deploy(_) | Opts::BuildSystems(_)),
- )?;
+ let config = opts.fleet_opts.build(matches!(
+ opts.command,
+ Opts::Deploy(_) | Opts::BuildSystems(_)
+ ))?;
match run_command(&config, opts.fleet_opts, opts.command).await {
Ok(()) => {
cmds/install-secrets/src/main.rsdiffbeforeafterboth--- a/cmds/install-secrets/src/main.rs
+++ b/cmds/install-secrets/src/main.rs
@@ -227,7 +227,6 @@
.from_env_lossy(),
)
.without_time()
- .with_target(false)
.init();
let opts = Opts::parse();
cmds/nix-plugin-fleet/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/cmds/nix-plugin-fleet/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "nix-plugin-fleet"
+version.workspace = true
+edition.workspace = true
+rust-version.workspace = true
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+fleet-base.workspace = true
cmds/nix-plugin-fleet/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/nix-plugin-fleet/src/lib.rs
@@ -0,0 +1,7 @@
+use fleet_base::primops::init_primops;
+
+/// SAFETY: expected plugin dynamic library entry point
+#[unsafe(no_mangle)]
+fn nix_plugin_entry() {
+ init_primops();
+}
cmds/remowt-plugin-fleet/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/cmds/remowt-plugin-fleet/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "remowt-plugin-fleet"
+description = "Remowt plugin exposing fleet's Nix endpoint to a running agent"
+version.workspace = true
+edition = "2021"
+
+[dependencies]
+remowt-fleet.workspace = true
+remowt-plugin.workspace = true
+
+anyhow.workspace = true
cmds/remowt-plugin-fleet/src/main.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/remowt-plugin-fleet/src/main.rs
@@ -0,0 +1,8 @@
+use remowt_fleet::{Nix, init_libraries};
+
+fn main() -> anyhow::Result<()> {
+ remowt_plugin::run(|rpc| {
+ init_libraries();
+ Nix.register_endpoints(rpc);
+ })
+}
cmds/repl-plugin-unstable/Cargo.tomldiffbeforeafterboth--- a/cmds/repl-plugin-unstable/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "repl-plugin-unstable"
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
-
-[lib]
-crate-type = ["cdylib"]
-
-[dependencies]
-fleet-base.workspace = true
cmds/repl-plugin-unstable/src/lib.rsdiffbeforeafterboth--- a/cmds/repl-plugin-unstable/src/lib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-use fleet_base::primops::init_primops;
-
-/// SAFETY: expected plugin dynamic library entry point
-#[unsafe(no_mangle)]
-fn nix_plugin_entry() {
- init_primops();
-}
cmds/terraform-provider-fleet/Cargo.tomldiffbeforeafterboth--- a/cmds/terraform-provider-fleet/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "terraform-provider-fleet"
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
-
-[dependencies]
-anyhow.workspace = true
-serde = { workspace = true, features = ["derive"] }
-tokio.workspace = true
-
-async-trait.workspace = true
-tf-provider.workspace = true
cmds/terraform-provider-fleet/src/main.rsdiffbeforeafterboth--- a/cmds/terraform-provider-fleet/src/main.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
- panic!(
- "this is a stub, real provider is in development, I just don't want to keep it in different branch."
- )
-}
crates/better-command/Cargo.tomldiffbeforeafterboth--- a/crates/better-command/Cargo.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[package]
-name = "better-command"
-version.workspace = true
-edition.workspace = true
-rust-version.workspace = true
-
-[dependencies]
-regex.workspace = true
-serde.workspace = true
-serde_json.workspace = true
-tracing.workspace = true
-
-tracing-indicatif = { workspace = true, optional = true }
-
-[features]
-indicatif = ["tracing-indicatif"]
crates/better-command/src/handler.rsdiffbeforeafterboth--- a/crates/better-command/src/handler.rs
+++ /dev/null
@@ -1,335 +0,0 @@
-//! Collection of handlers, which transform program-specific stdout format to tracing
-
-use std::{
- collections::HashMap,
- sync::{Arc, LazyLock, Mutex},
-};
-
-use regex::Regex;
-use serde::Deserialize;
-use tracing::{Span, info, info_span, warn};
-#[cfg(feature = "indicatif")]
-use tracing_indicatif::span_ext::IndicatifSpanExt as _;
-
-pub trait Handler: Send {
- fn handle_line(&mut self, e: &str);
-}
-
-/// Handler wrapper, which can be cloned.
-pub struct ClonableHandler<H>(Arc<Mutex<H>>);
-impl<H> Clone for ClonableHandler<H> {
- fn clone(&self) -> Self {
- Self(self.0.clone())
- }
-}
-impl<H> ClonableHandler<H> {
- pub fn new(inner: H) -> Self {
- Self(Arc::new(Mutex::new(inner)))
- }
-}
-impl<H: Handler> Handler for ClonableHandler<H> {
- fn handle_line(&mut self, e: &str) {
- self.0.lock().unwrap().handle_line(e)
- }
-}
-
-/// Converts command output to tracing lines
-pub struct PlainHandler;
-impl Handler for PlainHandler {
- fn handle_line(&mut self, e: &str) {
- info!(target: "log", "{e}");
- }
-}
-
-/// Ignores output
-pub struct NoopHandler;
-impl Handler for NoopHandler {
- fn handle_line(&mut self, _e: &str) {}
-}
-
-/// Transform nix internal-json logs to tracing spans.
-#[derive(Default)]
-pub struct NixHandler {
- spans: HashMap<u64, Span>,
-}
-#[derive(Deserialize, Debug)]
-#[serde(untagged)]
-enum LogField {
- String(String),
- Num(u64),
-}
-
-/// Nix internal-json log line type
-#[derive(Deserialize, Debug)]
-#[serde(rename_all = "camelCase", tag = "action")]
-#[allow(dead_code)]
-enum NixLog {
- Msg {
- level: u32,
- msg: String,
- raw_msg: Option<String>,
- },
- Start {
- id: u64,
- level: u32,
- #[serde(default)]
- fields: Vec<LogField>,
- text: String,
- #[serde(rename = "type")]
- typ: u32,
- },
- Stop {
- id: u64,
- },
- Result {
- id: u64,
- #[serde(rename = "type")]
- typ: u32,
- #[serde(default)]
- fields: Vec<LogField>,
- },
-}
-fn process_message(m: &str) -> String {
- // Supposed to remove formatting characters except colors, as some programs try to reset cursor position etc.
- static OSC_CLEANER: LazyLock<Regex> =
- LazyLock::new(|| Regex::new(r"\x1B\]([^\x07\x1C]*[\x07\x1C])?|\r").unwrap());
- static DETABBER: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\t").unwrap());
- let m = OSC_CLEANER.replace_all(m, "");
- // Indicatif can't format tabs. This is not the correct tab formatting, as correct one should be aligned,
- // and not just be replaced with the constant number of spaces, but it's ok for now, as statuses are single-line.
- DETABBER.replace_all(m.as_ref(), " ").to_string()
-}
-impl Handler for NixHandler {
- fn handle_line(&mut self, e: &str) {
- if let Some(e) = e.strip_prefix("@nix ") {
- let log: NixLog = match serde_json::from_str(e) {
- Ok(l) => l,
- Err(err) => {
- warn!("failed to parse nix log line {:?}: {}", e, err);
- return;
- }
- };
- match log {
- NixLog::Msg { msg, raw_msg, .. } => {
- #[allow(clippy::nonminimal_bool)]
- if !(msg.starts_with("\u{1b}[35;1mwarning:\u{1b}[0m Git tree '")
- && msg.ends_with("' is dirty"))
- && !msg.starts_with(
- "\u{1b}[35;1mwarning:\u{1b}[0m not writing modified lock file of flake",
- ) && 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"
- {
- if let Some(raw_msg) = raw_msg {
- if !msg.is_empty() {
- info!(target: "nix", "{}\n{}", raw_msg.trim_end(), msg.trim_end())
- } else {
- info!(target: "nix", "{}", raw_msg.trim_end())
- }
- } else {
- info!(target: "nix", "{}", msg.trim_end())
- }
- }
- }
- NixLog::Start {
- ref fields,
- typ,
- id,
- ..
- } if typ == 105 && !fields.is_empty() => {
- if let [LogField::String(drv), ..] = &fields[..] {
- let mut drv = drv.as_str();
- if let Some(pkg) = drv.strip_prefix("/nix/store/") {
- let mut it = pkg.splitn(2, '-');
- it.next();
- if let Some(pkg) = it.next() {
- drv = pkg;
- }
- }
- info!(target: "nix","building {}", drv);
- let span = info_span!("build", drv);
- #[cfg(feature = "indicatif")]
- span.pb_start();
- self.spans.insert(id, span);
- } else {
- warn!("bad build log: {:?}", log)
- }
- }
- NixLog::Start {
- ref fields,
- typ,
- id,
- ..
- } if typ == 100 && fields.len() >= 3 => {
- if let [
- LogField::String(drv),
- LogField::String(from),
- LogField::String(to),
- ..,
- ] = &fields[..]
- {
- let mut drv = drv.as_str();
-
- if let Some(pkg) = drv.strip_prefix("/nix/store/") {
- let mut it = pkg.splitn(2, '-');
- it.next();
- if let Some(pkg) = it.next() {
- drv = pkg;
- }
- }
- info!(target: "nix","copying {} {} -> {}", drv, from, to);
- let span = info_span!("copy", from, to, drv);
- #[cfg(feature = "indicatif")]
- span.pb_start();
- self.spans.insert(id, span);
- } else {
- warn!("bad copy log: {:?}", log)
- }
- }
- NixLog::Start { text, typ, id, .. }
- if typ == 0 || typ == 102 || typ == 103 || typ == 104 =>
- {
- if !text.is_empty()
- && text != "querying info about missing paths"
- && text != "copying 0 paths"
- // Too much spam on lazy-trees branch
- && !(text.starts_with("copying '") && text.ends_with("' to the store"))
- {
- let span = info_span!("job");
- #[cfg(feature = "indicatif")]
- {
- span.pb_start();
- span.pb_set_message(&process_message(text.trim()));
- }
- self.spans.insert(id, span);
- info!(target: "nix", "{}", text);
- }
- }
- NixLog::Start {
- text,
- level: 0,
- typ: 108,
- ..
- } if text.is_empty() => {
- // Cache lookup? Coupled with copy log
- }
- NixLog::Start {
- text,
- level: 4,
- typ: 109,
- ..
- } if text.starts_with("querying info about ") => {
- // Cache lookup
- }
- NixLog::Start {
- text,
- level: 4,
- typ: 101,
- ..
- } if text.starts_with("downloading ") => {
- // NAR downloading, coupled with copy log
- }
- NixLog::Start {
- text,
- level: 1,
- typ: 111,
- ..
- } if text.starts_with("waiting for a machine to build ") => {
- // Useless repeating notification about build
- }
- NixLog::Start {
- text,
- level: 3,
- typ: 111,
- ..
- } if text.starts_with("resolved derivation: ") => {
- // CA resolved
- }
- NixLog::Start {
- text,
- level: 1,
- typ: 111,
- id,
- ..
- } if text.starts_with("waiting for lock on ") => {
- let mut drv = text.strip_prefix("waiting for lock on ").unwrap();
- if let Some(txt) = drv.strip_prefix("\u{1b}[35;1m'") {
- drv = txt;
- }
- if let Some(txt) = drv.strip_suffix("'\u{1b}[0m") {
- drv = txt;
- }
- if let Some(txt) = drv.split("', '").next() {
- drv = txt;
- }
- if let Some(pkg) = drv.strip_prefix("/nix/store/") {
- let mut it = pkg.splitn(2, '-');
- it.next();
- if let Some(pkg) = it.next() {
- drv = pkg;
- }
- }
- let span = info_span!("waiting on drv", drv);
- #[cfg(feature = "indicatif")]
- span.pb_start();
- self.spans.insert(id, span);
- // Concurrent build of the same message
- }
- NixLog::Stop { id, .. } => {
- self.spans.remove(&id);
- }
- NixLog::Result { fields, id, typ } if typ == 101 && !fields.is_empty() => {
- if let Some(span) = self.spans.get(&id) {
- if let LogField::String(s) = &fields[0] {
- #[cfg(feature = "indicatif")]
- span.pb_set_message(&process_message(s.trim()));
- #[cfg(not(feature = "indicatif"))]
- {
- let _span = span.enter();
- info!("{}", process_message(s));
- }
- } else {
- warn!("bad fields: {fields:?}");
- }
- } else {
- warn!("unknown result id: {id} {typ} {fields:?}");
- }
- // dbg!(fields, id, typ);
- }
- NixLog::Result { fields, id, typ } if typ == 105 && fields.len() >= 4 => {
- if let Some(span) = self.spans.get(&id) {
- if let [
- LogField::Num(done),
- LogField::Num(expected),
- LogField::Num(_running),
- LogField::Num(_failed),
- ] = &fields[..4]
- {
- #[cfg(feature = "indicatif")]
- {
- span.pb_set_length(*expected);
- span.pb_set_position(*done);
- }
- let _ = (span, done, expected);
- } else {
- warn!("bad fields: {fields:?}");
- }
- } else {
- // warn!("unknown result id: {id} {typ} {fields:?}");
- // Unaccounted progress.
- }
- // dbg!(fields, id, typ);
- }
- NixLog::Result { typ, .. } if typ == 104 || typ == 106 => {
- // Set phase, expected
- }
- _ => warn!("unknown log: {:?}", log),
- };
- } else {
- let e = e.trim();
- if e.starts_with("Failed tcsetattr(TCSADRAIN): ") {
- return;
- }
- info!("{e}")
- }
- }
-}
crates/better-command/src/lib.rsdiffbeforeafterboth--- a/crates/better-command/src/lib.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-mod handler;
-pub use handler::{ClonableHandler, Handler, NixHandler, NoopHandler, PlainHandler};
crates/fleet-base/Cargo.tomldiffbeforeafterboth--- a/crates/fleet-base/Cargo.toml
+++ b/crates/fleet-base/Cargo.toml
@@ -5,9 +5,15 @@
rust-version.workspace = true
[dependencies]
+remowt-client.workspace = true
+remowt-endpoints.workspace = true
+remowt-fleet.workspace = true
+remowt-link-shared.workspace = true
+remowt-ui-prompt.workspace = true
+
age.workspace = true
anyhow.workspace = true
-better-command.workspace = true
+camino.workspace = true
chrono.workspace = true
clap = { workspace = true, features = ["derive"] }
fleet-shared.workspace = true
@@ -18,15 +24,11 @@
nix-eval.workspace = true
nixlike.workspace = true
nom.workspace = true
-openssh.workspace = true
rand.workspace = true
serde.workspace = true
serde_json.workspace = true
tabled.workspace = true
tempfile.workspace = true
-thiserror.workspace = true
time = { workspace = true, features = ["parsing"] }
tokio.workspace = true
-tokio-util = { workspace = true, features = ["codec"] }
-toml_edit.workspace = true
tracing.workspace = true
crates/fleet-base/src/command.rsdiffbeforeafterboth--- a/crates/fleet-base/src/command.rs
+++ /dev/null
@@ -1,442 +0,0 @@
-use std::{ffi::OsStr, pin, process::Stdio, sync::Arc, task::Poll};
-
-use anyhow::{Result, anyhow};
-use better_command::{Handler, NixHandler, PlainHandler};
-use futures::StreamExt;
-use itertools::Either;
-use openssh::{OverSsh, OwningCommand, Session};
-use serde::de::DeserializeOwned;
-use tokio::{io::AsyncRead, process::Command, select};
-use tokio_util::codec::{BytesCodec, FramedRead, LinesCodec};
-use tracing::debug;
-
-use crate::host::EscalationStrategy;
-
-fn escape_bash(input: &str, out: &mut String) {
- const TO_ESCAPE: &str = "$ !\"#&'()*,;<>?[\\]^`{|}";
- if input.chars().all(|c| !TO_ESCAPE.contains(c)) {
- out.push_str(input);
- return;
- }
- out.push('\'');
- for (i, v) in input.split('\'').enumerate() {
- if i != 0 {
- out.push_str("'\"'\"'");
- }
- out.push_str(v);
- }
- out.push('\'');
-}
-fn ostoutf8(os: impl AsRef<OsStr>) -> String {
- os.as_ref().to_str().expect("non-utf8 data").to_owned()
-}
-
-#[derive(Clone, Debug)]
-pub struct MyCommand {
- command: String,
- args: Vec<String>,
- env: Vec<(String, String)>,
- ssh_session: Option<Arc<Session>>,
- escalation: EscalationStrategy,
- escalate: bool,
-}
-impl MyCommand {
- pub fn new_on(
- escalation: EscalationStrategy,
- cmd: impl AsRef<OsStr>,
- session: Arc<Session>,
- ) -> Self {
- assert!(!cmd.as_ref().is_empty());
- Self {
- command: ostoutf8(cmd),
- args: vec![],
- env: vec![],
- ssh_session: Some(session),
- escalation,
- escalate: false,
- }
- }
- pub fn new(escalation: EscalationStrategy, cmd: impl AsRef<OsStr>) -> Self {
- assert!(!cmd.as_ref().is_empty());
- Self {
- command: ostoutf8(cmd),
- args: vec![],
- env: vec![],
- ssh_session: None,
- escalation,
- escalate: false,
- }
- }
- fn new_here(&self, cmd: impl AsRef<OsStr>) -> Self {
- match self.ssh_session.clone() {
- Some(ssh_session) => Self::new_on(self.escalation, cmd, ssh_session),
- _ => Self::new(self.escalation, cmd),
- }
- }
-
- fn into_args(self) -> Vec<String> {
- let mut out = Vec::new();
- if !self.env.is_empty() {
- out.push("env".to_owned());
- for (k, v) in self.env {
- assert!(!k.contains('='));
- out.push(format!("{k}={v}"));
- }
- }
- out.push(self.command);
- out.extend(self.args);
- out
- }
-
- /// Translates environment variables into env command execution.
- /// Required for ssh, as ssh don't allow to send environment variables (at least by default).
- ///
- /// FIXME: Insecure, as arguments might be seen by other users on the same machine.
- /// Figure out some way to transfer environment using stdio?
- fn translate_env_into_env(self) -> Self {
- if self.env.is_empty() {
- return self;
- }
- let mut out = self.new_here("env");
- for (k, v) in self.env {
- assert!(!k.contains('='));
- out.arg(format!("{k}={v}"));
- }
- out.arg(self.command);
- out.args(self.args);
-
- out
- }
- fn into_string(self) -> String {
- let mut out = String::new();
- if !self.env.is_empty() {
- out.push_str("env");
- for (k, v) in self.env {
- out.push(' ');
- assert!(!k.contains('='));
- escape_bash(&k, &mut out);
- out.push('=');
- escape_bash(&v, &mut out);
- }
- }
- if !out.is_empty() {
- out.push(' ');
- }
- escape_bash(&self.command, &mut out);
- for arg in self.args {
- out.push(' ');
- escape_bash(&arg, &mut out);
- }
- out
- }
- fn into_command_unchecked_local(self) -> Command {
- let mut out = Command::new(self.command);
- out.args(self.args);
- for (k, v) in self.env {
- out.env(k, v);
- }
- out
- }
- fn into_command(self) -> Result<Either<Command, openssh::OwningCommand<Arc<Session>>>> {
- Ok(match self.ssh_session.clone() {
- Some(session) => {
- let cmd = self.translate_env_into_env().into_command_unchecked_local();
- Either::Right(
- cmd.over_ssh(session)
- .map_err(|e| anyhow!("ssh error: {e}"))?,
- )
- }
- _ => {
- let cmd = self.into_command_unchecked_local();
- Either::Left(cmd)
- }
- })
- }
- pub fn arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
- let arg = arg.as_ref();
- self.args.push(ostoutf8(arg));
- self
- }
- pub fn eqarg(&mut self, arg: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut Self {
- let arg = arg.as_ref();
- let value = value.as_ref();
- let arg = ostoutf8(arg);
- let value = ostoutf8(value);
- self.arg(format!("{arg}={value}"));
- self
- }
- pub fn comparg(&mut self, arg: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut Self {
- self.arg(arg);
- self.arg(value);
- self
- }
- pub fn env(&mut self, name: impl AsRef<str>, value: impl AsRef<str>) -> &mut Self {
- self.env
- .push((name.as_ref().to_owned(), value.as_ref().to_owned()));
- self
- }
- pub fn args<V: AsRef<OsStr>>(&mut self, args: impl IntoIterator<Item = V>) -> &mut Self {
- for arg in args.into_iter() {
- let arg = arg.as_ref();
- self.args.push(ostoutf8(arg));
- }
- self
- }
- pub fn sudo(mut self) -> Self {
- self.escalate = true;
- self
- }
- fn wrap_sudo_if_needed(self) -> Self {
- if !self.escalate {
- return self;
- }
- match self.escalation {
- EscalationStrategy::Su => {
- let mut out = self.new_here("su");
- out.arg("-c").arg(self.into_string());
- out
- }
- EscalationStrategy::Sudo => {
- let mut out = self.new_here("sudo");
- out.args(self.into_args());
- out
- }
- EscalationStrategy::Run0 => {
- // run0 wants interactive authentication by default.
- let mut run0 = self.new_here("run0");
- let mut out = self.new_here("script");
-
- // Red backgrounds messes with fleet formatting
- run0.arg("--background=");
- run0.args(self.into_args());
-
- out.arg("-q");
- out.arg("/dev/null");
- out.arg("-c");
- out.arg(run0.into_string());
- dbg!(&out);
- out
- }
- }
- }
-
- pub async fn run(self) -> Result<()> {
- let str = self.clone().into_string();
- let cmd = self.wrap_sudo_if_needed().into_command()?;
- match cmd {
- Either::Left(cmd) => run_nix_inner(str, cmd, &mut PlainHandler).await?,
- Either::Right(cmd) => run_nix_inner_ssh(str, cmd, &mut PlainHandler).await?,
- };
- Ok(())
- }
- pub async fn run_string(self) -> Result<String> {
- let bytes = self.run_bytes().await?;
- Ok(String::from_utf8(bytes)?)
- }
- pub async fn run_value<T: DeserializeOwned>(self) -> Result<T> {
- let v = self.run_string().await?;
- Ok(serde_json::from_str(&v)?)
- }
- pub async fn run_bytes(self) -> Result<Vec<u8>> {
- let str = self.clone().into_string();
- let cmd = self.wrap_sudo_if_needed().into_command()?;
- let v = match cmd {
- Either::Left(cmd) => run_nix_inner_stdout(str, cmd, &mut PlainHandler).await?,
- Either::Right(cmd) => run_nix_inner_stdout_ssh(str, cmd, &mut PlainHandler).await?,
- };
- Ok(v)
- }
-
- pub async fn run_nix_string(mut self) -> Result<String> {
- let str = self.clone().into_string();
- self.arg("--log-format").arg("internal-json");
- let cmd = self.wrap_sudo_if_needed().into_command()?;
- let bytes = match cmd {
- Either::Left(cmd) => run_nix_inner_stdout(str, cmd, &mut NixHandler::default()).await?,
- Either::Right(cmd) => {
- run_nix_inner_stdout_ssh(str, cmd, &mut NixHandler::default()).await?
- }
- };
- Ok(String::from_utf8(bytes)?)
- }
- pub async fn run_nix(mut self) -> Result<()> {
- let str = self.clone().into_string();
- self.arg("--log-format").arg("internal-json");
- let cmd = self.wrap_sudo_if_needed().into_command()?;
- match cmd {
- Either::Left(mut cmd) => {
- cmd.stdout(Stdio::inherit());
- run_nix_inner(str, cmd, &mut NixHandler::default()).await
- }
- Either::Right(mut cmd) => {
- cmd.stdout(openssh::Stdio::inherit());
- run_nix_inner_ssh(str, cmd, &mut NixHandler::default()).await
- }
- }
- }
-}
-
-struct EmptyAsyncRead;
-impl AsyncRead for EmptyAsyncRead {
- fn poll_read(
- self: std::pin::Pin<&mut Self>,
- _cx: &mut std::task::Context<'_>,
- _buf: &mut tokio::io::ReadBuf<'_>,
- ) -> Poll<std::io::Result<()>> {
- Poll::Pending
- }
-}
-
-async fn run_nix_inner_stdout(
- str: String,
- cmd: Command,
- handler: &mut dyn Handler,
-) -> Result<Vec<u8>> {
- Ok(run_nix_inner_raw(str, cmd, true, handler, None)
- .await?
- .expect("has out"))
-}
-async fn run_nix_inner(str: String, cmd: Command, handler: &mut dyn Handler) -> Result<()> {
- let v = run_nix_inner_raw(str, cmd, false, handler, None).await?;
- assert!(v.is_none());
- Ok(())
-}
-async fn run_nix_inner_stdout_ssh(
- str: String,
- cmd: OwningCommand<Arc<Session>>,
- handler: &mut dyn Handler,
-) -> Result<Vec<u8>> {
- Ok(run_nix_inner_raw_ssh(str, cmd, true, handler, None)
- .await?
- .expect("has out"))
-}
-async fn run_nix_inner_ssh(
- str: String,
- cmd: OwningCommand<Arc<Session>>,
- handler: &mut dyn Handler,
-) -> Result<()> {
- let v = run_nix_inner_raw_ssh(str, cmd, false, handler, None).await?;
- assert!(v.is_none());
- Ok(())
-}
-
-async fn run_nix_inner_raw(
- str: String,
- mut cmd: Command,
- want_stdout: bool,
- err_handler: &mut dyn Handler,
- mut out_handler: Option<&mut dyn Handler>,
-) -> Result<Option<Vec<u8>>> {
- cmd.stderr(Stdio::piped());
- cmd.stdout(Stdio::piped());
- debug!("running command {str:?} on local");
- let mut child = cmd.spawn()?;
- let mut stderr = child.stderr.take().unwrap();
- let stdout = child.stdout.take().unwrap();
- let mut err = FramedRead::new(&mut stderr, LinesCodec::new());
- let mut out: Option<Box<dyn AsyncRead + Unpin + Send>> = Some(Box::new(stdout));
- let mut ob = want_stdout
- .then(|| out.take().unwrap())
- .unwrap_or_else(|| Box::new(EmptyAsyncRead));
- let mut ol = (!want_stdout)
- .then(|| out.take().unwrap())
- .unwrap_or_else(|| Box::new(EmptyAsyncRead));
- let mut ob = FramedRead::new(&mut ob, BytesCodec::new());
- let mut ol = FramedRead::new(&mut ol, LinesCodec::new());
-
- // while let Some(line) = read.next().await? {}
-
- let mut out_buf = if want_stdout { Some(vec![]) } else { None };
- loop {
- select! {
- biased;
-
- Some(e) = err.next() => {
- let e = e?;
- err_handler.handle_line(&e);
- },
- Some(o) = ob.next() => {
- out_buf.as_mut().expect("stdout == wants_stdout").extend_from_slice(&o?);
- },
- Some(o) = ol.next() => {
- let o = o?;
- if let Some(out) = out_handler.as_mut() {
- out.handle_line(&o)
- } else {
- err_handler.handle_line(&o)
- }
- // out_handler.handle_info(&o);
- },
- code = child.wait() => {
- let code = code?;
- if !code.success() {
- anyhow::bail!("command '{str}' failed with status {}", code);
- }
- break;
- }
- }
- }
-
- Ok(out_buf)
-}
-async fn run_nix_inner_raw_ssh(
- str: String,
- mut cmd: OwningCommand<Arc<Session>>,
- want_stdout: bool,
- err_handler: &mut dyn Handler,
- mut out_handler: Option<&mut dyn Handler>,
-) -> Result<Option<Vec<u8>>> {
- debug!("running command {str:?} over ssh");
- cmd.stderr(openssh::Stdio::piped());
- cmd.stdout(openssh::Stdio::piped());
- let mut child = cmd.spawn().await?;
- let mut stderr = child.stderr().take().unwrap();
- let stdout = child.stdout().take().unwrap();
- let mut err = FramedRead::new(&mut stderr, LinesCodec::new());
- let mut out: Option<Box<dyn AsyncRead + Unpin + Send>> = Some(Box::new(stdout));
- let mut ob = want_stdout
- .then(|| out.take().unwrap())
- .unwrap_or_else(|| Box::new(EmptyAsyncRead));
- let mut ol = (!want_stdout)
- .then(|| out.take().unwrap())
- .unwrap_or_else(|| Box::new(EmptyAsyncRead));
- let mut ob = FramedRead::new(&mut ob, BytesCodec::new());
- let mut ol = FramedRead::new(&mut ol, LinesCodec::new());
-
- // while let Some(line) = read.next().await? {}
-
- let mut out_buf = if want_stdout { Some(vec![]) } else { None };
-
- let mut wait_future = pin::pin!(child.wait());
- loop {
- select! {
- biased;
-
- Some(e) = err.next() => {
- let e = e?;
- err_handler.handle_line(&e);
- },
- Some(o) = ob.next() => {
- out_buf.as_mut().expect("stdout == wants_stdout").extend_from_slice(&o?);
- },
- Some(o) = ol.next() => {
- let o = o?;
- if let Some(out) = out_handler.as_mut() {
- out.handle_line(&o)
- } else {
- err_handler.handle_line(&o)
- }
- // out_handler.handle_info(&o);
- },
- code = &mut wait_future => {
- let code = code?;
- if !code.success() {
- anyhow::bail!("command '{str}' failed with status {}", code);
- }
- break;
- }
- }
- }
-
- Ok(out_buf)
-}
crates/fleet-base/src/deploy.rsdiffbeforeafterboth--- a/crates/fleet-base/src/deploy.rs
+++ b/crates/fleet-base/src/deploy.rs
@@ -1,8 +1,13 @@
-use std::{path::PathBuf, time::Duration};
+use std::time::Duration;
use anyhow::{Context as _, Result, anyhow, bail};
+use camino::Utf8PathBuf;
use clap::ValueEnum;
use itertools::Itertools;
+use remowt_endpoints::fs::FsClient;
+use remowt_endpoints::systemd::SystemdClient;
+use remowt_fleet::NixClient;
+use remowt_link_shared::BifConfig;
use tokio::time::sleep;
use tracing::{Instrument as _, error, info, info_span, warn};
@@ -59,10 +64,11 @@
pub async fn deploy_task(
action: DeployAction,
host: &ConfigHost,
- built: PathBuf,
+ built: Utf8PathBuf,
specialisation: Option<String>,
disable_rollback: bool,
) -> Result<()> {
+ let remowt = host.remowt().await?;
let deploy_kind = host.deploy_kind().await?;
if (deploy_kind == DeployKind::NixosInstall || deploy_kind == DeployKind::NixosLustrate)
&& !matches!(action, DeployAction::Boot | DeployAction::Upload)
@@ -86,7 +92,7 @@
generation.id, generation.datetime
);
{
- let mut cmd = host.cmd("sh").await?;
+ let mut cmd = remowt.cmd("sh");
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));
if let Err(e) = cmd.sudo().run().await {
error!("failed to set rollback marker: {e}");
@@ -104,7 +110,7 @@
// if we fail to perform generation switch in time, then we will still call the activation script, and this may break something.
// Anyway, reboot will still help in this case.
if action.should_schedule_rollback_run() {
- let mut cmd = host.cmd("systemd-run").await?;
+ let mut cmd = remowt.cmd("systemd-run");
cmd.comparg("--on-active", "3min")
.comparg("--unit", "rollback-watchdog-run")
.arg("systemctl")
@@ -116,14 +122,20 @@
}
}
}
+
+ let remowt = host.remowt().await?;
+ let fs = remowt.endpoints::<FsClient<_>>();
if deploy_kind == DeployKind::NixosLustrate {
// Fleet could also create this file, but as this operation is potentially disruptive,
// make user do it themself.
- if !host.file_exists("/etc/NIXOS_LUSTRATE").await? {
+ if !fs
+ .file_exists(Utf8PathBuf::from("/etc/NIXOS_LUSTRATE"))
+ .await?
+ {
bail!("/etc/NIXOS_LUSTRATE should be created on remote host");
}
// Wanted by NixOS to recognize the system as NixOS.
- let mut cmd = host.cmd("touch").await?;
+ let mut cmd = remowt.cmd("touch");
cmd.arg("/etc/NIXOS");
cmd.sudo().run().await.context("creating /etc/NIXOS")?;
}
@@ -131,7 +143,7 @@
info!(
"running nixos-install to switch profile, install bootloader, and perform activation"
);
- let mut cmd = host.cmd("nixos-install").await?;
+ let mut cmd = remowt.cmd("nixos-install");
cmd.arg("--system").arg(&built).args([
// Channels here aren't fleet host system channels, but channels embedded in installation cd, which might be old.
// It is possible to copy host channels, but I would prefer non-flake nix just to be unsupported.
@@ -147,32 +159,38 @@
if action.should_switch_profile() && !failed {
info!("switching system profile generation");
- // To avoid even more problems, using nixos-install for now.
- // // nix build is unable to work with --store argument for some reason, and nix until 2.26 didn't support copy with --profile argument,
- // // falling back to using nix-env command
- // // After stable NixOS starts using 2.26 - use `nix --store /mnt copy --from /mnt --profile ...` here, and instead of nix build below.
- // let mut cmd = host.cmd("nix-env").await?;
- // cmd.args([
- // "--store",
- // "/mnt",
- // "--profile",
- // "/mnt/nix/var/nix/profiles/system",
- // "--set",
- // ])
- // .arg(&built);
- // if let Err(e) = cmd.sudo().run_nix().await {
- // error!("failed to switch system profile generation: {e}");
- // failed = true;
- // }
- // It would also be possible to update profile atomically during copy:
- // https://github.com/NixOS/nix/pull/11657
- let mut cmd = host.nix_cmd().await?;
- cmd.arg("build");
- cmd.comparg("--profile", "/nix/var/nix/profiles/system");
- cmd.arg(&built);
- if let Err(e) = cmd.sudo().run_nix().await {
- error!("failed to switch system profile generation: {e}");
- failed = true;
+ match host.ensure_nix_plugin().await {
+ Ok(plugin_id) => {
+ let nix_elevated = remowt.plugin_endpoints::<NixClient<_>>(plugin_id);
+ // To avoid even more problems, using nixos-install for now.
+ // // nix build is unable to work with --store argument for some reason, and nix until 2.26 didn't support copy with --profile argument,
+ // // falling back to using nix-env command
+ // // After stable NixOS starts using 2.26 - use `nix --store /mnt copy --from /mnt --profile ...` here, and instead of nix build below.
+ // let mut cmd = host.cmd("nix-env").await?;
+ // cmd.args([
+ // "--store",
+ // "/mnt",
+ // "--profile",
+ // "/mnt/nix/var/nix/profiles/system",
+ // "--set",
+ // ])
+ // .arg(&built);
+ // if let Err(e) = cmd.sudo().run_nix().await {
+ // error!("failed to switch system profile generation: {e}");
+ // failed = true;
+ // }
+ if let Err(e) = nix_elevated
+ .switch_profile("/nix/var/nix/profiles/system".to_owned(), built.clone())
+ .await
+ {
+ error!("failed to switch system profile generation: {e}");
+ failed = true;
+ }
+ }
+ Err(e) => {
+ failed = true;
+ error!("failed to enable nix plugin: {e:?}");
+ }
}
}
@@ -189,7 +207,7 @@
built.clone()
};
let switch_script = specialised.join("bin/switch-to-configuration");
- let mut cmd = host.cmd("systemd-run").in_current_span().await?;
+ let mut cmd = remowt.cmd("systemd-run");
if deploy_kind == DeployKind::NixosLustrate {
cmd.arg("--setenv=NIXOS_INSTALL_BOOTLOADER=1");
}
@@ -209,12 +227,14 @@
}
}
if action.should_create_rollback_marker() {
+ let elevated_systemd = remowt.run0_endpoints::<SystemdClient<BifConfig>>().await?;
+ let elevated_fs = remowt.run0_endpoints::<FsClient<BifConfig>>().await?;
if !disable_rollback {
if failed {
if action.should_schedule_rollback_run() {
info!("executing rollback");
- if let Err(e) = host
- .systemctl_start("rollback-watchdog.service")
+ if let Err(e) = elevated_systemd
+ .start("rollback-watchdog.service".to_owned())
.instrument(info_span!("rollback"))
.await
{
@@ -223,8 +243,8 @@
}
} else {
info!("trying to mark upgrade as successful");
- if let Err(e) = host
- .rm_file("/etc/fleet_rollback_marker", true)
+ if let Err(e) = elevated_fs
+ .rm_file(Utf8PathBuf::from("/etc/fleet_rollback_marker"))
.in_current_span()
.await
{
@@ -234,16 +254,22 @@
}
}
info!("disarming watchdog, just in case");
- if let Err(_e) = host.systemctl_stop("rollback-watchdog.timer").await {
+ if let Err(_e) = elevated_systemd
+ .stop("rollback-watchdog.timer".to_owned())
+ .await
+ {
// It is ok, if there was no reboot - then timer might not be running.
}
if action.should_schedule_rollback_run() {
- if let Err(e) = host.systemctl_stop("rollback-watchdog-run.timer").await {
+ if let Err(e) = elevated_systemd
+ .stop("rollback-watchdog-run.timer".to_owned())
+ .await
+ {
error!("failed to disarm rollback run: {e}");
}
}
- } else if let Err(_e) = host
- .rm_file("/etc/fleet_rollback_marker", true)
+ } else if let Err(_e) = elevated_fs
+ .rm_file(Utf8PathBuf::from("/etc/fleet_rollback_marker"))
.in_current_span()
.await
{
@@ -257,8 +283,8 @@
config: &Config,
host: &ConfigHost,
location: GenerationStorage,
- generation: PathBuf,
-) -> Result<PathBuf> {
+ generation: Utf8PathBuf,
+) -> Result<Utf8PathBuf> {
if matches!(location, GenerationStorage::Pusher) {
bail!("pusher is not enabled in this version of fleet");
}
@@ -273,11 +299,11 @@
}
Err(e) if tries < 3 => {
tries += 1;
- warn!("copy failure ({}/3): {}", tries, e);
+ warn!("copy failure ({}/3): {:#}", tries, e);
sleep(Duration::from_millis(5000)).await;
}
Err(e) => {
- bail!("upload failed: {e}");
+ bail!("upload failed: {e:#}");
}
}
}
crates/fleet-base/src/fleetdata.rsdiffbeforeafterboth--- a/crates/fleet-base/src/fleetdata.rs
+++ b/crates/fleet-base/src/fleetdata.rs
@@ -144,10 +144,6 @@
pub generation_data: Value,
}
-fn is_false(b: &bool) -> bool {
- *b == false
-}
-
#[derive(Serialize, Deserialize, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
#[repr(transparent)]
pub struct SecretOwner(String);
@@ -291,7 +287,7 @@
}
// Which one is easier to access
- return a.owners.len().cmp(&b.owners.len());
+ a.owners.len().cmp(&b.owners.len())
}
impl FleetSecretDistributions {
crates/fleet-base/src/host.rsdiffbeforeafterboth1use std::{2 collections::{BTreeMap, BTreeSet, HashSet},3 ffi::{OsStr, OsString},4 fmt::Display,5 io::Write,6 ops::Deref,7 path::PathBuf,8 str::FromStr,9 sync::{Arc, Mutex, MutexGuard, OnceLock},10};1112use anyhow::{Context, Result, anyhow, bail, ensure};13use chrono::{DateTime, Utc};14use fleet_shared::SecretData;15use nix_eval::{Value, nix_go, nix_go_json, util::assert_warn};16use openssh::{ControlPersist, SessionBuilder};17use serde::de::DeserializeOwned;18use tabled::Tabled;19use tempfile::NamedTempFile;20use time::{UtcDateTime, format_description};21use tracing::warn;2223use crate::{24 command::MyCommand,25 fleetdata::{26 FleetData, FleetSecretData, FleetSecretDistribution, FleetSecretPart, SecretOwner,27 },28};2930pub struct FleetConfigInternals {31 pub prefer_identities: BTreeSet<SecretOwner>,32 pub now: DateTime<Utc>,3334 /// Fleet project directory, containing fleet.nix file.35 pub directory: PathBuf,36 /// builtins.currentSystem37 pub local_system: String,38 pub data: Arc<FleetData>,39 pub nix_args: Vec<OsString>,40 /// fleet_config.config41 pub config_field: Value,42 /// flake.output43 pub flake_outputs: Value,44 // TODO: Remove with connectivity refactor45 pub localhost: String,4647 /// import nixpkgs {system = local};48 pub default_pkgs: Value,49 /// inputs.nixpkgs50 pub nixpkgs: Value,51}5253// TODO: Make field not pub54#[derive(Clone)]55pub struct Config(pub Arc<FleetConfigInternals>);5657impl Deref for Config {58 type Target = FleetConfigInternals;5960 fn deref(&self) -> &Self::Target {61 &self.062 }63}6465#[derive(Clone, Copy, Debug)]66pub enum EscalationStrategy {67 Sudo,68 Run0,69 Su,70}7172#[derive(Clone, PartialEq, Copy, Debug)]73pub enum DeployKind {74 /// NixOS => NixOS managed by fleet75 UpgradeToFleet,76 /// NixOS managed by fleet => NixOS managed by fleet77 Fleet,78 /// Remote host has /mnt, /mnt/boot mounted,79 /// generated config is added to fleet configuration.80 NixosInstall,81 /// Remote host has some system and nix installed in multi-user mode (/nix is owned by root),82 /// generated config is added to fleet configuration,83 /// and /etc/NIXOS_LUSTRATE exists, fleet will perform the rest.84 NixosLustrate,85}8687impl FromStr for DeployKind {88 type Err = anyhow::Error;89 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {90 match s {91 "upgrade-to-fleet" => Ok(Self::UpgradeToFleet),92 "fleet" => Ok(Self::Fleet),93 "nixos-install" => Ok(Self::NixosInstall),94 "nixos-lustrate" => Ok(Self::NixosLustrate),95 v => bail!(96 "unknown deploy_kind: {v}; expected on of \"upgrade-to-fleet\", \"fleet\", \"nixos-install\", \"nixos-lustrate\""97 ),98 }99 }100}101pub struct ConfigHost {102 config: Config,103 pub name: String,104 groups: OnceLock<Vec<String>>,105106 // TODO: Both of those values are taken from host opts, there should be a cleaner way to specify it107 deploy_kind: OnceLock<DeployKind>,108 session_destination: OnceLock<String>,109 legacy_ssh_store: OnceLock<bool>,110111 pub host_config: Option<Value>,112 pub nixos_config: OnceLock<Value>,113 pub nixos_unchecked_config: OnceLock<Value>,114 pub pkgs_override: Option<Value>,115116 // TODO: Move command helpers away with connectivity refactor117 pub local: bool,118 pub session: OnceLock<Arc<openssh::Session>>,119}120121#[derive(Debug, Clone, Copy)]122pub enum GenerationStorage {123 Deployer,124 Machine,125 Pusher,126}127impl GenerationStorage {128 fn prefix(&self) -> &'static str {129 match self {130 GenerationStorage::Deployer => "deployer.",131 GenerationStorage::Machine => "",132 GenerationStorage::Pusher => "pusher.",133 }134 }135}136137#[derive(Tabled, Debug)]138pub struct Generation {139 #[tabled(rename = "ID", format("{}", self.rollback_id()))]140 pub id: u32,141 #[tabled(rename = "Current")]142 pub current: bool,143 #[tabled(rename = "Created at")]144 pub datetime: UtcDateTime,145 #[tabled(format = "{:?}")]146 pub store_path: PathBuf,147 #[tabled(skip)]148 pub location: GenerationStorage,149}150impl Generation {151 pub fn rollback_id(&self) -> String {152 format!("{}{}", self.location.prefix(), self.id)153 }154}155156fn parse_generation_line(g: &str) -> Option<Generation> {157 let mut parts = g.split_whitespace();158 let id = parts.next()?;159 let id: u32 = id.parse().ok()?;160 let date = parts.next()?;161 let time = parts.next()?;162 let current = if let Some(current) = parts.next() {163 if current == "(current)" {164 Some(true)165 } else {166 None167 }168 } else {169 Some(false)170 };171 let current = current?;172 if parts.next().is_some() {173 warn!("unexpected text after generation: {g}");174 }175176 let format = format_description::parse("[year]-[month]-[day] [hour]:[minute]:[second]")177 .expect("valid format");178 let datetime = UtcDateTime::parse(&format!("{date} {time}"), &format).ok()?;179180 Some(Generation {181 id,182 current,183 datetime,184 store_path: PathBuf::new(),185 location: GenerationStorage::Machine,186 })187}188// TODO: Move command helpers away with connectivity refactor189impl ConfigHost {190 pub async fn list_generations(&self, profile: &str) -> Result<Vec<Generation>> {191 let mut cmd = self.cmd("nix-env").await?;192 cmd.comparg("--profile", format!("/nix/var/nix/profiles/{profile}"))193 .arg("--list-generations")194 .env("TZ", "UTC");195 // Sudo is required because --list-generations tries to acquire profile lock196 let data = cmd.sudo().run_string().await?;197 let mut generations = data198 .split('\n')199 .map(|e| e.trim())200 .filter(|&l| !l.is_empty())201 .filter_map(|g| {202 let generation = parse_generation_line(g);203 if generation.is_none() {204 warn!("bad generation: {g}");205 };206 generation207 })208 .collect::<Vec<_>>();209 for ele in generations.iter_mut() {210 let mut cmd = self.cmd("readlink").await?;211 cmd.arg("--")212 .arg(format!("/nix/var/nix/profiles/{profile}-{}-link", ele.id));213 let path = cmd.run_string().await?;214 ele.store_path = PathBuf::from(path.trim_end_matches("\n"));215 }216217 Ok(generations)218 }219220 pub fn set_session_destination(&self, dest: String) {221 self.session_destination222 .set(dest)223 .expect("session destination is already set")224 }225 pub fn set_deploy_kind(&self, kind: DeployKind) {226 self.deploy_kind227 .set(kind)228 .expect("deploy kind is already set");229 }230 pub fn set_legacy_ssh_store(&self, legacy: bool) {231 self.legacy_ssh_store232 .set(legacy)233 .expect("legacy ssh store is already set")234 }235 pub async fn deploy_kind(&self) -> Result<DeployKind> {236 if let Some(kind) = self.deploy_kind.get() {237 return Ok(*kind);238 }239 let is_fleet_managed = match self.file_exists("/etc/FLEET_HOST").await {240 Ok(v) => v,241 Err(e) => {242 bail!("failed to query remote system kind: {e}");243 }244 };245 if !is_fleet_managed {246 bail!(247 "{}",248 indoc::indoc! {"249 host is not marked as managed by fleet250 if you're not trying to lustrate/install system from scratch,251 you should either252 1. manually create /etc/FLEET_HOST file on the target host,253 2. use ?deploy_kind=fleet host argument if you're upgrading from older version of fleet254 3. use ?deploy_kind=upgrade_to_fleet if you're upgrading from plain nixos to fleet-managed nixos255 "}256 );257 }258 // TOCTOU is possible259 let _ = self.deploy_kind.set(DeployKind::Fleet);260 Ok(*self.deploy_kind.get().expect("deploy kind is just set"))261 }262 pub async fn escalation_strategy(&self) -> Result<EscalationStrategy> {263 // Prefer sudo, as run0 has some gotchas with polkit264 // and too many repeating prompts.265 if (self.find_in_path("sudo").await).is_ok() {266 return Ok(EscalationStrategy::Sudo);267 }268 if (self.find_in_path("run0").await).is_ok() {269 return Ok(EscalationStrategy::Run0);270 }271 Ok(EscalationStrategy::Su)272 }273 async fn open_session(&self) -> Result<Arc<openssh::Session>> {274 assert!(!self.local, "do not open ssh connection to local session");275 // FIXME: TOCTOU276 if let Some(session) = &self.session.get() {277 return Ok((*session).clone());278 };279 let mut session = SessionBuilder::default();280 session.control_persist(ControlPersist::ClosedAfterInitialConnection);281282 let dest = self.session_destination.get().unwrap_or(&self.name);283 let session = session284 .connect(&dest)285 .await286 .map_err(|e| anyhow!("ssh error while connecting to {}: {e:#?}", self.name))?;287 let session = Arc::new(session);288 self.session.set(session.clone()).expect("TOCTOU happened");289 Ok(session)290 }291 pub async fn mktemp_dir(&self) -> Result<String> {292 let mut cmd = self.cmd("mktemp").await?;293 cmd.arg("-d");294 let path = cmd.run_string().await?;295 Ok(path.trim_end().to_owned())296 }297 pub async fn file_exists(&self, path: impl AsRef<OsStr>) -> Result<bool> {298 let mut cmd = self.cmd("sh").await?;299 cmd.arg("-c")300 .arg("test -e \"$1\" && echo true || echo false")301 .arg("_")302 .arg(path);303 cmd.run_value().await304 }305 pub async fn read_file_bin(&self, path: impl AsRef<OsStr>) -> Result<Vec<u8>> {306 let mut cmd = self.cmd("cat").await?;307 cmd.arg(path);308 cmd.run_bytes().await309 }310 pub async fn read_file_text(&self, path: impl AsRef<OsStr>) -> Result<String> {311 let mut cmd = self.cmd("cat").await?;312 cmd.arg(path);313 cmd.run_string().await314 }315 pub async fn read_dir(&self, path: impl AsRef<OsStr>) -> Result<Vec<String>> {316 let mut cmd = self.cmd("ls").await?;317 cmd.arg(path);318 let out = cmd.run_string().await?;319 let mut lines = out.split('\n');320 if let Some(last) = lines.next_back() {321 ensure!(last.is_empty(), "output of ls should end with newline");322 }323 Ok(lines.map(ToOwned::to_owned).collect())324 }325 #[allow(dead_code)]326 pub async fn read_file_json<D: DeserializeOwned>(&self, path: impl AsRef<OsStr>) -> Result<D> {327 let text = self.read_file_text(path).await?;328 Ok(serde_json::from_str(&text)?)329 }330 pub async fn read_env(&self, env: &str) -> Result<String> {331 let mut cmd = self.cmd("printenv").await?;332 cmd.arg(env);333 cmd.run_string().await334 }335 pub async fn find_in_path(&self, command: &str) -> Result<String> {336 // // `which` is not a part of coreutils, and it might not exist on machine.337 // let path = self.read_env("PATH").await?;338 // // Assuming delimiter is :, we don't work with windows host, this check will be much339 // // more sophisticated in remowt backend (and quicker, since actual PATH search will be done on remote machine)340 // for ele in path.split(':') {341 // let test_path = format!("{ele}/{cmd}");342 // test -x etc343 // }344 // let mut cmd = self.cmd("printenv").await?;345 // cmd.arg(env);346 // Ok(cmd.run_string().await?)347 // Assuming this is an environment issue if which doesn't exist, will be fixed with remowt.348 let mut cmd = self349 .cmd_escalation(350 // Not used351 EscalationStrategy::Su,352 "which",353 )354 .await?;355 cmd.arg(command);356 cmd.run_string().await357 }358 pub async fn read_file_value<D: FromStr>(&self, path: impl AsRef<OsStr>) -> Result<D>359 where360 <D as FromStr>::Err: Display,361 {362 let text = self.read_file_text(path).await?;363 D::from_str(&text).map_err(|e| anyhow!("failed to parse value: {e}"))364 }365 pub async fn cmd(&self, cmd: impl AsRef<OsStr>) -> Result<MyCommand> {366 self.cmd_escalation(self.escalation_strategy().await?, cmd)367 .await368 }369 pub async fn cmd_escalation(370 &self,371 escalation: EscalationStrategy,372 cmd: impl AsRef<OsStr>,373 ) -> Result<MyCommand> {374 if self.local {375 Ok(MyCommand::new(escalation, cmd))376 } else {377 let session = self.open_session().await?;378 Ok(MyCommand::new_on(escalation, cmd, session))379 }380 }381 pub async fn nix_cmd(&self) -> Result<MyCommand> {382 let mut nix = self.cmd("nix").await?;383 nix.args([384 "--extra-experimental-features",385 "nix-command",386 "--extra-experimental-features",387 "flakes",388 ]);389 Ok(nix)390 }391392 pub async fn decrypt(&self, data: SecretData) -> Result<Vec<u8>> {393 ensure!(data.encrypted, "secret is not encrypted");394 let mut cmd = self.cmd("fleet-install-secrets").await?;395 cmd.arg("decrypt").eqarg("--secret", data.to_string());396 let encoded = cmd397 .sudo()398 .run_string()399 .await400 .context("failed to call remote host for decrypt")?;401 let data: SecretData = encoded.parse().map_err(|e| anyhow!("{e}"))?;402 ensure!(!data.encrypted, "secret came out encrypted");403 Ok(data.data)404 }405 pub async fn reencrypt_distribution(406 &self,407 data: &FleetSecretDistribution,408 targets: BTreeSet<SecretOwner>,409 now: DateTime<Utc>,410 ) -> Result<FleetSecretDistribution> {411 let mut parts = BTreeMap::new();412 for (part_name, part) in &data.secret.parts {413 parts.insert(414 part_name.clone(),415 if part.raw.encrypted {416 FleetSecretPart {417 raw: self.reencrypt(part.raw.clone(), targets.clone()).await?,418 }419 } else {420 part.clone()421 },422 );423 }424 let secret = FleetSecretData {425 created_at: data.secret.created_at,426 expires_at: data.secret.expires_at,427 generation_data: data.secret.generation_data.clone(),428 parts,429 };430 Ok(FleetSecretDistribution::new(targets, secret, now))431 }432 pub async fn reencrypt(433 &self,434 data: SecretData,435 targets: BTreeSet<SecretOwner>,436 ) -> Result<SecretData> {437 ensure!(data.encrypted, "secret is not encrypted");438 let mut cmd = self.cmd("fleet-install-secrets").await?;439 cmd.arg("reencrypt").eqarg("--secret", data.to_string());440 for target in targets {441 let key = self.config.key(&target).await?;442 cmd.eqarg("--targets", key);443 }444 let encoded = cmd445 .sudo()446 .run_string()447 .await448 .context("failed to call remote host for decrypt")?;449 let data: SecretData = encoded.parse().map_err(|e| anyhow!("{e}"))?;450 ensure!(data.encrypted, "secret came out not encrypted");451 Ok(data)452 }453 /// Returns path for futureproofing, as path might change i.e on conversion to CA454 pub async fn remote_derivation(&self, path: &PathBuf) -> Result<PathBuf> {455 if self.local {456 // Path is located locally, thus already trusted.457 return Ok(path.to_owned());458 }459 let mut sign = MyCommand::new(460 // TODO: Look at the current escalation strategy.461 // ... or switch to run0 right after polkit update462 EscalationStrategy::Sudo,463 "nix",464 );465 sign.arg("store")466 .arg("sign")467 .comparg("--key-file", "/etc/nix/private-key")468 .arg("-r")469 .arg(&path);470 if let Err(e) = sign.sudo().run_nix().await {471 warn!("failed to sign store paths: {e}");472 }473 let mut nix = MyCommand::new(474 // Not used475 EscalationStrategy::Su,476 "nix",477 );478 nix.arg("copy").arg("--substitute-on-destination");479480 let proto = if self.legacy_ssh_store.get().cloned().unwrap_or(false) {481 "ssh"482 } else {483 "ssh-ng"484 };485486 match self.deploy_kind().await? {487 DeployKind::Fleet | DeployKind::UpgradeToFleet | DeployKind::NixosLustrate => {488 nix.comparg("--to", format!("{proto}://{}", self.name));489 }490 DeployKind::NixosInstall => {491 nix492 // Signature checking makes no sense with remote-store store argument set, as we're not even interacting with remote nix daemon493 .arg("--no-check-sigs")494 .comparg(495 "--to",496 format!("{proto}://root@{}?remote-store=/mnt", self.name),497 );498 }499 }500 nix.arg(path);501 nix.run_nix().await.context("nix copy")?;502 Ok(path.to_owned())503 }504 pub async fn systemctl_stop(&self, name: &str) -> Result<()> {505 let mut cmd = self.cmd("systemctl").await?;506 cmd.arg("stop").arg(name);507 cmd.sudo().run().await508 }509 pub async fn systemctl_start(&self, name: &str) -> Result<()> {510 let mut cmd = self.cmd("systemctl").await?;511 cmd.arg("start").arg(name);512 cmd.sudo().run().await513 }514515 pub async fn rm_file(&self, path: impl AsRef<OsStr>, sudo: bool) -> Result<()> {516 let mut cmd = self.cmd("rm").await?;517 cmd.arg("-f").arg(path);518 if sudo {519 cmd = cmd.sudo()520 }521 cmd.run().await522 }523}524525struct HostSecretDefinition(Value);526527impl ConfigHost {528 // TOCTOU is possible here in case if config is changed, but this case is not handled anywhere anyway,529 // assuming getting tags always returns the same value.530 pub fn tags(&self) -> Result<Vec<String>> {531 if let Some(v) = self.groups.get() {532 return Ok(v.clone());533 }534 let Some(host_config) = &self.host_config else {535 return Ok(vec![]);536 };537 let tags: Vec<String> = nix_go_json!(host_config.tags);538539 let _ = self.groups.set(tags.clone());540541 Ok(tags)542 }543 pub fn nixos_config(&self) -> Result<Value> {544 if let Some(v) = self.nixos_config.get() {545 return Ok(v.clone());546 }547 let Some(host_config) = &self.host_config else {548 bail!("local host has no nixos_config");549 };550 let nixos_config = nix_go!(host_config.nixos.config);551 assert_warn("nixos config evaluation", &nixos_config)?;552553 let _ = self.nixos_config.set(nixos_config.clone());554555 Ok(nixos_config)556 }557 pub fn nixos_unchecked_config(&self) -> Result<Value> {558 if let Some(v) = self.nixos_unchecked_config.get() {559 return Ok(v.clone());560 }561 let Some(host_config) = &self.host_config else {562 bail!("local host has no nixos_config");563 };564 let nixos_config = nix_go!(host_config.nixos_unchecked.config);565566 let _ = self.nixos_unchecked_config.set(nixos_config.clone());567568 Ok(nixos_config)569 }570571 pub fn list_defined_secrets(&self) -> Result<Vec<String>> {572 let nixos = self.nixos_unchecked_config()?;573 let secrets = nix_go!(nixos.secrets);574 secrets.list_fields()575 }576577 /// Packages for this host, resolved with nixpkgs overlays578 pub fn pkgs(&self) -> Result<Value> {579 if let Some(value) = &self.pkgs_override {580 return Ok(value.clone());581 }582 let Some(host_config) = &self.host_config else {583 bail!("local host has no host_config");584 };585 // TODO: Should nixos.options be cached?586 Ok(nix_go!(host_config.nixos.options._module.args.value.pkgs))587 }588}589590#[derive(Clone)]591pub struct SharedSecretDefinition(Value);592impl SharedSecretDefinition {593 pub fn expected_owners(&self) -> Result<BTreeSet<SecretOwner>> {594 let secret = &self.0;595 Ok(nix_go_json!(secret.expectedOwners))596 }597 pub fn allow_different(&self) -> Result<bool> {598 let secret = &self.0;599 Ok(nix_go_json!(secret.allowDifferent))600 }601 pub fn regenerate_on_owner_added(&self) -> Result<bool> {602 let secret = &self.0;603 Ok(nix_go_json!(secret.regenerateOnOwnerAdded))604 }605 pub fn regenerate_on_owner_removed(&self) -> Result<bool> {606 let secret = &self.0;607 Ok(nix_go_json!(secret.regenerateOnOwnerRemoved))608 }609 pub fn generator(&self) -> Result<Value> {610 let secret = &self.0;611 Ok(nix_go!(secret.generator))612 }613}614615impl Config {616 pub fn tagged_hostnames(&self, tag: &str) -> Result<Vec<String>> {617 let config = &self.config_field;618 let tagged: Vec<String> = nix_go_json!(config.taggedWith[{ tag }]);619 Ok(tagged)620 }621 pub fn expand_owner_set(&self, owners: Vec<String>) -> Result<BTreeSet<String>> {622 let mut out = BTreeSet::new();623 for owner in owners {624 if let Some(tag) = owner.strip_prefix('@') {625 let hosts = self.tagged_hostnames(tag)?;626 out.extend(hosts);627 } else {628 out.insert(owner);629 }630 }631 Ok(out)632 }633 pub fn local_host(&self) -> ConfigHost {634 ConfigHost {635 config: self.clone(),636 name: "<virtual localhost>".to_owned(),637 host_config: None,638 nixos_config: OnceLock::new(),639 nixos_unchecked_config: OnceLock::new(),640 groups: {641 let cell = OnceLock::new();642 let _ = cell.set(vec![]);643 cell644 },645 pkgs_override: Some(self.default_pkgs.clone()),646647 local: true,648 session: OnceLock::new(),649 deploy_kind: OnceLock::new(),650 session_destination: OnceLock::new(),651 legacy_ssh_store: OnceLock::new(),652 }653 }654655 pub fn preferred_hosts(656 &self,657 filter: impl Fn(&str) -> bool,658 ) -> Result<impl Iterator<Item = Result<ConfigHost>>> {659 let prefer = self660 .prefer_identities661 .iter()662 .filter_map(|v| v.as_host())663 .collect::<HashSet<_>>();664 let config = &self.config_field;665 let mut names = nix_go!(config.hosts).list_fields()?;666 names.retain(|s| filter(s));667 names.sort_by_key(|h| prefer.contains(h.as_str()));668669 Ok(names.into_iter().map(|h| self.host(&h)))670 }671672 pub fn host(&self, name: &str) -> Result<ConfigHost> {673 let config = &self.config_field;674 let host_config = nix_go!(config.hosts[{ name }]);675676 Ok(ConfigHost {677 config: self.clone(),678 name: name.to_owned(),679 host_config: Some(host_config),680 nixos_config: OnceLock::new(),681 nixos_unchecked_config: OnceLock::new(),682 groups: OnceLock::new(),683 pkgs_override: None,684685 // TODO: Remove with connectivit refactor686 local: self.localhost == name,687 session: OnceLock::new(),688 deploy_kind: OnceLock::new(),689 session_destination: OnceLock::new(),690 legacy_ssh_store: OnceLock::new(),691 })692 }693 pub fn list_hosts(&self) -> Result<Vec<ConfigHost>> {694 let config = &self.config_field;695 let names = nix_go!(config.hosts).list_fields()?;696 let mut out = vec![];697 for name in names {698 out.push(self.host(&name)?);699 }700 Ok(out)701 }702 // TODO: Replace usages with .host().nixos_config703 pub fn system_config(&self, host: &str) -> Result<Value> {704 let fleet_field = &self.config_field;705 Ok(nix_go!(fleet_field.hosts[{ host }].nixos.config))706 }707708 pub fn secret_definition(&self, secret: &str) -> Result<Option<SharedSecretDefinition>> {709 let config = &self.config_field;710 let shared_secrets = nix_go!(config.secrets);711 if !shared_secrets.has_field(secret)? {712 return Ok(None);713 }714 Ok(Some(SharedSecretDefinition(nix_go!(715 shared_secrets[secret]716 ))))717 }718719 pub fn save(&self) -> Result<()> {720 let mut tempfile = NamedTempFile::new_in(self.directory.clone()).context("failed to create updated version of fleet.nix in the same directory as original.\nDo you have write access to it? Access only to the fleet.nix won't be enough, the directory is used for atomic overwrite operation.\nIt is not recommended to use fleet by root anyway, move fleet project to your home directory.")?;721 let data = nixlike::serialize(&*self.data)?;722 tempfile.write_all(723 format!(724 "# This file contains fleet state and shouldn't be edited by hand\n\n{data}\n\n# vim: ts=2 et nowrap\n"725 )726 .as_bytes(),727 )?;728 let mut fleet_data_path = self.directory.clone();729 fleet_data_path.push("fleet.nix");730 tempfile.persist(fleet_data_path)?;731 Ok(())732 }733}crates/fleet-base/src/keys.rsdiffbeforeafterboth--- a/crates/fleet-base/src/keys.rs
+++ b/crates/fleet-base/src/keys.rs
@@ -31,7 +31,8 @@
} else {
warn!("Loading key for {}", host);
let host = self.host(host)?;
- let mut cmd = host.cmd("cat").await?;
+ let remowt = host.remowt().await?;
+ let mut cmd = remowt.cmd("cat");
cmd.arg("/etc/ssh/ssh_host_ed25519_key.pub");
let key = cmd.run_string().await?;
self.update_key(&host.name, key.clone());
crates/fleet-base/src/lib.rsdiffbeforeafterboth--- a/crates/fleet-base/src/lib.rs
+++ b/crates/fleet-base/src/lib.rs
@@ -1,8 +1,6 @@
-pub mod command;
pub mod deploy;
pub mod fleetdata;
pub mod host;
mod keys;
pub mod opts;
pub mod primops;
-pub mod secret_storage;
crates/fleet-base/src/opts.rsdiffbeforeafterboth--- a/crates/fleet-base/src/opts.rs
+++ b/crates/fleet-base/src/opts.rs
@@ -1,9 +1,8 @@
use std::{
collections::{BTreeMap, BTreeSet},
env::current_dir,
- ffi::OsString,
str::FromStr,
- sync::{Arc, Mutex},
+ sync::{Arc, OnceLock},
};
use anyhow::{Context, Result, bail};
@@ -196,7 +195,7 @@
}
// TODO: Config should be detached from opts.
- pub fn build(&self, nix_args: Vec<OsString>, assert: bool) -> Result<Config> {
+ pub fn build(&self, assert: bool) -> Result<Config> {
let cwd = current_dir()?;
let mut directory = cwd.clone();
let mut fleet_data_path = directory.join("fleet.nix");
@@ -274,11 +273,11 @@
data,
flake_outputs: flake,
local_system: self.local_system.clone(),
- nix_args,
config_field,
default_pkgs,
nixpkgs,
localhost: self.localhost.to_owned(),
+ local_host: OnceLock::new(),
}));
PRIMOPS_DATA
crates/fleet-base/src/primops.rsdiffbeforeafterboth--- a/crates/fleet-base/src/primops.rs
+++ b/crates/fleet-base/src/primops.rs
@@ -1,10 +1,12 @@
use std::collections::{BTreeMap, BTreeSet, HashMap};
-use std::sync::OnceLock;
+use std::sync::{Arc, OnceLock};
use anyhow::{Context, bail, ensure};
use fleet_shared::SecretData;
use itertools::Itertools;
use nix_eval::{NativeFn, Value, await_in_nix, nix_go, nix_go_json};
+use remowt_endpoints::fs::FsClient;
+use remowt_link_shared::BifConfig;
use serde::Deserialize;
use tracing::{info, warn};
@@ -28,7 +30,7 @@
let pkgs = host_on.pkgs()?;
let default_mk_secret_generators = nix_go!(pkgs.mkSecretGenerators);
let generators = nix_go!(default_mk_secret_generators(Obj { recipients }));
- Ok(pkgs.clone().attrs_update(generators)?)
+ pkgs.clone().attrs_update(generators)
}
pub fn get_default_pkgs_and_generators(config: &Config) -> Result<Value> {
let host_on = config.local_host();
@@ -91,12 +93,18 @@
let impure_on: Option<String> = nix_go_json!(default_generator_drv.impureOn);
let host_on = if let Some(on) = &impure_on {
- config
- .host(on)
- .context("failed to get secret generation target host")?
+ Arc::new(
+ config
+ .host(on)
+ .context("failed to get secret generation target host")?,
+ )
} else {
config.local_host()
};
+
+ let remowt = host_on.remowt().await?;
+ let fs = remowt.endpoints::<FsClient<BifConfig>>();
+
let mut recipients = Vec::new();
for owner in &expectations.owners {
recipients.push(config.key(owner).await?);
@@ -116,12 +124,13 @@
.context("failed to copy generator to target host")?;
// TODO: Remove destdir after everything is done
- let out_parent = host_on
+ let out_parent = fs
.mktemp_dir()
.await
+ .map_err(|e| anyhow!("{e:?}"))
.context("failed to prepare generator output dir on target host")?;
- let out = format!("{out_parent}/out");
- let mut generator_cmd = host_on.cmd(generator).await?;
+ let out = out_parent.join("out");
+ let mut generator_cmd = remowt.cmd(generator);
generator_cmd.env("out", &out);
if impure_on.is_none() {
let project_path: String = config
@@ -138,7 +147,7 @@
.context("failed to run impure generator")?;
{
- let marker = host_on.read_file_text(format!("{out}/marker")).await?;
+ let marker = fs.read_file_text(out.join("marker")).await?;
ensure!(
marker == "SUCCESS",
"impure generator ended prematurely, secret generation failed"
@@ -147,15 +156,16 @@
let mut missing_parts = expectations.parts.clone();
let mut parts = BTreeMap::new();
- for part in host_on.read_dir(&out).await? {
+ for part in fs.read_dir(&out).await? {
+ let part = part.into_string();
if part == "created_at" || part == "expires_at" || part == "marker" {
continue;
}
let Some(part_def) = missing_parts.remove(&part) else {
bail!("secret generator has produced an unexpected part: {part}");
};
- let contents: SecretData = host_on
- .read_file_text(format!("{out}/{part}"))
+ let contents: SecretData = fs
+ .read_file_text(out.join("part"))
.await?
.parse()
.map_err(|e| anyhow!("failed to decode secret {out:?} part {part:?}: {e}"))?;
@@ -178,11 +188,12 @@
);
}
- let created_at = host_on.read_file_value(format!("{out}/created_at")).await?;
- let expires_at = host_on
- .read_file_value(format!("{out}/expires_at"))
- .await
- .ok();
+ let created_at = fs.read_file_value(out.join("created_at")).await??;
+ let expires_at = match fs.read_file_value(out.join("expires_at")).await {
+ Ok(v) => Some(v?),
+ Err(remowt_endpoints::fs::Error::NotFound) => None,
+ Err(e) => return Err(e.into()),
+ };
let new_data = FleetSecretData {
created_at,
crates/fleet-base/src/secret_storage.rsdiffbeforeafterboth--- a/crates/fleet-base/src/secret_storage.rs
+++ /dev/null
@@ -1,278 +0,0 @@
-use anyhow::{Result, bail, ensure};
-use itertools::Itertools;
-use std::fs::{File, metadata};
-use std::io::{self, ErrorKind, Read, Write};
-use std::path::PathBuf;
-use std::str::FromStr;
-use std::{env, fs};
-
-use tempfile::{TempPath, tempfile_in};
-use toml_edit::{Document, DocumentMut, Formatted, Item, Value};
-
-struct Name(String);
-
-fn encode_name(name: &str) -> Name {
- assert!(
- !name.starts_with(['_', '.']),
- "groups should not start with _ or ."
- );
- assert!(
- !name.chars().any(|c| c == '/'),
- "group name should not contain internal slash"
- );
- Name(name.to_owned())
-}
-
-enum RewriteError {
- ConcurrentCreate,
- ConcurrentDelete,
- ConcurrentModify,
- ConcurrentWrite,
- Io(io::Error),
- Persist(tempfile::PersistError),
-}
-
-fn safe_rewrite(
- path: &PathBuf,
- old_content: Option<Vec<u8>>,
- new_content: Option<Vec<u8>>,
-) -> Result<(), RewriteError> {
- let mut f = match (old_content.is_some(), new_content.is_some()) {
- (false, true) => match File::create_new(path) {
- Ok(v) => v,
- Err(e) if e.kind() == ErrorKind::AlreadyExists => {
- return Err(RewriteError::ConcurrentCreate);
- }
- Err(e) => return Err(RewriteError::Io(e)),
- },
- (true, _) => match File::open(&path) {
- Ok(v) => v,
- Err(_e) => return Err(RewriteError::ConcurrentDelete),
- },
- (false, false) => match metadata(&path) {
- Err(e) if e.kind() == ErrorKind::NotFound => {
- return Ok(());
- }
- Ok(_) => return Err(RewriteError::ConcurrentCreate),
- Err(e) => return Err(RewriteError::Io(e)),
- },
- };
- f.lock().map_err(RewriteError::Io)?;
- let mut check_content = vec![];
- f.read_to_end(&mut check_content)
- .map_err(RewriteError::Io)?;
- match &old_content {
- Some(old) => {
- if old != &check_content {
- return Err(RewriteError::ConcurrentModify);
- }
- }
- None => {
- if !check_content.is_empty() {
- return Err(RewriteError::ConcurrentDelete);
- }
- }
- }
- if let Some(new_content) = new_content {
- if Some(&new_content) == old_content.as_ref() {
- return Ok(());
- }
- let dir = path.parent().expect("file is in directory, thus not root");
- let mut tempfile = tempfile::Builder::new()
- .prefix(".rewrite-")
- .tempfile_in(dir)
- .map_err(RewriteError::Io)?;
- tempfile.write_all(&new_content).map_err(RewriteError::Io)?;
- tempfile.flush().map_err(RewriteError::Io)?;
- tempfile.persist(path).map_err(RewriteError::Persist)?;
- } else {
- fs::remove_file(path).map_err(RewriteError::Io)?;
- }
- let _ = f.unlock();
- Ok(())
-}
-fn update_string(path: PathBuf, modify: impl Fn(&mut Option<String>) -> Result<()>) -> Result<()> {
- loop {
- let orig = match fs::read_to_string(&path) {
- Ok(v) => Some(v),
- Err(e) if e.kind() == ErrorKind::NotFound => None,
- Err(e) => return Err(e.into()),
- };
- let mut edit = orig.clone();
- modify(&mut edit);
-
- match safe_rewrite(&path, orig.map(String::into), edit.map(String::into)) {
- Ok(()) => return Ok(()),
- Err(
- RewriteError::ConcurrentCreate
- | RewriteError::ConcurrentModify
- | RewriteError::ConcurrentWrite
- | RewriteError::ConcurrentDelete,
- ) => {
- continue;
- }
- Err(RewriteError::Io(io)) => return Err(io.into()),
- Err(RewriteError::Persist(io)) => return Err(io.into()),
- }
- }
-}
-fn update_toml(path: PathBuf, modify: impl Fn(&mut DocumentMut) -> Result<()>) -> Result<()> {
- update_string(path, |str| {
- let mut doc = match str {
- None => DocumentMut::new(),
- Some(v) => DocumentMut::from_str(v)?,
- };
- modify(&mut doc)?;
- if doc.is_empty() {
- *str = None
- } else {
- *str = Some(doc.to_string())
- }
- Ok(())
- })
-}
-fn update_lines(path: PathBuf, modify: impl Fn(&mut Vec<String>) -> Result<()>) -> Result<()> {
- update_string(path, |str| {
- let mut list = if let Some(str) = str {
- str.split('\n').map(|s| s.to_owned()).collect_vec()
- } else {
- vec![]
- };
- let had_end_newline = if list.last().map(|v| v.as_str()) == Some("") {
- list.pop();
- true
- } else {
- false
- };
- modify(&mut list)?;
- if list.is_empty() {
- *str = None
- } else {
- if had_end_newline {
- list.push("".to_owned())
- }
- *str = Some(list.join("\n"));
- }
- Ok(())
- })
-}
-fn update_section(
- data: &mut Vec<String>,
- start: &str,
- end: &str,
- modify: impl Fn(&mut Vec<String>) -> Result<()>,
-) -> Result<()> {
- let first = data
- .iter()
- .enumerate()
- .filter(|(_, v)| *v == start)
- .at_most_one()
- .map_err(|_| anyhow::anyhow!("there should be at most one section start"))?
- .map(|(v, _)| v);
- let last = data
- .iter()
- .enumerate()
- .filter(|(_, v)| *v == end)
- .at_most_one()
- .map_err(|_| anyhow::anyhow!("there should be at most one section end"))?
- .map(|(v, _)| v);
-
- match (first, last) {
- (None, None) => {
- let mut out = Vec::new();
- modify(&mut out)?;
- if out.is_empty() {
- return Ok(());
- }
- data.push(start.to_owned());
- data.extend(out);
- data.push(end.to_owned());
- Ok(())
- }
- (None, Some(_)) | (Some(_), None) => {
- bail!("mismatched section start/end")
- }
- (Some(first), Some(last)) => {
- ensure!(first < last, "section end should come after start");
- let mut out = data[first + 1..last]
- .iter()
- .map(|v| v.to_owned())
- .collect_vec();
- modify(&mut out)?;
- if out.is_empty() {
- data.drain(first..=last);
- } else {
- data.splice(first + 1..last, out);
- }
- Ok(())
- }
- }
-}
-
-struct Group {
- path: PathBuf,
-}
-impl Group {
- fn new(path: PathBuf) -> Self {
- Self { path }
- }
- fn manage(&self, manager: &str) {}
- fn ensure_managing(&self, manager: &str) {
- if !self.has_stored() {
- return;
- }
- let managed = match fs::read_to_string(self.path.join(".managed_by")) {
- Ok(found_manager) => found_manager.lines().any(|line| line == manager),
- Err(e) if e.kind() == ErrorKind::NotFound => true,
- Err(e) => panic!("{e}"),
- };
- assert!(managed);
- }
- fn has_stored(&self) -> bool {
- match fs::metadata(&self.path) {
- Ok(d) => d.is_dir(),
- Err(e) if e.kind() == ErrorKind::NotFound => false,
- Err(e) => panic!("{e}"),
- }
- }
-}
-
-struct Root {
- path: PathBuf,
-}
-impl Root {
- fn new(path: PathBuf) -> Self {
- Self { path }
- }
- fn subgroup(&self, name: &str) -> Group {
- Group::new(self.path.join(name))
- }
-}
-
-#[test]
-fn test() {
- let mut data = vec![
- "a".to_owned(),
- "b".to_owned(),
- "start".to_owned(),
- "c".to_owned(),
- "d".to_owned(),
- "end".to_owned(),
- "e".to_owned(),
- "f".to_owned(),
- ];
- update_section(&mut data, "start", "end", |a| {
- a.push("vv".to_owned());
- Ok(())
- })
- .unwrap();
- dbg!(&data);
- // for v in 0..1000 {
- // update_toml(PathBuf::from("./test.toml"), |e| {
- // e.as_table_mut()
- // .insert("hello", Item::Value(Value::Integer(Formatted::new(v))));
- // })
- // .expect("update")
- // }
- // v.subgroup(name)
-}
crates/nix-eval/Cargo.tomldiffbeforeafterboth--- a/crates/nix-eval/Cargo.toml
+++ b/crates/nix-eval/Cargo.toml
@@ -10,10 +10,11 @@
nixlike.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
-thiserror.workspace = true
tracing.workspace = true
+camino = { workspace = true, features = ["serde1"] }
cxx.workspace = true
+futures.workspace = true
itertools.workspace = true
test-log.workspace = true
tokio.workspace = true
crates/nix-eval/src/drv.rsdiffbeforeafterboth--- a/crates/nix-eval/src/drv.rs
+++ b/crates/nix-eval/src/drv.rs
@@ -66,7 +66,13 @@
#[derive(Debug, Deserialize)]
pub struct DrvParsed {
pub inputs: DrvInputs,
- pub outputs: HashMap<String, serde_json::Value>,
+ pub outputs: HashMap<String, DrvParsedOutput>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct DrvParsedOutput {
+ #[serde(default)]
+ pub path: Option<String>,
}
#[derive(Debug, Deserialize)]
@@ -82,18 +88,19 @@
pub outputs: Vec<String>,
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct DrvGraph {
pub root: String,
pub nodes: HashMap<String, DrvNode>,
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct DrvNode {
pub name: String,
pub input_drvs: HashMap<String, Vec<String>>,
pub input_srcs: Vec<String>,
- pub outputs: Vec<String>,
+ // TODO: CA outputs without a known paths are skipped
+ pub outputs: HashMap<String, String>,
}
impl DrvGraph {
@@ -124,19 +131,59 @@
}
}
+ let outputs: HashMap<String, String> = parsed
+ .outputs
+ .into_iter()
+ .filter_map(|(name, out)| out.path.map(|p| (name, to_absolute_store_path(&sd, &p))))
+ .collect();
+
nodes.insert(
path.clone(),
DrvNode {
name: extract_drv_name(&path),
input_drvs,
input_srcs: parsed.inputs.srcs,
- outputs: parsed.outputs.into_keys().collect(),
+ outputs,
},
);
}
Ok(Self { root, nodes })
}
+
+ pub fn wanted_outputs(&self, root_outputs: &[String]) -> HashMap<String, Vec<String>> {
+ let mut wanted: HashMap<String, HashSet<String>> = HashMap::new();
+ wanted.insert(self.root.clone(), root_outputs.iter().cloned().collect());
+
+ let mut queue: VecDeque<String> = VecDeque::new();
+ queue.push_back(self.root.clone());
+ while let Some(path) = queue.pop_front() {
+ let Some(node) = self.nodes.get(&path) else {
+ continue;
+ };
+ for (dep_path, dep_outputs) in &node.input_drvs {
+ let entry = wanted.entry(dep_path.clone()).or_default();
+ let mut changed = false;
+ for o in dep_outputs {
+ if entry.insert(o.clone()) {
+ changed = true;
+ }
+ }
+ if changed {
+ queue.push_back(dep_path.clone());
+ }
+ }
+ }
+
+ wanted
+ .into_iter()
+ .map(|(k, v)| {
+ let mut v: Vec<_> = v.into_iter().collect();
+ v.sort();
+ (k, v)
+ })
+ .collect()
+ }
}
fn extract_drv_name(drv_path: &str) -> String {
crates/nix-eval/src/lib.ccdiffbeforeafterboth--- a/crates/nix-eval/src/lib.cc
+++ b/crates/nix-eval/src/lib.cc
@@ -1,8 +1,25 @@
#include "nix-eval/src/lib.rs"
#include "lib.hh"
#include <nix/fetchers/fetch-settings.hh>
+#include <nix/store/build-result.hh>
+#include <nix/store/content-address.hh>
+#include <nix/store/derived-path.hh>
+#include <nix/store/local-fs-store.hh>
+#include <nix/store/outputs-spec.hh>
+#include <nix/store/path-info.hh>
+#include <nix/store/profiles.hh>
+#include <nix/store/realisation.hh>
+#include <nix/store/store-api.hh>
+#include <nix/util/file-system.hh>
+#include <nix/util/hash.hh>
+#include <nix/util/posix-source-accessor.hh>
#include <nix/util/ref.hh>
+#include <nix/util/signature/local-keys.hh>
+#include <nix/util/signature/signer.hh>
+#include <nix/util/source-path.hh>
#include <nix_api_fetchers.h>
+#include <nix_api_store_internal.h>
+#include <sstream>
struct nix_fetchers_settings {
nix::ref<nix::fetchers::Settings> settings;
@@ -15,3 +32,175 @@
bool result = settings_ref->set(setting, value);
}
}
+
+rust::String switch_profile(Store *store, rust::Str profile,
+ rust::Str store_path) {
+ try {
+ auto nixStore = store->ptr;
+ auto *lfs = dynamic_cast<nix::LocalFSStore *>(&*nixStore);
+ if (!lfs)
+ return rust::String("destination is not a local-fs store");
+ auto path = nixStore->parseStorePath(std::string(store_path));
+ std::filesystem::path prof = std::string(profile);
+ auto gen = nix::createGeneration(*lfs, prof, path);
+ nix::switchLink(prof, gen);
+ return rust::String();
+ } catch (const std::exception &e) {
+ return rust::String(e.what());
+ }
+}
+
+rust::String sign_closure(Store *store, rust::Str store_path,
+ rust::Str key_file) {
+ try {
+ auto nixStore = store->ptr;
+ nix::LocalSigner signer(
+ nix::SecretKey::parse(nix::readFile(std::string(key_file))));
+ auto root = nixStore->parseStorePath(std::string(store_path));
+ nix::StorePathSet closure;
+ nixStore->computeFSClosure(root, closure);
+ for (auto &p : closure) {
+ auto info = nixStore->queryPathInfo(p);
+ nix::ValidPathInfo info2(*info);
+ info2.sign(*nixStore, signer);
+ nixStore->addSignatures(p, info2.sigs);
+ }
+ return rust::String();
+ } catch (const std::exception &e) {
+ return rust::String(e.what());
+ }
+}
+
+CxxListGenerationsResult list_generations(rust::Str profile_path) {
+ CxxListGenerationsResult out{rust::String(), {}};
+ try {
+ auto [gens, current] =
+ nix::findGenerations(std::filesystem::path(std::string(profile_path)));
+ for (auto &g : gens) {
+ CxxProfileGeneration cg{};
+ cg.id = g.number;
+ cg.store_path = rust::String(g.path.string());
+ cg.creation_time_unix = static_cast<int64_t>(g.creationTime);
+ cg.current = current.has_value() && *current == g.number;
+ out.generations.push_back(cg);
+ }
+ } catch (const std::exception &e) {
+ out.error = rust::String(e.what());
+ }
+ return out;
+}
+
+static std::vector<std::string> split_lines(rust::Str joined) {
+ std::vector<std::string> out;
+ std::string buf;
+ std::istringstream iss((std::string(joined)));
+ while (std::getline(iss, buf)) {
+ if (!buf.empty())
+ out.push_back(buf);
+ }
+ return out;
+}
+
+CxxBuildResult build_drv_outputs(Store *store, rust::Str drv_path,
+ // TODO: Vec<str>
+ rust::Str output_names_joined) {
+ CxxBuildResult res{rust::String(), {}};
+ try {
+ auto nixStore = store->ptr;
+ auto sp = nixStore->parseStorePath(std::string(drv_path));
+
+ nix::DerivedPath::Built built{
+ .drvPath = nix::makeConstantStorePathRef(sp),
+ .outputs = nix::OutputsSpec{nix::OutputsSpec::All{}},
+ };
+ auto names = split_lines(output_names_joined);
+ if (!names.empty()) {
+ std::set<nix::OutputName, std::less<>> nameSet;
+ for (auto &n : names)
+ nameSet.insert(n);
+ built.outputs =
+ nix::OutputsSpec{nix::OutputsSpec::Names{std::move(nameSet)}};
+ }
+
+ std::vector<nix::DerivedPath> reqs;
+ reqs.push_back(built);
+
+ auto results = nixStore->buildPathsWithResults(reqs);
+ for (auto &r : results) {
+ if (auto *failure = r.tryGetFailure()) {
+ res.error = rust::String(failure->what());
+ return res;
+ }
+ }
+ for (auto &r : results) {
+ if (auto *success = r.tryGetSuccess()) {
+ for (auto &[name, real] : success->builtOutputs) {
+ res.outputs.push_back(
+ rust::String(nixStore->printStorePath(real.outPath)));
+ }
+ }
+ }
+ } catch (const std::exception &e) {
+ res.error = rust::String(e.what());
+ }
+ return res;
+}
+
+CxxBuildResult substitute_paths(Store *store, rust::Str paths_joined) {
+ CxxBuildResult res{rust::String(), {}};
+ try {
+ auto nixStore = store->ptr;
+ auto paths = split_lines(paths_joined);
+
+ std::vector<nix::DerivedPath> reqs;
+ reqs.reserve(paths.size());
+ for (auto &p : paths) {
+ reqs.push_back(nix::DerivedPath::Opaque{nixStore->parseStorePath(p)});
+ }
+
+ // Substituter miss will cause scheduler to trigger build
+ auto results = nixStore->buildPathsWithResults(reqs);
+ for (auto &r : results) {
+ if (r.tryGetSuccess() == nullptr)
+ continue;
+ if (auto *opaque = std::get_if<nix::DerivedPath::Opaque>(&r.path.raw())) {
+ res.outputs.push_back(
+ rust::String(nixStore->printStorePath(opaque->path)));
+ }
+ }
+ } catch (const std::exception &e) {
+ res.error = rust::String(e.what());
+ }
+ return res;
+}
+
+bool is_valid_path(Store *store, rust::Str path) {
+ try {
+ auto nixStore = store->ptr;
+ auto sp = nixStore->parseStorePath(std::string(path));
+ return nixStore->isValidPath(sp);
+ } catch (const std::exception &) {
+ return false;
+ }
+}
+
+AddFileToStoreResult add_file_to_store(Store *store, rust::Str name,
+ rust::Str path) {
+ AddFileToStoreResult out{rust::String(), rust::String(), rust::String()};
+ try {
+ auto nixStore = store->ptr;
+ auto src = nix::PosixSourceAccessor::createAtRoot(
+ std::filesystem::path(std::string(path)));
+ auto info = nixStore->addToStoreSlow(std::string(name), src,
+ nix::ContentAddressMethod::Raw::Flat,
+ nix::HashAlgorithm::SHA256);
+ out.store_path = rust::String(nixStore->printStorePath(info.path));
+ if (info.ca.has_value()) {
+ out.hash =
+ rust::String(info.ca->hash.to_string(nix::HashFormat::SRI, true));
+ }
+ } catch (const std::exception &e) {
+ out.error = rust::String(e.what());
+ }
+ return out;
+}
crates/nix-eval/src/lib.hhdiffbeforeafterboth--- a/crates/nix-eval/src/lib.hh
+++ b/crates/nix-eval/src/lib.hh
@@ -1,7 +1,32 @@
#pragma once
+#include "rust/cxx.h"
#include <nix_api_fetchers.h>
+struct Store;
+
+struct AddFileToStoreResult;
+struct CxxBuildResult;
+
extern "C" {
void set_fetcher_setting(nix_fetchers_settings *settings, const char *setting,
const char *value);
}
+
+rust::String switch_profile(Store *store, rust::Str profile,
+ rust::Str store_path);
+
+rust::String sign_closure(Store *store, rust::Str store_path,
+ rust::Str key_file);
+
+struct CxxListGenerationsResult;
+CxxListGenerationsResult list_generations(rust::Str profile_path);
+
+AddFileToStoreResult add_file_to_store(Store *store, rust::Str name,
+ rust::Str path);
+
+CxxBuildResult build_drv_outputs(Store *store, rust::Str drv_path,
+ rust::Str output_names_joined);
+
+CxxBuildResult substitute_paths(Store *store, rust::Str paths_joined);
+
+bool is_valid_path(Store *store, rust::Str path);
crates/nix-eval/src/lib.rsdiffbeforeafterboth--- a/crates/nix-eval/src/lib.rs
+++ b/crates/nix-eval/src/lib.rs
@@ -1,12 +1,13 @@
use std::borrow::Cow;
use std::cell::RefCell;
+use std::collections::HashMap;
use std::ffi::{CStr, CString, c_char, c_int, c_uint, c_void};
use std::ptr::{null, null_mut};
use std::sync::{Arc, LazyLock, OnceLock};
use std::{array, fmt, slice};
-use std::{collections::HashMap, path::PathBuf};
use anyhow::{Context, anyhow, bail};
+use camino::{Utf8Path, Utf8PathBuf};
use itertools::Itertools;
use serde::Serialize;
use serde::de::DeserializeOwned;
@@ -38,8 +39,9 @@
make_attrs, make_bindings_builder, make_list, make_list_builder, realised_string,
realised_string_free, realised_string_get_buffer_size, realised_string_get_buffer_start,
realised_string_get_store_path, realised_string_get_store_path_count, register_primop,
- set_err_msg, setting_set, state_free, store_open, store_parse_path, store_path_free,
- store_path_name, string_realise, value, value_call, value_decref, value_force, value_incref,
+ set_err_msg, setting_set, state_free, store_copy_closure, store_free, store_open,
+ store_parse_path, store_path_free, store_path_name, string_realise, value, value_call,
+ value_decref, value_force, value_incref,
};
// Contains macros helpers
@@ -47,6 +49,7 @@
pub mod logging;
#[doc(hidden)]
pub mod macros;
+pub mod scheduler;
#[doc(hidden)]
pub mod __macro_support {
@@ -68,8 +71,28 @@
}
#[cxx::bridge]
pub mod nix_cxx {
+ struct AddFileToStoreResult {
+ error: String,
+ store_path: String,
+ hash: String,
+ }
+ struct CxxProfileGeneration {
+ id: u64,
+ store_path: String,
+ creation_time_unix: i64,
+ current: bool,
+ }
+ struct CxxListGenerationsResult {
+ error: String,
+ generations: Vec<CxxProfileGeneration>,
+ }
+ struct CxxBuildResult {
+ error: String,
+ outputs: Vec<String>,
+ }
unsafe extern "C++" {
type nix_fetchers_settings;
+ type Store;
include!("nix-eval/src/lib.hh");
#[allow(clippy::missing_safety_doc)]
@@ -78,6 +101,34 @@
setting: *const c_char,
value: *const c_char,
);
+
+ #[allow(clippy::missing_safety_doc)]
+ unsafe fn switch_profile(store: *mut Store, profile: &str, store_path: &str) -> String;
+
+ #[allow(clippy::missing_safety_doc)]
+ unsafe fn sign_closure(store: *mut Store, store_path: &str, key_file: &str) -> String;
+
+ #[allow(clippy::missing_safety_doc)]
+ unsafe fn add_file_to_store(
+ store: *mut Store,
+ name: &str,
+ path: &str,
+ ) -> AddFileToStoreResult;
+
+ fn list_generations(profile_path: &str) -> CxxListGenerationsResult;
+
+ #[allow(clippy::missing_safety_doc)]
+ unsafe fn build_drv_outputs(
+ store: *mut Store,
+ drv_path: &str,
+ output_names_joined: &str,
+ ) -> CxxBuildResult;
+
+ #[allow(clippy::missing_safety_doc)]
+ unsafe fn substitute_paths(store: *mut Store, paths_joined: &str) -> CxxBuildResult;
+
+ #[allow(clippy::missing_safety_doc)]
+ unsafe fn is_valid_path(store: *mut Store, path: &str) -> bool;
}
}
@@ -186,7 +237,7 @@
unsafe { set_err_msg(self.0, err as c_int, msg.as_ptr()) };
}
pub fn set_err(&mut self, err: anyhow::Error) {
- let mut fmt = format!("{err:?}").replace("\0", "\\0");
+ let fmt = format!("{err:?}").replace("\0", "\\0");
self.set_err_raw(
NixErrorKind::Generic,
&CString::new(fmt).expect("NUL bytes were just replaced"),
@@ -352,6 +403,125 @@
with_default_context(|c, _| unsafe { setting_set(c, s.as_ptr(), v.as_ptr()) }).map(|_| ())
}
+#[instrument(skip(dst))]
+pub fn copy_closure_to(dst: &Store, path: &Utf8Path) -> Result<()> {
+ let path_c = CString::new(path.as_str())?;
+ with_store_context(|c, src_store, _state| -> Result<()> {
+ let sp = unsafe { store_parse_path(c, src_store, path_c.as_ptr()) };
+ if sp.is_null() {
+ bail!("failed to parse store path {path}");
+ }
+ let rc = unsafe { store_copy_closure(c, src_store, dst.0, sp) };
+ unsafe { store_path_free(sp) };
+ if rc != nix_raw::err_NIX_OK {
+ bail!("store_copy_closure failed (code {rc})");
+ }
+ Ok(())
+ })?
+}
+
+#[instrument]
+pub fn switch_profile(profile: &str, store_path: &Utf8Path) -> Result<()> {
+ let msg = with_store_context(|_c, store, _state| unsafe {
+ nix_cxx::switch_profile(store.cast(), profile, store_path.as_str())
+ })?
+ .to_string();
+ if msg.is_empty() {
+ Ok(())
+ } else {
+ bail!("failed to switch profile {profile}: {msg}");
+ }
+}
+
+// TODO: fleet operator-managed key file
+#[instrument]
+pub fn sign_closure(store_path: &str, key_file: &str) -> Result<()> {
+ let msg = with_store_context(|_c, store, _state| unsafe {
+ nix_cxx::sign_closure(store.cast(), store_path, key_file)
+ })?
+ .to_string();
+ if msg.is_empty() {
+ Ok(())
+ } else {
+ bail!("failed to sign {store_path}: {msg}");
+ }
+}
+
+#[derive(Debug)]
+pub struct AddedFile {
+ pub store_path: Utf8PathBuf,
+ pub hash: String,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct ProfileGeneration {
+ pub id: u64,
+ pub store_path: Utf8PathBuf,
+ pub creation_time_unix: i64,
+ pub current: bool,
+}
+
+#[instrument]
+pub fn list_generations(profile_path: &str) -> Result<Vec<ProfileGeneration>> {
+ let res = nix_cxx::list_generations(profile_path);
+ if !res.error.is_empty() {
+ bail!(
+ "failed to list generations at {profile_path}: {}",
+ res.error
+ );
+ }
+ Ok(res
+ .generations
+ .into_iter()
+ .map(|g| ProfileGeneration {
+ id: g.id,
+ store_path: Utf8PathBuf::from(g.store_path),
+ creation_time_unix: g.creation_time_unix,
+ current: g.current,
+ })
+ .collect())
+}
+
+#[instrument]
+pub fn add_file_to_store(name: &str, path: &Utf8Path) -> Result<AddedFile> {
+ let res = with_store_context(|_c, store, _state| unsafe {
+ nix_cxx::add_file_to_store(store.cast(), name, path.as_str())
+ })?;
+ if !res.error.is_empty() {
+ bail!("failed to add {path} to store: {}", res.error);
+ }
+ Ok(AddedFile {
+ store_path: Utf8PathBuf::from(res.store_path),
+ hash: res.hash,
+ })
+}
+
+pub fn build_drv_outputs(drv_path: &str, output_names: &[String]) -> Result<Vec<String>> {
+ let joined = output_names.join("\n");
+ let res = with_store_context(|_c, store, _state| unsafe {
+ nix_cxx::build_drv_outputs(store.cast(), drv_path, &joined)
+ })?;
+ if !res.error.is_empty() {
+ bail!("build of {drv_path} failed: {}", res.error);
+ }
+ Ok(res.outputs)
+}
+
+pub fn substitute_paths(paths: &[String]) -> Result<Vec<String>> {
+ let joined = paths.join("\n");
+ let res = with_store_context(|_c, store, _state| unsafe {
+ nix_cxx::substitute_paths(store.cast(), &joined)
+ })?;
+ if !res.error.is_empty() {
+ warn!("substitute_paths reported: {}", res.error);
+ }
+ Ok(res.outputs)
+}
+
+pub fn is_valid_path(path: &str) -> Result<bool> {
+ with_store_context(|_c, store, _state| unsafe { nix_cxx::is_valid_path(store.cast(), path) })
+}
+
pub struct FetchSettings(*mut fetchers_settings);
impl FetchSettings {
pub fn new() -> Self {
@@ -450,17 +620,31 @@
unsafe { *user_data.cast::<String>() = s.to_owned() };
}
-struct Store(*mut c_store);
+pub struct Store(*mut c_store);
unsafe impl Send for Store {}
unsafe impl Sync for Store {}
impl Store {
+ pub fn open(uri: &str) -> Result<Self> {
+ let uri = CString::new(uri)?;
+ let ptr = with_default_context(|c, _| unsafe { store_open(c, uri.as_ptr(), null_mut()) })?;
+ if ptr.is_null() {
+ bail!("failed to open store");
+ }
+ Ok(Store(ptr))
+ }
+
fn parse_path(&self, path: &CStr) -> Result<StorePath> {
with_default_context(|c, _| {
StorePath(unsafe { store_parse_path(c, self.0, path.as_ptr()) })
})
}
}
+impl Drop for Store {
+ fn drop(&mut self) {
+ unsafe { store_free(self.0) }
+ }
+}
#[repr(transparent)]
pub struct EvalState(*mut c_eval_state);
@@ -858,7 +1042,7 @@
Ok(out)
}
#[instrument(name = "build", skip(self), fields(output))]
- pub fn build(&self, output: &str) -> Result<PathBuf> {
+ pub fn build(&self, output: &str) -> Result<Utf8PathBuf> {
if !self.is_derivation() {
bail!("expected derivation to build")
}
@@ -880,14 +1064,15 @@
.get_field("drvPath")
.context("getting drvPath")?
.to_string()?;
- let graph = drv::DrvGraph::resolve(&drv_path)?;
+ let graph = Arc::new(drv::DrvGraph::resolve(&drv_path)?);
let _guard = logging::register_build_graph(&Span::current(), &graph);
- // to_string here blocks until the path is built
+ scheduler::build_graph_sync(graph.clone(), vec![output.to_owned()])?;
+
let s = v.builtin_to_string()?;
let rs = s.to_realised_string()?;
let out_path = rs.as_str().to_owned();
- Ok(PathBuf::from(out_path))
+ Ok(Utf8PathBuf::from(out_path))
}
pub fn as_json<T: DeserializeOwned>(&self) -> Result<T> {
let to_json = Self::eval("builtins.toJSON")?;
crates/nix-eval/src/logging.ccdiffbeforeafterboth--- a/crates/nix-eval/src/logging.cc
+++ b/crates/nix-eval/src/logging.cc
@@ -96,7 +96,9 @@
extern "C" {
void apply_tracing_logger() {
- logger = std::make_unique<TracingLogger>();
+ auto old = logger;
+ logger = new TracingLogger();
+ delete old;
// verbosity = lvlVomit;
}
rust::Box<ErrorInfoBuilder>
crates/nix-eval/src/logging.rsdiffbeforeafterboth--- a/crates/nix-eval/src/logging.rs
+++ b/crates/nix-eval/src/logging.rs
@@ -499,7 +499,9 @@
} else if level == Level::INFO {
info!(target: "nix", "{}", s)
} else if level == Level::DEBUG {
- debug!(target: "nix", "{}", s)
+ if s != "querying info about missing paths" {
+ debug!(target: "nix", "{}", s)
+ }
} else {
trace!(target: "nix", "{}", s)
}
@@ -583,7 +585,9 @@
} else if level == Level::INFO {
info!(target: "nix", "{v}")
} else if level == Level::DEBUG {
- debug!(target: "nix", "{v}")
+ if v != "querying info about missing paths" {
+ debug!(target: "nix", "{v}")
+ }
} else {
trace!(target: "nix", "{v}")
}
crates/nix-eval/src/scheduler.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/nix-eval/src/scheduler.rs
@@ -0,0 +1,372 @@
+use std::collections::{HashMap, HashSet};
+use std::sync::Arc;
+
+use anyhow::{Context, Result, bail};
+use futures::stream::{FuturesUnordered, StreamExt};
+use tokio::sync::{Semaphore, broadcast};
+use tracing::{debug, info, instrument, warn};
+
+use crate::drv::DrvGraph;
+
+#[derive(Clone, Debug)]
+pub enum BuildEvent {
+ SubstitutePrepassStarted {
+ paths: usize,
+ },
+ SubstitutePrepassFinished {
+ satisfied: usize,
+ },
+ DrvStarted {
+ drv_path: String,
+ name: String,
+ wanted: Vec<String>,
+ },
+ DrvSkipped {
+ drv_path: String,
+ name: String,
+ },
+ DrvFinished {
+ drv_path: String,
+ name: String,
+ },
+ DrvFailed {
+ drv_path: String,
+ name: String,
+ error: String,
+ },
+ DrvCancelled {
+ drv_path: String,
+ name: String,
+ failed_dep: String,
+ },
+}
+
+pub struct Scheduler {
+ parallelism: usize,
+ events: broadcast::Sender<BuildEvent>,
+}
+
+impl Scheduler {
+ pub fn new(parallelism: usize) -> Self {
+ let parallelism = parallelism.max(1);
+ let (events, _) = broadcast::channel(1024);
+ Self {
+ parallelism,
+ events,
+ }
+ }
+
+ pub fn subscribe(&self) -> broadcast::Receiver<BuildEvent> {
+ self.events.subscribe()
+ }
+
+ #[instrument(name = "scheduler", skip(self, graph), fields(root = %graph.root, nodes = graph.nodes.len()))]
+ pub async fn run(&self, graph: Arc<DrvGraph>, root_outputs: Vec<String>) -> Result<()> {
+ let wanted = graph.wanted_outputs(&root_outputs);
+
+ self.substitute_prepass(&graph, &wanted).await?;
+ self.build_topo(&graph, wanted).await
+ }
+
+ async fn substitute_prepass(
+ &self,
+ graph: &DrvGraph,
+ wanted: &HashMap<String, Vec<String>>,
+ ) -> Result<()> {
+ let paths = collect_substitute_paths(graph, wanted);
+ if paths.is_empty() {
+ return Ok(());
+ }
+ let _ = self
+ .events
+ .send(BuildEvent::SubstitutePrepassStarted { paths: paths.len() });
+ debug!("substitute pre-pass: {} paths", paths.len());
+
+ let satisfied = tokio::task::spawn_blocking(move || crate::substitute_paths(&paths))
+ .await
+ .expect("substitute pre-pass task should not panic")?;
+
+ let _ = self.events.send(BuildEvent::SubstitutePrepassFinished {
+ satisfied: satisfied.len(),
+ });
+ Ok(())
+ }
+
+ async fn build_topo(
+ &self,
+ graph: &Arc<DrvGraph>,
+ wanted: HashMap<String, Vec<String>>,
+ ) -> Result<()> {
+ let mut indeg: HashMap<String, usize> = graph
+ .nodes
+ .iter()
+ .map(|(k, n)| (k.clone(), n.input_drvs.len()))
+ .collect();
+ let mut dependents: HashMap<String, Vec<String>> = HashMap::new();
+ for (path, node) in &graph.nodes {
+ for dep in node.input_drvs.keys() {
+ dependents
+ .entry(dep.clone())
+ .or_default()
+ .push(path.clone());
+ }
+ }
+
+ let sem = Arc::new(Semaphore::new(self.parallelism));
+ let mut ready: Vec<String> = indeg
+ .iter()
+ .filter(|(_, d)| **d == 0)
+ .map(|(k, _)| k.clone())
+ .collect();
+ let mut in_flight = FuturesUnordered::new();
+ let mut failed: HashMap<String, String> = HashMap::new();
+ // Tainted = transitively depends on a failed drv
+ let mut tainted: HashMap<String, String> = HashMap::new();
+
+ loop {
+ let batch: Vec<String> = std::mem::take(&mut ready);
+ for path in batch {
+ if let Some(failed_dep) = tainted.get(&path) {
+ let name = graph
+ .nodes
+ .get(&path)
+ .map(|n| n.name.clone())
+ .unwrap_or_default();
+ let _ = self.events.send(BuildEvent::DrvCancelled {
+ drv_path: path.clone(),
+ name,
+ failed_dep: failed_dep.clone(),
+ });
+ propagate_done(&dependents, &mut indeg, &mut ready, &path);
+ continue;
+ }
+
+ let sem = sem.clone();
+ let events = self.events.clone();
+ let graph = graph.clone();
+ let wanted_here = wanted.get(&path).cloned().unwrap_or_default();
+ in_flight.push(tokio::spawn(async move {
+ let _permit = sem.acquire_owned().await.expect("semaphore not closed");
+ let node = graph
+ .nodes
+ .get(&path)
+ .expect("ready node must be in graph")
+ .clone();
+ let name = node.name.clone();
+
+ let all_valid = !wanted_here.is_empty()
+ && wanted_here.iter().all(|o| {
+ node.outputs
+ .get(o)
+ .map(|p| crate::is_valid_path(p).unwrap_or(false))
+ .unwrap_or(false)
+ });
+ if all_valid {
+ let _ = events.send(BuildEvent::DrvSkipped {
+ drv_path: path.clone(),
+ name: name.clone(),
+ });
+ return (path, name, Ok::<(), anyhow::Error>(()));
+ }
+
+ let _ = events.send(BuildEvent::DrvStarted {
+ drv_path: path.clone(),
+ name: name.clone(),
+ wanted: wanted_here.clone(),
+ });
+
+ let path_for_build = path.clone();
+ let res = tokio::task::spawn_blocking(move || {
+ crate::build_drv_outputs(&path_for_build, &wanted_here)
+ })
+ .await
+ .expect("build task should not panic");
+
+ match res {
+ Ok(_) => {
+ let _ = events.send(BuildEvent::DrvFinished {
+ drv_path: path.clone(),
+ name: name.clone(),
+ });
+ (path, name, Ok(()))
+ }
+ Err(e) => {
+ let msg = format!("{e:#}");
+ let _ = events.send(BuildEvent::DrvFailed {
+ drv_path: path.clone(),
+ name: name.clone(),
+ error: msg,
+ });
+ (path, name, Err(e))
+ }
+ }
+ }));
+ }
+
+ let Some(joined) = in_flight.next().await else {
+ break;
+ };
+ let (finished, _name, res) = match joined {
+ Ok(t) => t,
+ Err(e) => bail!("scheduler task panicked: {e}"),
+ };
+ match res {
+ Ok(()) => {
+ propagate_done(&dependents, &mut indeg, &mut ready, &finished);
+ }
+ Err(e) => {
+ failed.insert(finished.clone(), format!("{e:#}"));
+ mark_tainted(&dependents, &finished, &mut tainted);
+ propagate_done(&dependents, &mut indeg, &mut ready, &finished);
+ }
+ }
+ }
+
+ let stuck: Vec<_> = indeg
+ .iter()
+ .filter(|(_, d)| **d != 0)
+ .map(|(k, _)| k.as_str())
+ .collect();
+ if !stuck.is_empty() {
+ warn!(
+ "scheduler finished with {} nodes still pending (loop?)",
+ stuck.len()
+ );
+ }
+
+ if failed.is_empty() {
+ info!("scheduler completed");
+ Ok(())
+ } else {
+ let mut report = format!("{} drv(s) failed to build:", failed.len());
+ let mut sorted: Vec<_> = failed.iter().collect();
+ sorted.sort_by(|a, b| a.0.cmp(b.0));
+ for (path, err) in sorted {
+ let name = graph
+ .nodes
+ .get(path)
+ .map(|n| n.name.as_str())
+ .unwrap_or("?");
+ let chain = path_to_root(graph, path);
+ report.push_str(&format!(
+ "\n\n {name} ({path}):\n {err}\n needed by: {}",
+ chain.join(" => "),
+ ));
+ }
+ Err(anyhow::anyhow!(report))
+ }
+ }
+}
+
+fn propagate_done(
+ dependents: &HashMap<String, Vec<String>>,
+ indeg: &mut HashMap<String, usize>,
+ ready: &mut Vec<String>,
+ finished: &str,
+) {
+ if let Some(deps) = dependents.get(finished) {
+ for d in deps {
+ let entry = indeg.get_mut(d).expect("dependent must have indeg");
+ *entry = entry.saturating_sub(1);
+ if *entry == 0 {
+ ready.push(d.clone());
+ }
+ }
+ }
+}
+
+fn mark_tainted(
+ dependents: &HashMap<String, Vec<String>>,
+ failed: &str,
+ tainted: &mut HashMap<String, String>,
+) {
+ let mut queue: Vec<String> = dependents.get(failed).cloned().unwrap_or_default();
+ while let Some(node) = queue.pop() {
+ if tainted
+ .entry(node.clone())
+ .or_insert_with(|| failed.to_owned())
+ == failed
+ {
+ if let Some(deps) = dependents.get(&node) {
+ for d in deps {
+ if !tainted.contains_key(d) {
+ queue.push(d.clone());
+ }
+ }
+ }
+ }
+ }
+}
+
+fn path_to_root(graph: &DrvGraph, from: &str) -> Vec<String> {
+ let mut dependents: HashMap<&str, Vec<&str>> = HashMap::new();
+ for (path, node) in &graph.nodes {
+ for dep in node.input_drvs.keys() {
+ dependents
+ .entry(dep.as_str())
+ .or_default()
+ .push(path.as_str());
+ }
+ }
+
+ let mut chain: Vec<String> = vec![node_name(graph, from)];
+ let mut cur = from;
+ let mut seen: HashSet<&str> = HashSet::new();
+ seen.insert(cur);
+ while cur != graph.root.as_str() {
+ let Some(next) = dependents.get(cur).and_then(|v| v.first().copied()) else {
+ break;
+ };
+ if !seen.insert(next) {
+ break;
+ }
+ chain.push(node_name(graph, next));
+ cur = next;
+ }
+ chain
+}
+
+fn node_name(graph: &DrvGraph, path: &str) -> String {
+ graph
+ .nodes
+ .get(path)
+ .map(|n| n.name.clone())
+ .unwrap_or_else(|| path.to_owned())
+}
+
+fn collect_substitute_paths(
+ graph: &DrvGraph,
+ wanted: &HashMap<String, Vec<String>>,
+) -> Vec<String> {
+ let mut paths: HashSet<String> = HashSet::new();
+ for node in graph.nodes.values() {
+ for src in &node.input_srcs {
+ paths.insert(src.clone());
+ }
+ }
+ for (path, outs) in wanted {
+ let Some(node) = graph.nodes.get(path) else {
+ continue;
+ };
+ for o in outs {
+ if let Some(p) = node.outputs.get(o) {
+ paths.insert(p.clone());
+ }
+ }
+ }
+ let mut v: Vec<_> = paths.into_iter().collect();
+ v.sort();
+ v
+}
+
+// TODO: Parallelism as a metric works poorly with multiple machines, but I haven't thought about bringing
+// hercy here yet. In case of remote machines - they will handle parallelism on their own, and this one
+// will work as a hard cap.
+pub fn build_graph_sync(graph: Arc<DrvGraph>, root_outputs: Vec<String>) -> Result<()> {
+ let parallelism = std::thread::available_parallelism()
+ .map(|p| p.get())
+ .unwrap_or(4);
+ let scheduler = Scheduler::new(parallelism);
+ crate::await_in_nix(async move { scheduler.run(graph, root_outputs).await })
+ .context("scheduler run")
+}
crates/nixlike/Cargo.tomldiffbeforeafterboth--- a/crates/nixlike/Cargo.toml
+++ b/crates/nixlike/Cargo.toml
@@ -11,5 +11,3 @@
linked-hash-map.workspace = true
peg.workspace = true
serde.workspace = true
-serde-transcode.workspace = true
-serde_json.workspace = true
crates/remowt-fleet/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/crates/remowt-fleet/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "remowt-fleet"
+description = "Remowt endpoints for fleet"
+version.workspace = true
+edition = "2021"
+
+[dependencies]
+bifrostlink.workspace = true
+
+remowt-client.workspace = true
+remowt-endpoints.workspace = true
+
+anyhow.workspace = true
+camino.workspace = true
+nix-eval.workspace = true
+serde = { workspace = true }
+thiserror.workspace = true
+tokio = { workspace = true, features = ["io-util", "net", "process", "rt"] }
+tracing.workspace = true
+uuid.workspace = true
crates/remowt-fleet/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/remowt-fleet/src/lib.rs
@@ -0,0 +1,120 @@
+use std::path::PathBuf;
+
+use anyhow::{Context as _, Result};
+use bifrostlink::Config;
+use bifrostlink::declarative::endpoints;
+use camino::Utf8PathBuf;
+use remowt_client::Remowt;
+use remowt_endpoints::nix_daemon::NixDaemonClient;
+use serde::{Deserialize, Serialize};
+use tokio::net::UnixListener;
+use tracing::error;
+
+pub struct Nix;
+pub use nix_eval::{init_libraries, init_tokio_for_nix};
+
+#[derive(Serialize, Deserialize, Debug, thiserror::Error)]
+pub enum NixError {
+ #[error("nix daemon unavailable: {0}")]
+ DaemonUnavailable(String),
+ #[error("tunnel socket unavailable: {0}")]
+ Tunnel(String),
+ #[error("profile switch failed: {0}")]
+ Profile(String),
+ #[error("signing failed: {0}")]
+ Sign(String),
+ #[error("listing generations failed: {0}")]
+ ListGenerations(String),
+}
+
+#[endpoints(ns = 91)]
+impl Nix {
+ #[endpoints(id = 3)]
+ async fn switch_profile(
+ &self,
+ profile: String,
+ store_path: Utf8PathBuf,
+ ) -> Result<(), NixError> {
+ tokio::task::spawn_blocking(move || nix_eval::switch_profile(&profile, &store_path))
+ .await
+ .map_err(|e| NixError::Profile(e.to_string()))?
+ .map_err(|e| NixError::Profile(e.to_string()))
+ }
+
+ #[endpoints(id = 4)]
+ async fn sign_closure(
+ &self,
+ store_path: Utf8PathBuf,
+ key_file: Utf8PathBuf,
+ ) -> Result<(), NixError> {
+ tokio::task::spawn_blocking(move || {
+ nix_eval::sign_closure(store_path.as_str(), key_file.as_str())
+ })
+ .await
+ .map_err(|e| NixError::Sign(e.to_string()))?
+ .map_err(|e| NixError::Sign(e.to_string()))
+ }
+
+ #[endpoints(id = 5)]
+ async fn list_generations(
+ &self,
+ profile: String,
+ ) -> Result<Vec<nix_eval::ProfileGeneration>, NixError> {
+ tokio::task::spawn_blocking(move || {
+ nix_eval::list_generations(&format!("/nix/var/nix/profiles/{profile}"))
+ })
+ .await
+ .map_err(|e| NixError::ListGenerations(e.to_string()))?
+ .map_err(|e| NixError::ListGenerations(e.to_string()))
+ }
+}
+
+pub async fn nix_store_socket(conn: Remowt, store: &str) -> Result<PathBuf> {
+ let store = store.to_owned();
+ let path = std::env::temp_dir().join(format!("fleet-nix-{}.sock", uuid::Uuid::new_v4()));
+ let _ = std::fs::remove_file(&path);
+ let listener = UnixListener::bind(&path)?;
+ tokio::spawn(async move {
+ if let Err(e) = serve(conn, listener, store).await {
+ error!("nix daemon proxy failed: {e}");
+ }
+ });
+ Ok(path)
+}
+
+async fn serve(conn: Remowt, listener: UnixListener, store: String) -> Result<()> {
+ let nix = conn.endpoints::<NixDaemonClient<_>>();
+ loop {
+ let (mut local, _) = listener.accept().await?;
+
+ let (rx, remote_sock) = match conn.bind_runtime_unix("nix-daemon").await {
+ Ok(rx) => rx,
+ Err(e) => {
+ error!("streamlocal_forward failed: {e}");
+ continue;
+ }
+ };
+ let sock_str = remote_sock.as_str().to_owned();
+ match nix.serve_store(store.clone(), sock_str).await {
+ Ok(Ok(())) => {}
+ Ok(Err(e)) => {
+ error!("nix bridge: {e}");
+ continue;
+ }
+ Err(e) => {
+ error!("nix bridge rpc failed: {e}");
+ continue;
+ }
+ }
+
+ let mut channel = rx
+ .accept()
+ .await
+ .context("failed to accept remote nix connection")?;
+ tokio::spawn(async move {
+ if let Err(e) = tokio::io::copy_bidirectional(&mut local, &mut channel).await {
+ tracing::debug!("nix tunnel ended: {e}");
+ }
+ });
+ }
+}
flake.lockdiffbeforeafterboth--- a/flake.lock
+++ b/flake.lock
@@ -2,10 +2,10 @@
"nodes": {
"crane": {
"locked": {
- "lastModified": 1773189535,
+ "lastModified": 1780532242,
"owner": "ipetkov",
"repo": "crane",
- "rev": "6fa2fb4cf4a89ba49fc9dd5a3eb6cde99d388269",
+ "rev": "59a82a1222dd3b2080b5cc52a1a2e8d5f1b77f37",
"type": "github"
},
"original": {
@@ -37,10 +37,10 @@
]
},
"locked": {
- "lastModified": 1772408722,
+ "lastModified": 1778716662,
"owner": "hercules-ci",
"repo": "flake-parts",
- "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
+ "rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
"type": "github"
},
"original": {
@@ -62,10 +62,10 @@
]
},
"locked": {
- "lastModified": 1759080490,
+ "lastModified": 1780160585,
"owner": "CertainLach",
"repo": "fleet-tf",
- "rev": "878bd8c23933d628bf750378bbe527b841901c3d",
+ "rev": "aa2200a3f8f93a8c0d3b87bb29f11d9d9b0a23e6",
"type": "github"
},
"original": {
@@ -111,10 +111,10 @@
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
- "lastModified": 1768702010,
+ "lastModified": 1781448983,
"owner": "deltarocks",
"repo": "nix",
- "rev": "b05b52670b9c7affff5b9be3edb539a1603c39e6",
+ "rev": "bb8784f285658e77642437409824619f5c34a854",
"type": "github"
},
"original": {
@@ -126,10 +126,10 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1773268153,
+ "lastModified": 1781402740,
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "63ca4f465b79edbaa9ff113ea7ff48fb49ea0db0",
+ "rev": "49145c5aba740948d6da1265f584826bd27619ad",
"type": "github"
},
"original": {
@@ -171,6 +171,34 @@
"type": "github"
}
},
+ "remowt-agents": {
+ "inputs": {
+ "crane": [
+ "crane"
+ ],
+ "flake-parts": [
+ "flake-parts"
+ ],
+ "nixpkgs": [
+ "nixpkgs"
+ ],
+ "rust-overlay": "rust-overlay",
+ "shelly": [
+ "shelly"
+ ]
+ },
+ "locked": {
+ "lastModified": 1781471358,
+ "rev": "c69dddc33f8e2081ef685ae20a7278f92cfcd32e",
+ "revCount": 37,
+ "type": "git",
+ "url": "file:/home/lach/build/remowt-agents"
+ },
+ "original": {
+ "type": "git",
+ "url": "file:/home/lach/build/remowt-agents"
+ }
+ },
"root": {
"inputs": {
"crane": "crane",
@@ -178,7 +206,8 @@
"fleet-tf": "fleet-tf",
"nix": "nix",
"nixpkgs": "nixpkgs",
- "rust-overlay": "rust-overlay",
+ "remowt-agents": "remowt-agents",
+ "rust-overlay": "rust-overlay_2",
"shelly": "shelly",
"treefmt-nix": "treefmt-nix"
}
@@ -186,14 +215,15 @@
"rust-overlay": {
"inputs": {
"nixpkgs": [
+ "remowt-agents",
"nixpkgs"
]
},
"locked": {
- "lastModified": 1773216618,
+ "lastModified": 1769309768,
"owner": "oxalica",
"repo": "rust-overlay",
- "rev": "07d7dc6fcc5eae76b4fb0e19d4afd939437bec97",
+ "rev": "140c9dc582cb73ada2d63a2180524fcaa744fad5",
"type": "github"
},
"original": {
@@ -202,6 +232,25 @@
"type": "github"
}
},
+ "rust-overlay_2": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1781320681,
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "rev": "5b929d8c854149d926d05ea0cd6469bf4e54db27",
+ "type": "github"
+ },
+ "original": {
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "type": "github"
+ }
+ },
"shelly": {
"locked": {
"lastModified": 1756323923,
@@ -223,10 +272,10 @@
]
},
"locked": {
- "lastModified": 1772660329,
+ "lastModified": 1780220602,
"owner": "numtide",
"repo": "treefmt-nix",
- "rev": "3710e0e1218041bbad640352a0440114b1e10428",
+ "rev": "db947814a175b7ca6ded66e21383d938df01c227",
"type": "github"
},
"original": {
flake.nixdiffbeforeafterboth--- a/flake.nix
+++ b/flake.nix
@@ -23,6 +23,13 @@
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
+ remowt-agents = {
+ url = "git+file:/home/lach/build/remowt-agents";
+ inputs.nixpkgs.follows = "nixpkgs";
+ inputs.flake-parts.follows = "flake-parts";
+ inputs.crane.follows = "crane";
+ inputs.shelly.follows = "shelly";
+ };
# DeterminateSystem's nix fork is controversial, but I don't mind it,
# and it has lazy-trees support which is useful for fleet.
nix = {
@@ -147,7 +154,7 @@
packages = lib.mkIf deployerSystem (
let
packages = pkgs.callPackages ./pkgs {
- inherit craneLib inputs';
+ inherit craneLib inputs;
};
in
packages // { default = packages.fleet; }
lib/flakePart.nixdiffbeforeafterboth--- a/lib/flakePart.nix
+++ b/lib/flakePart.nix
@@ -57,7 +57,7 @@
modules = (import ../modules/module-list.nix) ++ [
module
(
- { inputs', ... }:
+ { inputs, ... }:
{
config = {
data = if isPath data then import data else data;
@@ -66,12 +66,13 @@
(final: prev: {
inherit
(import ../pkgs {
- inherit (prev) callPackage;
- inherit inputs';
+ inherit (final) callPackage;
+ inherit inputs;
craneLib = crane.mkLib prev;
})
fleet-install-secrets
fleet-generator-helper
+ remowt-plugin-fleet
;
})
];
modules/nixpkgs.nixdiffbeforeafterboth--- a/modules/nixpkgs.nix
+++ b/modules/nixpkgs.nix
@@ -42,10 +42,12 @@
default = config.nixpkgs.buildUsing;
defaultText = literalExpression "config.nixpkgs.buildUsing";
};
- config.nixos = {
- inherit _file;
- nixpkgs.overlays = config.nixpkgs.overlays;
- };
+ config.nixos =
+ { inputs', ... }:
+ {
+ inherit _file;
+ nixpkgs.overlays = config.nixpkgs.overlays;
+ };
};
};
}
pkgs/default.nixdiffbeforeafterboth--- a/pkgs/default.nix
+++ b/pkgs/default.nix
@@ -1,10 +1,11 @@
{
callPackage,
craneLib,
- inputs',
+ inputs,
}:
{
- fleet = callPackage ./fleet.nix { inherit craneLib inputs'; };
+ fleet = callPackage ./fleet.nix { inherit craneLib inputs; };
+ remowt-plugin-fleet = callPackage ./remowt-plugin-fleet.nix { inherit craneLib inputs; };
fleet-install-secrets = callPackage ./fleet-install-secrets.nix { inherit craneLib; };
fleet-generator-helper = callPackage ./fleet-generator-helper.nix { inherit craneLib; };
}
pkgs/fleet.nixdiffbeforeafterboth--- a/pkgs/fleet.nix
+++ b/pkgs/fleet.nix
@@ -2,10 +2,16 @@
lib,
craneLib,
installShellFiles,
- inputs',
+ inputs,
+
+ stdenv,
pkg-config,
rustPlatform,
+ rofi,
}:
+let
+ system = stdenv.hostPlatform.system;
+in
craneLib.buildPackage rec {
pname = "fleet";
src = lib.cleanSourceWith {
@@ -20,10 +26,15 @@
cargoExtraArgs = "--locked -p ${pname}";
+ REMOWT_AGENTS_DIR = "${inputs.remowt-agents.packages.${system}.remowt-agents}";
+ # TODO: built-in fleet prompter should be a prodash widget, or it should require
+ # tty remowt prompter running on host machine idk.
+ ROFI = "${rofi}/bin/rofi";
+
buildInputs = [
- inputs'.nix.packages.nix-expr-c
- inputs'.nix.packages.nix-flake-c
- inputs'.nix.packages.nix-fetchers-c
+ inputs.nix.packages.${system}.nix-expr-c
+ inputs.nix.packages.${system}.nix-flake-c
+ inputs.nix.packages.${system}.nix-fetchers-c
];
nativeBuildInputs = [
installShellFiles
pkgs/remowt-plugin-fleet.nixdiffbeforeafterboth--- /dev/null
+++ b/pkgs/remowt-plugin-fleet.nix
@@ -0,0 +1,36 @@
+{
+ lib,
+ craneLib,
+ inputs,
+
+ stdenv,
+ pkg-config,
+ rustPlatform,
+}:
+let
+ system = stdenv.hostPlatform.system;
+in
+craneLib.buildPackage rec {
+ pname = "remowt-plugin-fleet";
+ src = lib.cleanSourceWith {
+ src = ../.;
+ filter =
+ path: type:
+ (lib.hasSuffix "\.cc" path)
+ || (lib.hasSuffix "\.hh" path)
+ || (craneLib.filterCargoSources path type);
+ };
+ strictDeps = true;
+
+ cargoExtraArgs = "--locked -p ${pname}";
+
+ buildInputs = [
+ inputs.nix.packages.${system}.nix-expr-c
+ inputs.nix.packages.${system}.nix-flake-c
+ inputs.nix.packages.${system}.nix-fetchers-c
+ ];
+ nativeBuildInputs = [
+ pkg-config
+ rustPlatform.bindgenHook
+ ];
+}