diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4c016d4..b2de2ed 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,3 +1,4 @@ +--- name: "Build Packages" on: pull_request: @@ -23,9 +24,15 @@ jobs: if: needs.pre-job.outputs.should_skip != 'true' steps: - uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 - uses: cachix/install-nix-action@v31 with: nix_path: nixpkgs=channel:nixos-unstable + extra_nix_config: | + extra-platforms = aarch64-linux i686-linux - uses: cachix/cachix-action@v16 with: name: wires diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index d401ec1..89d7c09 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -1,3 +1,4 @@ +--- name: "PR Preview" on: push: @@ -35,9 +36,15 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ needs.base-ref.outputs.base-ref }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 - uses: cachix/install-nix-action@v31 with: nix_path: nixpkgs=channel:nixos-unstable + extra_nix_config: | + extra-platforms = aarch64-linux i686-linux - uses: cachix/cachix-action@v16 with: name: wires @@ -74,9 +81,15 @@ jobs: if: needs.eval-head.outputs.drv != needs.eval-base.outputs.drv steps: - uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 - uses: cachix/install-nix-action@v31 with: nix_path: nixpkgs=channel:nixos-unstable + extra_nix_config: | + extra-platforms = aarch64-linux i686-linux - uses: cachix/cachix-action@v16 with: name: wires diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9492f44..4ea688e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,3 +1,4 @@ +--- name: "Test" on: pull_request: @@ -91,18 +92,18 @@ jobs: matrix: test: ${{ fromJSON(needs.find-vm-tests.outputs.tests) }} steps: - - run: | - sudo rm -rf /usr/share/dotnet - sudo rm -rf /usr/local/lib/android - sudo rm -rf /opt/ghc - sudo rm -rf /opt/hostedtoolcache/CodeQL - sudo docker image prune --all --force - uses: actions/checkout@v4 + - name: QEMU static binaries + run: sudo apt-get update && sudo apt-get -y --no-install-recommends install qemu-user-static + - uses: wimpysworld/nothing-but-nix@main + - uses: cachix/install-nix-action@v31 with: nix_path: nixpkgs=channel:nixos-unstable enable_kvm: true - extra_nix_config: "system-features = nixos-test benchmark big-parallel kvm" + extra_nix_config: | + system-features = nixos-test benchmark big-parallel kvm + extra-platforms = aarch64-linux i686-linux - uses: cachix/cachix-action@v16 with: name: wires diff --git a/Cargo.lock b/Cargo.lock index 8da8676..7bf4904 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,32 @@ version = 4 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "agent" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "nix", + "prost 0.13.5", + "prost-build", + "tokio", + "tracing", + "tracing-subscriber", +] [[package]] name = "aho-corasick" @@ -28,9 +42,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -49,30 +63,31 @@ checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell", + "windows-sys 0.59.0", ] [[package]] @@ -83,9 +98,9 @@ checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-trait" @@ -93,30 +108,30 @@ version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -127,9 +142,9 @@ checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bitmaps" @@ -164,15 +179,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.6.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - -[[package]] -name = "cc" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47de7e88bbbd467951ae7f5a6f34f70d1b4d9cfce53d5fd70f74ebe118b3db56" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cfg-if" @@ -188,9 +197,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", @@ -226,9 +235,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -252,8 +261,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck 0.5.0", - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] @@ -265,21 +274,21 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "console" -version = "0.15.8" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", - "lazy_static", "libc", - "unicode-width 0.1.13", - "windows-sys 0.52.0", + "once_cell", + "unicode-width 0.2.0", + "windows-sys 0.59.0", ] [[package]] @@ -290,13 +299,13 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "derive_more" -version = "0.99.18" +version = "0.99.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" dependencies = [ "convert_case", - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "rustc_version", "syn 2.0.100", ] @@ -319,15 +328,15 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "enum-display-derive" @@ -335,16 +344,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f16ef37b2a9b242295d61a154ee91ae884afff6b8b933b486b12481cc58310ca" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 1.0.109", ] [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", @@ -361,9 +370,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fixedbitset" @@ -431,8 +440,8 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] @@ -472,15 +481,27 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed7131e57abbde63513e0e6636f76668a1ca9798dcae2df4e283cae9ee83859e" dependencies = [ - "rustix 1.0.3", + "rustix", "windows-targets", ] +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "heck" @@ -537,9 +558,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -561,9 +582,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" @@ -575,17 +596,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "key_agent" -version = "0.1.0" -dependencies = [ - "anyhow", - "nix", - "prost 0.13.5", - "prost-build", - "tokio", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -596,12 +606,12 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" name = "lib" version = "0.1.0" dependencies = [ + "agent", "async-trait", "derive_more", "futures", "gethostname", "im", - "key_agent", "prost 0.13.5", "regex", "serde", @@ -617,21 +627,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.171" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "lock_api" @@ -645,9 +649,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "logos" @@ -666,8 +670,8 @@ checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" dependencies = [ "beef", "fnv", - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "regex-syntax 0.6.29", "syn 1.0.109", ] @@ -680,18 +684,18 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mintex" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07" +checksum = "c505b3e17ed6b70a7ed2e67fbb2c560ee327353556120d6e72f5232b6880d536" [[package]] name = "mio" @@ -700,7 +704,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -749,18 +753,18 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.36.1" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "overload" @@ -802,9 +806,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -814,9 +818,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" [[package]] name = "proc-macro-error" @@ -825,8 +829,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 1.0.109", "version_check", ] @@ -837,8 +841,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "version_check", ] @@ -853,9 +857,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -877,7 +881,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ - "bytes 1.6.0", + "bytes 1.10.1", "prost-derive 0.13.5", ] @@ -920,8 +924,8 @@ checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", "itertools 0.14.0", - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] @@ -946,13 +950,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ - "proc-macro2 1.0.94", + "proc-macro2 1.0.95", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand_core" version = "0.6.4" @@ -970,9 +980,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags", ] @@ -1026,44 +1036,31 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys 0.4.14", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustix" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys 0.9.3", + "linux-raw-sys", "windows-sys 0.59.0", ] [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "scopeguard" @@ -1073,9 +1070,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" @@ -1104,8 +1101,8 @@ checksum = "350922b83e64ef1ac841b6c47a95d6cc1677735e5cad058eac0fb32e80796122" dependencies = [ "logos", "proc-macro-error", - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 1.0.109", ] @@ -1116,7 +1113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c56cc536c2da20c38f9c134d5a313e2b996f63fcc0540d25d3d3daeb1d04bb8f" dependencies = [ "proc-macro-error", - "quote 1.0.36", + "quote 1.0.40", "serde-query-core", "syn 1.0.109", ] @@ -1127,8 +1124,8 @@ version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] @@ -1150,8 +1147,8 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] @@ -1166,9 +1163,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -1194,15 +1191,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1231,8 +1228,8 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "unicode-ident", ] @@ -1242,41 +1239,41 @@ version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "unicode-ident", ] [[package]] name = "tempfile" -version = "3.12.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "cfg-if", "fastrand", + "getrandom", "once_cell", - "rustix 0.38.37", + "rustix", "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] @@ -1303,7 +1300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", - "bytes 1.6.0", + "bytes 1.10.1", "libc", "mio", "parking_lot", @@ -1320,8 +1317,8 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] @@ -1342,8 +1339,8 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", ] @@ -1396,15 +1393,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-segmentation" @@ -1414,9 +1411,9 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" @@ -1438,15 +1435,15 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vt100" @@ -1456,7 +1453,7 @@ checksum = "84cd863bf0db7e392ba3bd04994be3473491b31e66340672af5d11943c6274de" dependencies = [ "itoa", "log", - "unicode-width 0.1.13", + "unicode-width 0.1.14", "vte", ] @@ -1477,8 +1474,8 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", ] [[package]] @@ -1487,6 +1484,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -1506,8 +1512,8 @@ checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", "wasm-bindgen-shared", ] @@ -1518,7 +1524,7 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ - "quote 1.0.36", + "quote 1.0.40", "wasm-bindgen-macro-support", ] @@ -1528,8 +1534,8 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ - "proc-macro2 1.0.94", - "quote 1.0.36", + "proc-macro2 1.0.95", + "quote 1.0.40", "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -1693,3 +1699,12 @@ dependencies = [ "tracing-log", "tracing-subscriber", ] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] diff --git a/Cargo.toml b/Cargo.toml index a7d2ff9..422c454 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["wire/key_agent", "wire/lib", "wire/cli"] +members = ["wire/agent", "wire/lib", "wire/cli"] resolver = "2" package.edition = "2021" package.version = "0.1.0" diff --git a/flake.nix b/flake.nix index b87e407..9962855 100644 --- a/flake.nix +++ b/flake.nix @@ -29,7 +29,7 @@ ./nix/shells.nix ./nix/checks.nix ./wire/cli - ./wire/key_agent + ./wire/agent ./doc ./tests/nix ]; diff --git a/justfile b/justfile index bfd00a7..445f5a6 100644 --- a/justfile +++ b/justfile @@ -4,4 +4,4 @@ build-dhat: cargo build --profile profiling --features dhat-heap @echo 'dhat binaries in target/profiling' @echo 'Example:' - @echo 'WIRE_RUNTIME=/nix/store/...-runtime WIRE_KEY_AGENT=/nix/store/...-key_agent-0.1.0 PROJECT/target/profiling/wire apply ...' + @echo 'WIRE_RUNTIME=/nix/store/...-runtime WIRE_AGENT=/nix/store/...-agent-0.1.0 PROJECT/target/profiling/wire apply ...' diff --git a/runtime/evaluate.nix b/runtime/evaluate.nix index e090fb9..733d86c 100644 --- a/runtime/evaluate.nix +++ b/runtime/evaluate.nix @@ -71,6 +71,13 @@ rec { inspect = { inherit path; - nodes = builtins.mapAttrs (_: v: v.config.deployment) nodes; + nodes = builtins.mapAttrs ( + _: v: + v.config.deployment + // { + # Necessary for the agent so it can know what architecture it should push to + inherit (v.config.nixpkgs.hostPlatform) system; + } + ) nodes; }; } diff --git a/wire/key_agent/Cargo.toml b/wire/agent/Cargo.toml similarity index 66% rename from wire/key_agent/Cargo.toml rename to wire/agent/Cargo.toml index 068fabb..28b207e 100644 --- a/wire/key_agent/Cargo.toml +++ b/wire/agent/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "key_agent" +name = "agent" edition.workspace = true version.workspace = true @@ -8,6 +8,9 @@ tokio = { workspace = true } anyhow = { workspace = true } prost = { workspace = true } nix = { version = "0.29.0", features = ["user"] } +clap = { workspace = true, features = ["derive"] } +tracing.workspace = true +tracing-subscriber.workspace = true [build-dependencies] prost-build = "0.5" diff --git a/wire/agent/build.rs b/wire/agent/build.rs new file mode 100644 index 0000000..0bbe292 --- /dev/null +++ b/wire/agent/build.rs @@ -0,0 +1,3 @@ +fn main() { + prost_build::compile_protos(&["src/models.proto"], &["src/"]).unwrap(); +} diff --git a/wire/agent/default.nix b/wire/agent/default.nix new file mode 100644 index 0000000..a8c6b90 --- /dev/null +++ b/wire/agent/default.nix @@ -0,0 +1,26 @@ +{ + config, + withSystem, + lib, + ... +}: +{ + + flake.packages = + # macos is not supported with the agent + lib.genAttrs (builtins.filter (system: !lib.hasSuffix "darwin" system) config.systems) + + ( + system: + withSystem system ( + { buildRustProgram, ... }: + { + agent = buildRustProgram { + name = "agent"; + pname = "agent"; + cargoExtraArgs = "-p agent"; + }; + } + ) + ); +} diff --git a/wire/agent/src/cli.rs b/wire/agent/src/cli.rs new file mode 100644 index 0000000..48a53d0 --- /dev/null +++ b/wire/agent/src/cli.rs @@ -0,0 +1,55 @@ +use std::{path::PathBuf, str::FromStr, time::Duration}; + +use anyhow::bail; +use clap::{Parser, Subcommand}; + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct Time(pub Duration); + +#[derive(Subcommand, Debug)] +pub enum Operations { + #[command()] + /// Push keys + PushKeys { + #[arg(short, long)] + /// Total length for the protobuf message + length: usize, + }, + #[command()] + /// Initiate magic rollback session + Rollback { + // Waiting period before transitioning to the timeout phase, where the + // agent awaits a response from wire. + // + /// Grace period + grace_period: Time, + // The waiting period to receive a response from wire, if the time + // exceeds the specified value, the agent will initiate a rollback. + /// Waiting period before rolling back + timeout: Time, + /// Store path to known-working system closure, typically the + /// current/previous one. + known_working_closure: PathBuf, + }, + #[command()] + Dummy, +} + +impl FromStr for Time { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let num: u64 = match s.parse() { + Ok(v) => v, + Err(e) => bail!(e), + }; + + Ok(Time(Duration::from_secs(num))) + } +} + +#[derive(Parser, Debug)] +pub struct Args { + #[command(subcommand)] + pub operation: Operations, +} diff --git a/wire/agent/src/lib.rs b/wire/agent/src/lib.rs new file mode 100644 index 0000000..481d517 --- /dev/null +++ b/wire/agent/src/lib.rs @@ -0,0 +1,4 @@ +pub mod cli; +pub mod keys { + include!(concat!(env!("OUT_DIR"), "/agent.rs")); +} diff --git a/wire/agent/src/main.rs b/wire/agent/src/main.rs new file mode 100644 index 0000000..c51eb4a --- /dev/null +++ b/wire/agent/src/main.rs @@ -0,0 +1,191 @@ +#![deny(clippy::pedantic)] +use agent::keys::{Keys, OpCode, Rollback}; +use anyhow::bail; +use clap::Parser; +use cli::Time; +use nix::unistd::{geteuid, Group, User}; +use prost::bytes::BytesMut; +use prost::Message; +use std::os::unix::fs::PermissionsExt; +use std::path::{Path, PathBuf}; +use std::process::Stdio; +use std::{ + io::{Cursor, Read}, + os::unix::fs::chown, +}; +use tokio::fs::File; +use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}; +use tokio::net::{UnixListener, UnixStream}; +use tokio::process::Command; +use tokio::select; +use tokio::sync::mpsc; +use tracing::{debug, error, info, info_span, instrument}; +use tracing_subscriber::fmt; + +mod cli; + +fn create_path(key_path: &Path) -> Result<(), anyhow::Error> { + let prefix = key_path.parent().unwrap(); + std::fs::create_dir_all(prefix)?; + + Ok(()) +} + +#[instrument] +async fn push_keys(length: usize) -> Result<(), anyhow::Error> { + let mut stdin = std::io::stdin(); + let mut msg_buf = vec![0u8; length]; + stdin.read_exact(&mut msg_buf)?; + + let msg = Keys::decode(&mut Cursor::new(&msg_buf))?; + for key in msg.keys { + let path = PathBuf::from(&key.destination); + create_path(&path)?; + + let mut file = File::create(path).await?; + let mut permissions = file.metadata().await?.permissions(); + + permissions.set_mode(key.permissions); + file.set_permissions(permissions).await?; + + let user = User::from_name(&key.user)?; + let group = Group::from_name(&key.group)?; + + chown( + key.destination, + user.map(|user| user.uid.into()), + group.map(|group| group.gid.into()), + )?; + + let mut file_buf = vec![ + 0u8; + key.length + .try_into() + .expect("failed to convert size to usize") + ]; + + stdin.read_exact(&mut file_buf)?; + file.write_all(&file_buf).await?; + + println!("Wrote to {file:?}"); + } + Ok(()) +} + +#[instrument] +async fn rollback( + grace_period: Time, + timeout: Time, + known_working_closure: PathBuf, +) -> Result<(), anyhow::Error> { + let (tx, mut rx) = mpsc::channel(1); + let sleeper = tokio::time::sleep(timeout.0); + tokio::pin!(sleeper); + + tokio::spawn(async move { + let server = UnixListener::bind(".wire-agent").unwrap(); + loop { + info!("accepting new connection"); + match server.accept().await { + Ok((mut stream, _)) => { + info!("accepted connection"); + let mut buf = BytesMut::new(); + stream.read_buf(&mut buf).await.unwrap(); + let rollback = Rollback::decode(buf).unwrap(); + if let OpCode::Query = rollback.opcode() { + let mut resp = rollback.clone(); + resp.message = String::from("acknowledged"); + let n = stream.write(resp.encode_to_vec().as_slice()).await.unwrap(); + info!({ written = n }, "response sent"); + } + tx.send(rollback.clone()).await.unwrap(); + } + Err(err) => error!({ error = %err }), + } + } + }); + + loop { + select! { + msg = rx.recv() => { + let d = msg.unwrap(); + debug!("received socket message: {:?}", d); + match d.opcode() { + OpCode::Unspecified | OpCode::Query => (), + OpCode::Finish => { + return Ok(()); + }, + + } + } + + () = &mut sleeper => { + let path = known_working_closure.join("bin/switch-to-configuration"); + info!("timer elapsed, rolling back to {}", path.to_str().unwrap()); + + let span = info_span!("activation"); + let _enter = span.enter(); + + let mut child = Command::new(path) + .arg("switch") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + // Approach adopted from the handle_io logic + let stderr = BufReader::new(child.stderr.take().unwrap()); + let mut lines = stderr.lines(); + + while let Some(line) = lines.next_line().await.unwrap() { + info!("{line}"); + } + + return Ok(()); + + } + } + } +} + +#[tokio::main] +async fn main() -> Result<(), anyhow::Error> { + let args = cli::Args::parse(); + if !geteuid().is_root() { + bail!("agent must be ran as root"); + } + let format = fmt::format() + .with_level(false) + .without_time() + .with_target(true) + .compact(); + tracing_subscriber::fmt().event_format(format).init(); + + match args.operation { + cli::Operations::PushKeys { length } => push_keys(length).await, + cli::Operations::Rollback { + grace_period, + timeout, + known_working_closure, + } => rollback(grace_period, timeout, known_working_closure).await, + cli::Operations::Dummy => { + let b = Rollback { + opcode: OpCode::Finish.into(), + timeout: 10, + grace_period: 10, + closure: "/run/current-system".to_string(), + message: String::new(), + }; + + let mut a = UnixStream::connect(".wire-agent").await?; + _ = a.write(&b.encode_to_vec()).await?; + + let mut resp = BytesMut::new(); + a.read_buf(&mut resp).await?; + let v = Rollback::decode(&mut resp).unwrap(); + println!("response: {v:?}"); + + Ok(()) + } + } +} diff --git a/wire/agent/src/models.proto b/wire/agent/src/models.proto new file mode 100644 index 0000000..dc1eb1d --- /dev/null +++ b/wire/agent/src/models.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + + +package agent; + +message Key { + string destination = 1; + string user = 2; + string group = 3; + uint32 permissions = 4; + int64 length = 5; +} + +message Keys { + repeated Key keys = 1; +} + + +// TODO (opcode signaling and other stuff like logs maybe) +enum OpCode { + OP_CODE_UNSPECIFIED = 0; + OP_CODE_FINISH = 1; // mark rollback as successful and close + OP_CODE_QUERY = 2; // query for current info such as duration left and closure +} + +message Rollback { + OpCode opcode = 1; + uint64 timeout = 2; + uint64 grace_period = 3; + string closure = 4; + string message = 5; // server only +} diff --git a/wire/cli/default.nix b/wire/cli/default.nix index 4b48f83..352be28 100644 --- a/wire/cli/default.nix +++ b/wire/cli/default.nix @@ -1,7 +1,9 @@ +{ self, ... }: { perSystem = { pkgs, + lib, self', buildRustProgram, ... @@ -29,11 +31,19 @@ nativeBuildInputs = [ pkgs.makeWrapper ]; - postBuild = '' - wrapProgram $out/bin/wire \ - --set WIRE_RUNTIME ${../../runtime} \ - --set WIRE_KEY_AGENT ${self'.packages.agent} - ''; + postBuild = + let + agents = lib.mapAttrsToList (name: value: { + inherit name; + path = value.agent; + }) (lib.filterAttrs (_: value: value ? agent) self.packages); + + in + '' + wrapProgram $out/bin/wire \ + --set WIRE_RUNTIME ${../../runtime} \ + --set WIRE_AGENT ${pkgs.linkFarm "wire-agents-farm" agents} + ''; meta.mainProgram = "wire"; }; }; diff --git a/wire/key_agent/build.rs b/wire/key_agent/build.rs deleted file mode 100644 index c5362bf..0000000 --- a/wire/key_agent/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern crate prost_build; - -fn main() { - prost_build::compile_protos(&["src/keys.proto"], &["src/"]).unwrap(); -} diff --git a/wire/key_agent/default.nix b/wire/key_agent/default.nix deleted file mode 100644 index f670ada..0000000 --- a/wire/key_agent/default.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ - perSystem = - { - buildRustProgram, - ... - }: - { - packages = { - agent = buildRustProgram { - name = "key_agent"; - pname = "key_agent"; - cargoExtraArgs = "-p key_agent"; - }; - }; - }; -} diff --git a/wire/key_agent/src/keys.proto b/wire/key_agent/src/keys.proto deleted file mode 100644 index 4290ab5..0000000 --- a/wire/key_agent/src/keys.proto +++ /dev/null @@ -1,15 +0,0 @@ -syntax = "proto3"; - -package key_agent.keys; - -message Key { - string destination = 1; - string user = 2; - string group = 3; - uint32 permissions = 4; - int64 length = 5; -} - -message Keys { - repeated Key keys = 1; -} diff --git a/wire/key_agent/src/lib.rs b/wire/key_agent/src/lib.rs deleted file mode 100644 index 651f7b1..0000000 --- a/wire/key_agent/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod keys { - include!(concat!(env!("OUT_DIR"), "/key_agent.keys.rs")); -} diff --git a/wire/key_agent/src/main.rs b/wire/key_agent/src/main.rs deleted file mode 100644 index 5d45fcd..0000000 --- a/wire/key_agent/src/main.rs +++ /dev/null @@ -1,68 +0,0 @@ -#![deny(clippy::pedantic)] -use nix::unistd::{Group, User}; -use prost::Message; -use std::env; -use std::os::unix::fs::PermissionsExt; -use std::path::{Path, PathBuf}; -use std::{ - io::{Cursor, Read}, - os::unix::fs::chown, -}; -use tokio::fs::File; -use tokio::io::AsyncWriteExt; - -use key_agent::keys::Keys; - -fn create_path(key_path: &Path) -> Result<(), anyhow::Error> { - let prefix = key_path.parent().unwrap(); - std::fs::create_dir_all(prefix)?; - - Ok(()) -} - -#[tokio::main] -async fn main() -> Result<(), anyhow::Error> { - let mut stdin = std::io::stdin(); - let length: usize = env::args().nth(1).expect("failed to grab arg").parse()?; - let mut msg_buf = vec![0u8; length]; - - stdin.read_exact(&mut msg_buf)?; - - let msg = Keys::decode(&mut Cursor::new(&msg_buf))?; - - println!("{msg:?}"); - - for key in msg.keys { - let path = PathBuf::from(&key.destination); - create_path(&path)?; - - let mut file = File::create(path).await?; - let mut permissions = file.metadata().await?.permissions(); - - permissions.set_mode(key.permissions); - file.set_permissions(permissions).await?; - - let user = User::from_name(&key.user)?; - let group = Group::from_name(&key.group)?; - - chown( - key.destination, - user.map(|user| user.uid.into()), - group.map(|group| group.gid.into()), - )?; - - let mut file_buf = vec![ - 0u8; - key.length - .try_into() - .expect("failed to convert size to usize") - ]; - - stdin.read_exact(&mut file_buf)?; - file.write_all(&file_buf).await?; - - println!("Wrote to {file:?}"); - } - - Ok(()) -} diff --git a/wire/lib/Cargo.toml b/wire/lib/Cargo.toml index c45afbc..075491a 100644 --- a/wire/lib/Cargo.toml +++ b/wire/lib/Cargo.toml @@ -19,7 +19,7 @@ thiserror = "1.0.62" serde_repr = "0.1.20" regex = "1.11.1" derive_more = "0.99.18" -key_agent = { path = "../key_agent" } +agent = { path = "../agent" } futures = "0.3.31" prost = { workspace = true } gethostname = "1.0.1" diff --git a/wire/lib/src/hive/key.rs b/wire/lib/src/hive/key.rs index f1795cc..5880b73 100644 --- a/wire/lib/src/hive/key.rs +++ b/wire/lib/src/hive/key.rs @@ -128,7 +128,7 @@ async fn copy_buffers( Ok(()) } -async fn process_key(key: &Key) -> Result<(key_agent::keys::Key, Vec), Error> { +async fn process_key(key: &Key) -> Result<(agent::keys::Key, Vec), Error> { let mut reader = create_reader(&key.source).await?; let mut buf = Vec::new(); @@ -146,7 +146,7 @@ async fn process_key(key: &Key) -> Result<(key_agent::keys::Key, Vec), Error ); Ok(( - key_agent::keys::Key { + agent::keys::Key { length: buf .len() .try_into() @@ -164,7 +164,7 @@ async fn process_key(key: &Key) -> Result<(key_agent::keys::Key, Vec), Error pub struct UploadKeyStep { pub moment: UploadKeyAt, } -pub struct PushKeyAgentStep; +pub struct PushAgentStep; impl Display for UploadKeyStep { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -172,9 +172,9 @@ impl Display for UploadKeyStep { } } -impl Display for PushKeyAgentStep { +impl Display for PushAgentStep { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Push the key agent") + write!(f, "Push the agent") } } @@ -207,7 +207,7 @@ impl ExecuteStep for UploadKeyStep { } async fn execute(&self, ctx: &mut Context<'_>) -> Result<(), HiveLibError> { - let agent_directory = ctx.state.key_agent_directory.as_ref().unwrap(); + let agent_directory = ctx.state.agent_directory.as_ref().unwrap(); let futures = ctx .node @@ -219,7 +219,7 @@ impl ExecuteStep for UploadKeyStep { }) .map(|key| async move { process_key(key).await }); - let (keys, bufs): (Vec, Vec>) = join_all(futures) + let (keys, bufs): (Vec, Vec>) = join_all(futures) .await .into_iter() .collect::, Error>>() @@ -227,7 +227,7 @@ impl ExecuteStep for UploadKeyStep { .into_iter() .unzip(); - let msg = key_agent::keys::Keys { keys }; + let msg = agent::keys::Keys { keys }; trace!("Sending message {msg:?}"); @@ -237,8 +237,9 @@ impl ExecuteStep for UploadKeyStep { let mut child = command .args([ - format!("{agent_directory}/bin/key_agent"), - buf.len().to_string(), + format!("{agent_directory}/bin/agent"), + "push-keys".to_string(), + format!("--length {}", buf.len()), ]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) @@ -278,20 +279,28 @@ impl ExecuteStep for UploadKeyStep { } #[async_trait] -impl ExecuteStep for PushKeyAgentStep { +impl ExecuteStep for PushAgentStep { fn should_execute(&self, ctx: &Context) -> bool { should_execute(&UploadKeyAt::AnyOpportunity, ctx) } async fn execute(&self, ctx: &mut Context<'_>) -> Result<(), HiveLibError> { - let agent_directory = match env::var_os("WIRE_KEY_AGENT") { - Some(agent) => agent.into_string().unwrap(), - None => panic!("WIRE_KEY_AGENT environment variable not set"), - }; + let mut agent_directory = PathBuf::from( + env::var_os("WIRE_AGENT") + .expect("WIRE_AGENT environment variable not set!") + .into_string() + .unwrap(), + ); + + agent_directory.push(ctx.node.system.as_str()); + + let path = String::from(agent_directory.to_str().unwrap()); + + debug!("agent path: {path}"); - push(ctx.node, ctx.name, Push::Path(&agent_directory)).await?; + push(ctx.node, ctx.name, Push::Path(&path)).await?; - ctx.state.key_agent_directory = Some(agent_directory); + ctx.state.agent_directory = Some(path); Ok(()) } diff --git a/wire/lib/src/hive/node.rs b/wire/lib/src/hive/node.rs index 3f8b073..b84b2c5 100644 --- a/wire/lib/src/hive/node.rs +++ b/wire/lib/src/hive/node.rs @@ -12,7 +12,7 @@ use tracing_indicatif::span_ext::IndicatifSpanExt; use crate::nix::StreamTracing; use crate::SubCommandModifiers; -use super::key::{Key, PushKeyAgentStep, UploadKeyAt, UploadKeyStep}; +use super::key::{Key, PushAgentStep, UploadKeyAt, UploadKeyStep}; use super::steps::activate::SwitchToConfigurationStep; use super::HiveLibError; @@ -31,6 +31,7 @@ pub struct Target { pub port: u32, } +#[cfg(test)] impl Default for Target { fn default() -> Self { Target { @@ -57,8 +58,14 @@ pub struct Node { #[serde(rename(deserialize = "_keys", serialize = "keys"))] pub keys: im::Vector, + + #[serde()] + // system is the architecture of the host, this is mainly used for + // determining the correct binary to push to the host's machine. + pub system: String, } +#[cfg(test)] impl Default for Node { fn default() -> Self { Node { @@ -67,6 +74,7 @@ impl Default for Node { tags: im::HashSet::new(), allow_local_deployment: true, build_remotely: false, + system: String::from("x86_64-linux"), } } } @@ -117,7 +125,7 @@ pub trait ExecuteStep: Send + Sync + Display { pub struct StepState { pub evaluation: Option, pub build: Option, - pub key_agent_directory: Option, + pub agent_directory: Option, } pub struct Context<'a> { @@ -139,7 +147,7 @@ impl<'a> GoalExecutor<'a> { pub fn new(context: Context<'a>) -> Self { Self { steps: vec![ - Box::new(PushKeyAgentStep), + Box::new(PushAgentStep), Box::new(UploadKeyStep { moment: UploadKeyAt::AnyOpportunity, }),