From 221b4348d8f7caaf0df843640cbc0a0c5845b5c8 Mon Sep 17 00:00:00 2001 From: Nikos Papadakis Date: Thu, 25 Jan 2024 01:18:30 +0200 Subject: [PATCH] nats --- Cargo.lock | 1386 ++++++++++++---------------------- agent/.gitignore | 1 - agent/Cargo.toml | 30 +- agent/build.rs | 6 - agent/server.conf | 27 + agent/src/bin/prymn_agent.rs | 33 - agent/src/config.rs | 18 - agent/src/debian.rs | 186 ----- agent/src/health.rs | 190 ----- agent/src/info.rs | 87 --- agent/src/lib.rs | 8 - agent/src/main.rs | 107 +++ agent/src/pty.rs | 166 ---- agent/src/self_update.rs | 143 ---- agent/src/server/agent.rs | 224 ------ agent/src/server/mod.rs | 128 ---- agent/src/task.rs | 154 ---- agent/tests/task_health.rs | 18 - 18 files changed, 642 insertions(+), 2270 deletions(-) delete mode 100644 agent/.gitignore delete mode 100644 agent/build.rs create mode 100644 agent/server.conf delete mode 100644 agent/src/bin/prymn_agent.rs delete mode 100644 agent/src/config.rs delete mode 100644 agent/src/debian.rs delete mode 100644 agent/src/health.rs delete mode 100644 agent/src/info.rs delete mode 100644 agent/src/lib.rs create mode 100644 agent/src/main.rs delete mode 100644 agent/src/pty.rs delete mode 100644 agent/src/self_update.rs delete mode 100644 agent/src/server/agent.rs delete mode 100644 agent/src/server/mod.rs delete mode 100644 agent/src/task.rs delete mode 100644 agent/tests/task_health.rs diff --git a/Cargo.lock b/Cargo.lock index 9085b8e..d8524fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,106 +26,44 @@ dependencies = [ "memchr", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" - -[[package]] -name = "anstyle-parse" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - [[package]] name = "anyhow" -version = "1.0.76" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] -name = "async-stream" -version = "0.3.5" +name = "async-nats" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "dbc1f1a75fd07f0f517322d103211f12d757658e91676def9a2e688774656c60" dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-trait" -version = "0.1.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "base64", + "bytes", + "futures", + "http", + "memchr", + "nkeys", + "nuid", + "once_cell", + "rand", + "regex", + "ring", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "rustls-webpki", + "serde", + "serde_json", + "serde_nanos", + "serde_repr", + "thiserror", + "time", + "tokio", + "tokio-retry", + "tokio-rustls", + "tracing", + "url", ] [[package]] @@ -134,51 +72,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "axum" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http", - "http-body", - "hyper", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "backtrace" version = "0.3.69" @@ -196,9 +89,15 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bitflags" @@ -207,22 +106,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bitflags" -version = "2.4.1" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] [[package]] -name = "bumpalo" -version = "3.14.0" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +dependencies = [ + "serde", +] [[package]] name = "cc" @@ -240,51 +145,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "chrono" -version = "0.4.31" +name = "const-oid" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-targets 0.48.5", -] - -[[package]] -name = "clap" -version = "4.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_lex" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" @@ -303,56 +167,115 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] -name = "either" -version = "1.9.0" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "encoding_rs" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "cfg-if", + "libc", ] [[package]] -name = "envy" -version = "0.4.2" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", "serde", ] [[package]] -name = "equivalent" -version = "1.0.1" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "libc", - "windows-sys 0.52.0", + "block-buffer", + "crypto-common", ] [[package]] -name = "fastrand" -version = "2.0.1" +name = "ed25519" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "signature", +] [[package]] -name = "fixedbitset" -version = "0.4.2" +name = "ed25519-dalek" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +dependencies = [ + "curve25519-dalek", + "ed25519", + "sha2", + "signature", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" [[package]] name = "fnv" @@ -370,46 +293,63 @@ dependencies = [ ] [[package]] -name = "futures-channel" -version = "0.3.29" +name = "futures" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-sink", "futures-task", "memchr", "pin-project-lite", @@ -418,10 +358,20 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.2.11" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -434,58 +384,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "h2" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 2.1.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "hermit-abi" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "http" version = "0.2.11" @@ -497,94 +401,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "http-range-header" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "idna" version = "0.5.0" @@ -595,56 +411,12 @@ dependencies = [ "unicode-normalization", ] -[[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.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" -dependencies = [ - "equivalent", - "hashbrown 0.14.3", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" -[[package]] -name = "js-sys" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" -dependencies = [ - "wasm-bindgen", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -657,12 +429,6 @@ version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" -[[package]] -name = "linux-raw-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" - [[package]] name = "lock_api" version = "0.4.11" @@ -679,24 +445,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "memchr" version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -718,18 +472,19 @@ dependencies = [ ] [[package]] -name = "multimap" -version = "0.8.3" +name = "nkeys" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +checksum = "aad178aad32087b19042ee36dfd450b73f5f934fbfb058b59b198684dfec4c47" dependencies = [ - "winapi", + "byteorder", + "data-encoding", + "ed25519", + "ed25519-dalek", + "getrandom", + "log", + "rand", + "signatory", ] [[package]] @@ -743,12 +498,12 @@ dependencies = [ ] [[package]] -name = "num-traits" -version = "0.2.17" +name = "nuid" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "fc895af95856f929163a0aa20c26a78d26bfdc839f51b9d5aa7a5b79e52b7e83" dependencies = [ - "autocfg", + "rand", ] [[package]] @@ -776,6 +531,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "overload" version = "0.1.1" @@ -805,22 +566,21 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap 2.1.0", -] - [[package]] name = "pin-project" version = "1.1.3" @@ -853,117 +613,61 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "platforms" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "prettyplease" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] -[[package]] -name = "prost" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" -dependencies = [ - "bytes", - "heck", - "itertools", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "regex", - "syn", - "tempfile", - "which", -] - -[[package]] -name = "prost-derive" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost-types" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" -dependencies = [ - "prost", -] - [[package]] name = "prymn_agent" version = "0.1.0" dependencies = [ "anyhow", - "chrono", - "clap", - "envy", - "itertools", - "once_cell", - "prost", - "regex", - "reqwest", - "rustix", - "serde", + "async-nats", "serde_json", - "sysinfo", "tokio", "tokio-stream", - "tokio-util", - "tonic", - "tonic-build", - "tower-http", "tracing", "tracing-subscriber", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1004,14 +708,14 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -1021,9 +725,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" dependencies = [ "aho-corasick", "memchr", @@ -1037,38 +741,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] -name = "reqwest" -version = "0.11.23" +name = "ring" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", + "cc", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.48.0", ] [[package]] @@ -1078,24 +761,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] -name = "rustix" -version = "0.38.28" +name = "rustc_version" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "bitflags 2.4.1", - "errno", - "itoa", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "semver", ] [[package]] -name = "rustversion" -version = "1.0.14" +name = "rustls" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] [[package]] name = "ryu" @@ -1103,6 +818,15 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1110,19 +834,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "serde" -version = "1.0.193" +name = "sct" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + +[[package]] +name = "serde" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", @@ -1131,9 +894,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", @@ -1141,17 +904,36 @@ dependencies = [ ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "serde_nanos" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "8ae801b7733ca8d6a2b580debe99f67f36826a0f5b8a36055dc6bc40f8d6bc71" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -1170,6 +952,28 @@ dependencies = [ "libc", ] +[[package]] +name = "signatory" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e303f8205714074f6068773f0e29527e0453937fe837c9717d066635b65f31" +dependencies = [ + "pkcs8", + "rand_core", + "signature", + "zeroize", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "slab" version = "0.4.9" @@ -1196,16 +1000,32 @@ dependencies = [ ] [[package]] -name = "strsim" -version = "0.10.0" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.42" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -1213,57 +1033,23 @@ dependencies = [ ] [[package]] -name = "sync_wrapper" -version = "0.1.2" +name = "thiserror" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sysinfo" -version = "0.29.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ - "cfg-if", - "core-foundation-sys", - "libc", - "ntapi", - "once_cell", - "winapi", + "thiserror-impl", ] [[package]] -name = "system-configuration" -version = "0.5.1" +name = "thiserror-impl" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys 0.48.0", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1276,6 +1062,35 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +dependencies = [ + "deranged", + "itoa", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +dependencies = [ + "time-core", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1310,16 +1125,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.2.0" @@ -1331,6 +1136,27 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-retry" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +dependencies = [ + "pin-project", + "rand", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.14" @@ -1340,114 +1166,8 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", - "tokio-util", ] -[[package]] -name = "tokio-util" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tonic" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" -dependencies = [ - "async-stream", - "async-trait", - "axum", - "base64", - "bytes", - "h2", - "http", - "http-body", - "hyper", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost", - "tokio", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic-build" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889" -dependencies = [ - "prettyplease", - "proc-macro2", - "prost-build", - "quote", - "syn", -] - -[[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", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" -dependencies = [ - "bitflags 2.4.1", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-range-header", - "pin-project-lite", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - [[package]] name = "tracing" version = "0.1.40" @@ -1506,16 +1226,16 @@ dependencies = [ ] [[package]] -name = "try-lock" -version = "0.2.5" +name = "typenum" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -1532,6 +1252,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -1543,12 +1269,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - [[package]] name = "valuable" version = "0.1.0" @@ -1556,13 +1276,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] -name = "want" -version = "0.3.1" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" @@ -1570,94 +1287,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" - -[[package]] -name = "web-sys" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "winapi" version = "0.3.9" @@ -1680,15 +1309,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -1822,11 +1442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] -name = "winreg" -version = "0.50.0" +name = "zeroize" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/agent/.gitignore b/agent/.gitignore deleted file mode 100644 index b83d222..0000000 --- a/agent/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/agent/Cargo.toml b/agent/Cargo.toml index f6378be..e364e56 100644 --- a/agent/Cargo.toml +++ b/agent/Cargo.toml @@ -4,26 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.71" -chrono = "0.4.26" -clap = "4.3.9" -envy = "0.4.2" -itertools = "0.11.0" -once_cell = "1.18.0" -prost = "0.12.1" -regex = "1.10.2" -reqwest = { version = "0.11.18", features = ["blocking", "json"], default-features = false } -rustix = { version = "0.38.28", features = ["fs", "process", "pty", "stdio", "termios"] } -serde = { version = "1.0.173", features = ["derive"] } -serde_json = "1.0.103" -sysinfo = { version = "0.29.2", default-features = false } -tokio = { version = "1.28.2", features = ["full"] } -tokio-stream = { version = "0.1.14", features = ["net", "sync"] } -tokio-util = { version = "0.7.10", features = ["codec"] } -tonic = { version = "0.10.2" } -tower-http = { version = "0.4.3", features = ["trace"] } -tracing = "0.1.37" -tracing-subscriber = "0.3.17" - -[build-dependencies] -tonic-build = "0.10.2" +anyhow = "1.0.79" +async-nats = "0.33.0" +serde_json = "1.0.111" +tokio = { version = "1.35.1", features = ["full"] } +tokio-stream = { version = "0.1.14", default-features = false } +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["fmt"] } diff --git a/agent/build.rs b/agent/build.rs deleted file mode 100644 index 84fcb7f..0000000 --- a/agent/build.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - tonic_build::configure() - .build_client(false) - .compile(&["../proto/agent.proto"], &["../proto"]) - .unwrap(); -} diff --git a/agent/server.conf b/agent/server.conf new file mode 100644 index 0000000..cf24e03 --- /dev/null +++ b/agent/server.conf @@ -0,0 +1,27 @@ +authorization: { + users = [ + { + user: prymn_admin + password: prymn_admin + permissions: { + publish: ">" + subscribe: ">" + } + } + { + user: demo_agent + password: demo_agent_password + permissions: { + publish: [ + "agents.v1.demo_agent.>" + ] + subscribe: [ + "agents.v1.demo_agent.>" + "_INBOX_demo_agent.>" + ] + } + } + ] +} + +jetstream: {} diff --git a/agent/src/bin/prymn_agent.rs b/agent/src/bin/prymn_agent.rs deleted file mode 100644 index c557fa4..0000000 --- a/agent/src/bin/prymn_agent.rs +++ /dev/null @@ -1,33 +0,0 @@ -use anyhow::Context; -use clap::arg; -use prymn_agent::{self_update, server}; -use tracing::Level; -use tracing_subscriber::{filter::Targets, layer::SubscriberExt, util::SubscriberInitExt}; - -fn main() -> anyhow::Result<()> { - // Debug subscriber, should be configurable in the future - tracing_subscriber::fmt() - .with_max_level(Level::TRACE) - .pretty() - .without_time() - .with_file(false) - .finish() - .with( - Targets::new() - .with_target("prymn_agent", Level::DEBUG) - .with_target("tower_http", Level::DEBUG), - ) - .init(); - - let command = clap::Command::new(env!("CARGO_BIN_NAME")) - .version(env!("CARGO_PKG_VERSION")) - .arg(arg!(--install "Install this agent binary to the system").exclusive(true)) - .try_get_matches() - .unwrap_or_else(|e| e.exit()); - - if let Some(token) = command.get_one::("install") { - self_update::install(token).context("failed to install the agent to the system") - } else { - server::run() - } -} diff --git a/agent/src/config.rs b/agent/src/config.rs deleted file mode 100644 index ed54131..0000000 --- a/agent/src/config.rs +++ /dev/null @@ -1,18 +0,0 @@ -use once_cell::sync::Lazy; -use serde::Deserialize; - -#[derive(Deserialize, Debug)] -pub struct Config { - #[serde(default = "default_backend_url")] - pub backend_url: String, -} - -fn default_backend_url() -> String { - "https://app.prymn.net".to_string() -} - -pub static CONFIG: Lazy = - Lazy::new(|| match envy::prefixed("PRYMN_").from_env::() { - Ok(config) => config, - Err(_) => todo!("handle this error"), - }); diff --git a/agent/src/debian.rs b/agent/src/debian.rs deleted file mode 100644 index 4ae241f..0000000 --- a/agent/src/debian.rs +++ /dev/null @@ -1,186 +0,0 @@ -use std::process::{Command, Output}; - -use regex::Regex; - -pub fn update_package_index() -> std::io::Result { - Command::new("apt-get").arg("-y").arg("update").output() -} - -pub fn run_updates(dry_run: bool) -> std::io::Result { - let mut command = Command::new("apt-get"); - - if dry_run { - command.arg("-s"); - } - - command.arg("-y").arg("upgrade").output() -} - -pub fn install_packages(packages: &[&str]) -> std::io::Result { - Command::new("apt-get") - .arg("install") - .arg("-y") - .args(packages) - .output() -} - -pub fn get_available_updates() -> std::io::Result> { - let output = Command::new("apt-get").arg("-sV").arg("upgrade").output()?; - let upgradables = parse_upgrade_output(&String::from_utf8_lossy(&output.stdout)); - Ok(upgradables) -} - -fn parse_upgrade_output(output: &str) -> Vec { - output - .split_once("The following packages will be upgraded:\n") - .and_then(|(_, rest)| { - // Find the first line with non-whitespace characters (indicating the end of the list) - let re = Regex::new(r"(?m)^\S").unwrap(); - re.find(rest).map(|m| rest.split_at(m.start()).0) - }) - .map_or_else(Vec::new, |text| { - let lines = text.lines(); - lines.map(|line| line.trim().to_owned()).collect() - }) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parses_upgrade_output_correctly() { - // `apt-get -sV upgrade` - let test_output = r" -NOTE: This is only a simulation! - apt-get needs root privileges for real execution. - Keep also in mind that locking is deactivated, - so don't depend on the relevance to the real current situation! -Reading package lists... Done -Building dependency tree... Done -Reading state information... Done -Calculating upgrade... Done -The following packages have been kept back: - linux-image-amd64 (5.10.191-1 => 5.10.197-1) -The following packages will be upgraded: - adduser (3.118 => 3.118+deb11u1) - base-files (11.1+deb11u7 => 11.1+deb11u8) - cpio (2.13+dfsg-4 => 2.13+dfsg-7.1~deb11u1) - dbus (1.12.24-0+deb11u1 => 1.12.28-0+deb11u1) - distro-info-data (0.51+deb11u3 => 0.51+deb11u4) - dpkg (1.20.12 => 1.20.13) - grub-common (2.06-3~deb11u5 => 2.06-3~deb11u6) - grub-pc (2.06-3~deb11u5 => 2.06-3~deb11u6) - grub-pc-bin (2.06-3~deb11u5 => 2.06-3~deb11u6) - grub2-common (2.06-3~deb11u5 => 2.06-3~deb11u6) - krb5-locales (1.18.3-6+deb11u3 => 1.18.3-6+deb11u4) - libbsd0 (0.11.3-1 => 0.11.3-1+deb11u1) - libcurl3-gnutls (7.74.0-1.3+deb11u7 => 7.74.0-1.3+deb11u10) - libdbus-1-3 (1.12.24-0+deb11u1 => 1.12.28-0+deb11u1) - libgssapi-krb5-2 (1.18.3-6+deb11u3 => 1.18.3-6+deb11u4) - libk5crypto3 (1.18.3-6+deb11u3 => 1.18.3-6+deb11u4) - libkrb5-3 (1.18.3-6+deb11u3 => 1.18.3-6+deb11u4) - libkrb5support0 (1.18.3-6+deb11u3 => 1.18.3-6+deb11u4) - libncurses6 (6.2+20201114-2+deb11u1 => 6.2+20201114-2+deb11u2) - libncursesw6 (6.2+20201114-2+deb11u1 => 6.2+20201114-2+deb11u2) - libnss-systemd (247.3-7+deb11u2 => 247.3-7+deb11u4) - libpam-systemd (247.3-7+deb11u2 => 247.3-7+deb11u4) - libssl1.1 (1.1.1n-0+deb11u5 => 1.1.1w-0+deb11u1) - libsystemd0 (247.3-7+deb11u2 => 247.3-7+deb11u4) - libtinfo6 (6.2+20201114-2+deb11u1 => 6.2+20201114-2+deb11u2) - libudev1 (247.3-7+deb11u2 => 247.3-7+deb11u4) - logrotate (3.18.0-2+deb11u1 => 3.18.0-2+deb11u2) - ncurses-base (6.2+20201114-2+deb11u1 => 6.2+20201114-2+deb11u2) - ncurses-bin (6.2+20201114-2+deb11u1 => 6.2+20201114-2+deb11u2) - ncurses-term (6.2+20201114-2+deb11u1 => 6.2+20201114-2+deb11u2) - openssh-client (1:8.4p1-5+deb11u1 => 1:8.4p1-5+deb11u2) - openssh-server (1:8.4p1-5+deb11u1 => 1:8.4p1-5+deb11u2) - openssh-sftp-server (1:8.4p1-5+deb11u1 => 1:8.4p1-5+deb11u2) - openssl (1.1.1n-0+deb11u5 => 1.1.1w-0+deb11u1) - qemu-utils (1:5.2+dfsg-11+deb11u2 => 1:5.2+dfsg-11+deb11u3) - systemd (247.3-7+deb11u2 => 247.3-7+deb11u4) - systemd-sysv (247.3-7+deb11u2 => 247.3-7+deb11u4) - udev (247.3-7+deb11u2 => 247.3-7+deb11u4) -38 upgraded, 0 newly installed, 0 to remove and 1 not upgraded. -Inst base-files [11.1+deb11u7] (11.1+deb11u8 Debian:11.8/oldstable [amd64]) -Conf base-files (11.1+deb11u8 Debian:11.8/oldstable [amd64]) -Inst dpkg [1.20.12] (1.20.13 Debian:11.8/oldstable [amd64]) -Conf dpkg (1.20.13 Debian:11.8/oldstable [amd64]) -Inst ncurses-bin [6.2+20201114-2+deb11u1] (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [amd64]) -Conf ncurses-bin (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [amd64]) -Inst ncurses-base [6.2+20201114-2+deb11u1] (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [all]) -Conf ncurses-base (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [all]) -Inst libnss-systemd [247.3-7+deb11u2] (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) [] -Inst libsystemd0 [247.3-7+deb11u2] (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) [systemd:amd64 ] -Conf libsystemd0 (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) [systemd:amd64 ] -Inst libpam-systemd [247.3-7+deb11u2] (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) [systemd:amd64 ] -Inst systemd [247.3-7+deb11u2] (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Inst udev [247.3-7+deb11u2] (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) [] -Inst libudev1 [247.3-7+deb11u2] (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Conf libudev1 (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Inst adduser [3.118] (3.118+deb11u1 Debian:11.8/oldstable [all]) -Conf adduser (3.118+deb11u1 Debian:11.8/oldstable [all]) -Conf systemd (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Inst systemd-sysv [247.3-7+deb11u2] (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Inst dbus [1.12.24-0+deb11u1] (1.12.28-0+deb11u1 Debian:11.8/oldstable [amd64]) [] -Inst libdbus-1-3 [1.12.24-0+deb11u1] (1.12.28-0+deb11u1 Debian:11.8/oldstable [amd64]) -Inst libk5crypto3 [1.18.3-6+deb11u3] (1.18.3-6+deb11u4 Debian:11.8/oldstable [amd64]) -Conf libk5crypto3 (1.18.3-6+deb11u4 Debian:11.8/oldstable [amd64]) -Inst libkrb5support0 [1.18.3-6+deb11u3] (1.18.3-6+deb11u4 Debian:11.8/oldstable [amd64]) [libkrb5-3:amd64 ] -Conf libkrb5support0 (1.18.3-6+deb11u4 Debian:11.8/oldstable [amd64]) [libkrb5-3:amd64 ] -Inst libkrb5-3 [1.18.3-6+deb11u3] (1.18.3-6+deb11u4 Debian:11.8/oldstable [amd64]) [libgssapi-krb5-2:amd64 ] -Conf libkrb5-3 (1.18.3-6+deb11u4 Debian:11.8/oldstable [amd64]) [libgssapi-krb5-2:amd64 ] -Inst libgssapi-krb5-2 [1.18.3-6+deb11u3] (1.18.3-6+deb11u4 Debian:11.8/oldstable [amd64]) -Conf libgssapi-krb5-2 (1.18.3-6+deb11u4 Debian:11.8/oldstable [amd64]) -Inst libssl1.1 [1.1.1n-0+deb11u5] (1.1.1w-0+deb11u1 Debian:11.8/oldstable [amd64]) -Conf libssl1.1 (1.1.1w-0+deb11u1 Debian:11.8/oldstable [amd64]) -Inst libncurses6 [6.2+20201114-2+deb11u1] (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [amd64]) [] -Inst libncursesw6 [6.2+20201114-2+deb11u1] (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [amd64]) [] -Inst libtinfo6 [6.2+20201114-2+deb11u1] (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [amd64]) -Conf libtinfo6 (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [amd64]) -Inst cpio [2.13+dfsg-4] (2.13+dfsg-7.1~deb11u1 Debian:11.8/oldstable [amd64]) -Inst logrotate [3.18.0-2+deb11u1] (3.18.0-2+deb11u2 Debian:11.8/oldstable [amd64]) -Inst krb5-locales [1.18.3-6+deb11u3] (1.18.3-6+deb11u4 Debian:11.8/oldstable [all]) -Inst ncurses-term [6.2+20201114-2+deb11u1] (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [all]) -Inst openssh-sftp-server [1:8.4p1-5+deb11u1] (1:8.4p1-5+deb11u2 Debian:11.8/oldstable [amd64]) [] -Inst openssh-server [1:8.4p1-5+deb11u1] (1:8.4p1-5+deb11u2 Debian:11.8/oldstable [amd64]) [] -Inst openssh-client [1:8.4p1-5+deb11u1] (1:8.4p1-5+deb11u2 Debian:11.8/oldstable [amd64]) -Inst distro-info-data [0.51+deb11u3] (0.51+deb11u4 Debian:11.8/oldstable [all]) -Inst grub2-common [2.06-3~deb11u5] (2.06-3~deb11u6 Debian-Security:11/oldstable-security [amd64]) [grub-pc:amd64 ] -Inst grub-pc [2.06-3~deb11u5] (2.06-3~deb11u6 Debian-Security:11/oldstable-security [amd64]) [] -Inst grub-pc-bin [2.06-3~deb11u5] (2.06-3~deb11u6 Debian-Security:11/oldstable-security [amd64]) [] -Inst grub-common [2.06-3~deb11u5] (2.06-3~deb11u6 Debian-Security:11/oldstable-security [amd64]) -Inst libbsd0 [0.11.3-1] (0.11.3-1+deb11u1 Debian:11.8/oldstable [amd64]) -Inst libcurl3-gnutls [7.74.0-1.3+deb11u7] (7.74.0-1.3+deb11u10 Debian-Security:11/oldstable-security [amd64]) -Inst openssl [1.1.1n-0+deb11u5] (1.1.1w-0+deb11u1 Debian:11.8/oldstable [amd64]) -Inst qemu-utils [1:5.2+dfsg-11+deb11u2] (1:5.2+dfsg-11+deb11u3 Debian:11.8/oldstable [amd64]) -Conf libnss-systemd (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Conf libpam-systemd (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Conf udev (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Conf systemd-sysv (247.3-7+deb11u4 Debian:11.8/oldstable, Debian:11-updates/oldstable-updates [amd64]) -Conf dbus (1.12.28-0+deb11u1 Debian:11.8/oldstable [amd64]) -Conf libdbus-1-3 (1.12.28-0+deb11u1 Debian:11.8/oldstable [amd64]) -Conf libncurses6 (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [amd64]) -Conf libncursesw6 (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [amd64]) -Conf cpio (2.13+dfsg-7.1~deb11u1 Debian:11.8/oldstable [amd64]) -Conf logrotate (3.18.0-2+deb11u2 Debian:11.8/oldstable [amd64]) -Conf krb5-locales (1.18.3-6+deb11u4 Debian:11.8/oldstable [all]) -Conf ncurses-term (6.2+20201114-2+deb11u2 Debian:11.8/oldstable [all]) -Conf openssh-sftp-server (1:8.4p1-5+deb11u2 Debian:11.8/oldstable [amd64]) -Conf openssh-server (1:8.4p1-5+deb11u2 Debian:11.8/oldstable [amd64]) -Conf openssh-client (1:8.4p1-5+deb11u2 Debian:11.8/oldstable [amd64]) -Conf distro-info-data (0.51+deb11u4 Debian:11.8/oldstable [all]) -Conf grub2-common (2.06-3~deb11u6 Debian-Security:11/oldstable-security [amd64]) -Conf grub-pc (2.06-3~deb11u6 Debian-Security:11/oldstable-security [amd64]) -Conf grub-pc-bin (2.06-3~deb11u6 Debian-Security:11/oldstable-security [amd64]) -Conf grub-common (2.06-3~deb11u6 Debian-Security:11/oldstable-security [amd64]) -Conf libbsd0 (0.11.3-1+deb11u1 Debian:11.8/oldstable [amd64]) -Conf libcurl3-gnutls (7.74.0-1.3+deb11u10 Debian-Security:11/oldstable-security [amd64]) -Conf openssl (1.1.1w-0+deb11u1 Debian:11.8/oldstable [amd64]) -Conf qemu-utils (1:5.2+dfsg-11+deb11u3 Debian:11.8/oldstable [amd64]) - "; - - let upgradables = parse_upgrade_output(test_output); - assert_eq!(upgradables.len(), 38); - } -} diff --git a/agent/src/health.rs b/agent/src/health.rs deleted file mode 100644 index 685bd15..0000000 --- a/agent/src/health.rs +++ /dev/null @@ -1,190 +0,0 @@ -//! System health module -use std::{collections::HashMap, sync::Arc}; - -use tokio::sync::watch; - -use super::{info::Info, task::TaskStatus}; - -const MEMORY_USAGE_CRITICAL_THRESHOLD: u64 = 90; -const CPU_USAGE_CRITICAL_THRESHOLD: u64 = 90; -const DISK_USAGE_CRITICAL_THRESHOLD: u64 = 90; - -#[derive(Clone, PartialEq)] -pub enum CriticalReason { - HighMemoryUsage, - HighCpuUsage, - HighDiskUsage, -} - -#[derive(Clone, Default, PartialEq)] -pub enum SystemStatus { - #[default] - Normal, - OutOfDate, - Updating, - Critical(Vec), -} - -#[derive(Clone, Default)] -pub struct SystemHealth { - pub status: SystemStatus, -} - -#[derive(Default, Clone)] -pub struct Health { - system: SystemHealth, - tasks: HashMap, -} - -impl Health { - pub fn system(&self) -> &SystemHealth { - &self.system - } - - pub fn tasks(&self) -> &HashMap { - &self.tasks - } -} - -/// [HealthMonitor] gives access to shared system health state, allowing to watch health and update -/// task health status. -/// -/// # Usage -/// Internally it uses [Arc] so it can be cheaply cloned and shared. -/// ``` -/// use prymn_agent::health::HealthMonitor; -/// use prymn_agent::info::Info; -/// -/// let mut info = Info::new(); -/// let health_monitor = HealthMonitor::new(); -/// -/// // Monitor health changes -/// let _receiver = health_monitor.monitor(); -/// -/// // Refresh system resources -/// info.refresh_resources(); -/// -/// // Update the health monitor with the refreshed info -/// health_monitor.check_system_info(&info); -/// ``` -#[derive(Clone)] -pub struct HealthMonitor { - sender: Arc>, -} - -impl HealthMonitor { - pub fn new() -> Self { - let (sender, _) = watch::channel(Health::default()); - Self { - sender: Arc::new(sender), - } - } - - pub fn check_system_info(&self, info: &Info) { - use sysinfo::{CpuExt, DiskExt, SystemExt}; - - let sys = info.system(); - let mut status = SystemStatus::Normal; - let mut statuses = vec![]; - - // Check for critical memory usage - let memory_usage = if sys.total_memory() > 0 { - sys.used_memory() * 100 / sys.total_memory() - } else { - 0 - }; - - if memory_usage > MEMORY_USAGE_CRITICAL_THRESHOLD { - statuses.push(CriticalReason::HighMemoryUsage); - } - - // Check for critical CPU usage - let cpu_usage = sys.global_cpu_info().cpu_usage(); - - if cpu_usage > CPU_USAGE_CRITICAL_THRESHOLD as f32 { - statuses.push(CriticalReason::HighCpuUsage); - } - - // Check for any disk usage that is critical - for disk in sys.disks() { - let available_disk = if disk.total_space() > 0 { - disk.available_space() * 100 / disk.total_space() - } else { - 0 - }; - - if available_disk < 100 - DISK_USAGE_CRITICAL_THRESHOLD { - statuses.push(CriticalReason::HighDiskUsage); - } - } - - if !statuses.is_empty() { - status = SystemStatus::Critical(statuses); - } - - self.sender.send_if_modified(|Health { system, .. }| { - if system.status == status { - return false; - } - - system.status = status; - true - }); - } - - /// Spawns a new tokio task that tracks from the [watch::Receiver] the status of a Prymn task - /// via [TaskStatus] - pub fn track_task(&self, name: String, mut task_recv: watch::Receiver) { - let sender = self.sender.clone(); - - tokio::task::spawn(async move { - while task_recv.changed().await.is_ok() { - sender.send_modify(|health| { - health - .tasks - .insert(String::from(&name), task_recv.borrow().clone()); - }); - } - - // At this point the Sender part of the watch dropped, meaning we can clear the task - // because it is complete. - sender.send_if_modified(|health| health.tasks.remove(&name).is_some()); - }); - } - - pub fn clear_task(&self, task_name: &str) { - self.sender - .send_if_modified(|Health { tasks, .. }| tasks.remove(task_name).is_some()); - } - - pub fn monitor(&self) -> watch::Receiver { - self.sender.subscribe() - } -} - -impl Default for HealthMonitor { - fn default() -> Self { - Self::new() - } -} - -impl std::fmt::Display for SystemStatus { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - SystemStatus::Normal => write!(f, "normal"), - SystemStatus::OutOfDate => write!(f, "out of date"), - SystemStatus::Updating => write!(f, "updating"), - SystemStatus::Critical(_) => write!(f, "critical"), - } - } -} - -impl std::fmt::Display for CriticalReason { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - CriticalReason::HighMemoryUsage => write!(f, "high memory usage"), - CriticalReason::HighCpuUsage => write!(f, "high cpu usage"), - CriticalReason::HighDiskUsage => write!(f, "high disk usage"), - } - } -} diff --git a/agent/src/info.rs b/agent/src/info.rs deleted file mode 100644 index 4cbfd07..0000000 --- a/agent/src/info.rs +++ /dev/null @@ -1,87 +0,0 @@ -//! System info - -use std::{sync::Mutex, time::Duration}; - -use anyhow::Context; -use sysinfo::{CpuRefreshKind, SystemExt}; - -use crate::debian; - -pub struct Info { - system: sysinfo::System, - updates: Vec, -} - -impl Info { - pub fn new() -> Self { - Self { - system: sysinfo::System::new(), - updates: Vec::new(), - } - } - - pub fn refresh_resources(&mut self) { - self.system.refresh_specifics( - sysinfo::RefreshKind::new() - .with_disks_list() - .with_memory() - .with_cpu(CpuRefreshKind::new().with_cpu_usage()), - ); - } - - pub fn refresh_updates(&mut self) -> anyhow::Result<()> { - debian::update_package_index().context("while fetching the package index")?; - - let updates = - debian::get_available_updates().context("while fetching available updates")?; - - self.updates = updates; - - Ok(()) - } - - pub fn system(&self) -> &sysinfo::System { - &self.system - } - - pub fn updates(&self) -> &Vec { - &self.updates - } -} - -impl Default for Info { - fn default() -> Self { - Self::new() - } -} - -/// Spawns a new thread that forever gathers system information. -pub fn spawn_info_subsystem() -> &'static Mutex { - const REFRESH_RESOURCES_INTERVAL: Duration = Duration::from_secs(5); - const REFRESH_UPDATES_INTERVAL: Duration = Duration::from_secs(3600); - - let info = Box::new(Mutex::new(Info::new())); - let info = Box::leak(info); - - std::thread::spawn(|| loop { - tracing::debug!("refreshing system resources"); - - #[allow(clippy::mut_mutex_lock)] - info.lock().unwrap().refresh_resources(); - - std::thread::sleep(REFRESH_RESOURCES_INTERVAL); - }); - - std::thread::spawn(|| loop { - tracing::debug!("refreshing available system updates"); - - #[allow(clippy::mut_mutex_lock)] - if let Err(err) = info.lock().unwrap().refresh_updates() { - tracing::warn!(?err, "failed to refresh updates"); - } - - std::thread::sleep(REFRESH_UPDATES_INTERVAL); - }); - - info -} diff --git a/agent/src/lib.rs b/agent/src/lib.rs deleted file mode 100644 index e43b076..0000000 --- a/agent/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod config; -pub mod debian; -pub mod health; -pub mod info; -pub mod pty; -pub mod self_update; -pub mod server; -pub mod task; diff --git a/agent/src/main.rs b/agent/src/main.rs new file mode 100644 index 0000000..c90146c --- /dev/null +++ b/agent/src/main.rs @@ -0,0 +1,107 @@ +use async_nats as nats; +use nats::{Client, ConnectOptions}; +use tracing::Level; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let subscriber = tracing_subscriber::fmt() + .with_max_level(Level::TRACE) + .finish(); + + tracing::subscriber::set_global_default(subscriber) + .expect("to set a tracing global subscriber"); + + let client = ConnectOptions::new() + .name("Prymn Agent demo_agent") + .custom_inbox_prefix("_INBOX_demo_agent") + .user_and_password("demo_agent".to_owned(), "demo_agent_password".to_owned()) + .connect("localhost") + .await + .map_err(|err| err)?; + + tracing::info!("connected to nats server"); + wait_for_commands(client).await; + Ok(()) +} + +async fn wait_for_commands(_client: Client) { + // let mut sub = client + // .subscribe("agents.v1.demo_agent.cmd.*") + // .await + // .unwrap(); + // + // let mut command_queue = CommandQueue::default(); + // + // while let Some(msg) = sub.next().await { + // let suffix = msg.subject.trim_start_matches("agents.v1.demo_agent.cmd."); + // + // match suffix { + // "end" => { + // let key = std::str::from_utf8(&msg.payload).unwrap(); + // command_queue.end_command(key); + // } + // key => { + // if let Some(mut receiver) = command_queue.add_command(key) { + // tokio::spawn(async move { + // while let Ok(()) = receiver.changed().await { + // let queue = receiver.borrow(); + // while let Some(cmd) = queue.lock().unwrap().pop_back() { + // handle_command(cmd); + // } + // } + // }); + // } + // } + // } + // } +} +// +// fn handle_command(cmd: Command) { +// println!("{cmd:?}"); +// } +// +// #[derive(Default)] +// struct CommandQueue(HashMap>>>); +// +// impl CommandQueue { +// pub fn add_command(&mut self, key: &str) -> Option>>> { +// match self.0.get_mut(key) { +// Some(sender) => { +// sender.send_modify(|q| q.lock().unwrap().push_back(Command::Foo)); +// None +// } +// None => { +// let (sender, receiver) = watch::channel(Mutex::new(VecDeque::new())); +// sender.send_modify(|q| q.lock().unwrap().push_back(Command::Foo)); +// Some(receiver) +// } +// } +// } +// +// pub fn end_command(&mut self, key: &str) { +// self.0.remove(key); +// } +// } +// +// mod cmd { +// // use std::borrow::Cow; +// +// #[derive(Debug, Clone)] +// pub enum Command { +// Foo, +// } +// +// #[derive(Debug)] +// pub struct UnknownCommand<'a>(&'a str); +// +// impl<'a> TryFrom<&'a str> for Command { +// type Error = UnknownCommand<'a>; +// +// fn try_from(cmd: &'a str) -> Result { +// match cmd { +// "foo" => Ok(Command::Foo), +// _ => Err(UnknownCommand(cmd)), +// } +// } +// } +// } diff --git a/agent/src/pty.rs b/agent/src/pty.rs deleted file mode 100644 index e1f3ea6..0000000 --- a/agent/src/pty.rs +++ /dev/null @@ -1,166 +0,0 @@ -use std::{io, task::ready}; - -use rustix::{ - fd::OwnedFd, - fs::{fcntl_getfl, fcntl_setfl, OFlags}, - process::{ioctl_tiocsctty, setsid}, - pty::{grantpt, ioctl_tiocgptpeer, openpt, unlockpt, OpenptFlags}, - stdio::{dup2_stderr, dup2_stdin, dup2_stdout}, - termios::{tcsetwinsize, Winsize}, -}; -use tokio::{ - io::{unix::AsyncFd, AsyncRead, AsyncWrite}, - process::Child, -}; - -#[derive(Debug)] -pub struct Pty { - fd: AsyncFd, -} - -impl Pty { - pub fn open() -> io::Result { - let master = openpt(OpenptFlags::RDWR | OpenptFlags::NOCTTY | OpenptFlags::CLOEXEC)?; - grantpt(&master)?; - unlockpt(&master)?; - - // Set nonblocking - let flags = fcntl_getfl(&master)?; - fcntl_setfl(&master, flags | OFlags::NONBLOCK)?; - - let fd = AsyncFd::new(master)?; - - Ok(Self { fd }) - } - - pub fn child(&self) -> io::Result { - // NOTE: Linux v4.13 and above - let fd = ioctl_tiocgptpeer(&self.fd, OpenptFlags::RDWR | OpenptFlags::NOCTTY)?; - let child = PtyChild { fd }; - - Ok(child) - } - - pub fn resize_window(&self, rows: u16, cols: u16) -> io::Result<()> { - let winsize = Winsize { - ws_row: rows, - ws_col: cols, - ws_xpixel: 0, - ws_ypixel: 0, - }; - - tcsetwinsize(&self.fd, winsize)?; - - Ok(()) - } - - pub fn try_clone(&self) -> io::Result { - let fd = self.fd.get_ref().try_clone()?; - - Ok(Pty { - fd: AsyncFd::new(fd)?, - }) - } -} - -impl AsyncRead for Pty { - fn poll_read( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - buf: &mut tokio::io::ReadBuf<'_>, - ) -> std::task::Poll> { - loop { - let mut guard = ready!(self.fd.poll_read_ready(cx)?); - - match guard.try_io(|inner| { - let fd = inner.get_ref(); - let n = rustix::io::read(fd, buf.initialize_unfilled())?; - buf.advance(n); - - Ok(()) - }) { - Ok(result) => return std::task::Poll::Ready(result), - Err(_would_block) => continue, - } - } - } -} - -impl AsyncWrite for Pty { - fn poll_write( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - buf: &[u8], - ) -> std::task::Poll> { - loop { - let mut guard = ready!(self.fd.poll_write_ready(cx))?; - - match guard.try_io(|inner| Ok(rustix::io::write(inner.get_ref(), buf)?)) { - Ok(result) => return std::task::Poll::Ready(result), - Err(_would_block) => continue, - } - } - } - - fn poll_flush( - self: std::pin::Pin<&mut Self>, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - std::task::Poll::Ready(Ok(())) - } - - fn poll_shutdown( - self: std::pin::Pin<&mut Self>, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - std::task::Poll::Ready(Ok(())) - } -} - -#[derive(Debug)] -pub struct PtyChild { - fd: OwnedFd, -} - -impl PtyChild { - pub fn login_tty(&self) -> io::Result<()> { - setsid()?; - ioctl_tiocsctty(&self.fd)?; - dup2_stdin(&self.fd)?; - dup2_stdout(&self.fd)?; - dup2_stderr(&self.fd)?; - - Ok(()) - } -} - -pub fn open_shell(pty_child: PtyChild) -> io::Result { - let mut cmd = tokio::process::Command::new("/bin/bash"); - - unsafe { - cmd.pre_exec(move || { - pty_child.login_tty()?; - Ok(()) - }); - } - - cmd.spawn() -} - -#[cfg(test)] -mod test { - use rustix::fd::AsRawFd; - - use super::*; - - #[tokio::test] - async fn can_open_pty() { - let pty = Pty::open().unwrap(); - let child = pty.child().unwrap(); - - let master_fd = pty.fd.get_ref().as_raw_fd(); - let child_fd = child.fd.as_raw_fd(); - - assert!(master_fd != child_fd); - } -} diff --git a/agent/src/self_update.rs b/agent/src/self_update.rs deleted file mode 100644 index 84bc248..0000000 --- a/agent/src/self_update.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::{fs::File, io::Write, os::unix::prelude::PermissionsExt, path::Path, process::Command}; - -use anyhow::Context; -use reqwest::{blocking::Client, StatusCode}; -use serde::Deserialize; - -use crate::config; - -const PRYMN_PATH: &str = "/usr/local/bin/prymn_agent"; - -pub fn install(token: &str) -> anyhow::Result<()> { - let this_exe = std::env::current_exe()?; - - copy_binary(&this_exe, Path::new(PRYMN_PATH)).with_context(|| { - format!( - "could not copy the file {} to the destination {PRYMN_PATH}", - this_exe.to_str().unwrap(), - ) - })?; - - install_service_file(Path::new("/etc/systemd/system/prymn.service")) - .context("could not install the agent daemon service")?; - - register_to_backend(token).context("could not register the agent")?; - - Ok(()) -} - -fn copy_binary(src: &Path, dest: &Path) -> anyhow::Result<()> { - if dest.exists() { - // unlink the potentially running binary - std::fs::remove_file(dest)?; - } - - std::fs::copy(src, dest)?; - - let mut perms = dest.metadata()?.permissions(); - perms.set_mode(0o755); - std::fs::set_permissions(dest, perms)?; - - Ok(()) -} - -fn install_service_file(dest: &Path) -> anyhow::Result<()> { - let mut file = File::create(dest)?; - write!( - file, - r#" -[Unit] -Description=Prymn Agent Service -After=network.target - -[Service] -ExecStart={PRYMN_PATH} -Type=simple -Restart=always - -[Install] -WantedBy=default.target -"# - )?; - - if !Command::new("systemctl") - .arg("daemon-reload") - .status()? - .success() - { - anyhow::bail!("command exit with non-zero exit code; could not reload systemd daemon"); - } - - if !Command::new("systemctl") - .arg("enable") - .arg("--now") - .arg("prymn.service") - .status()? - .success() - { - anyhow::bail!("command exit with non-zero exit code; could not enable systemd service"); - } - - Ok(()) -} - -fn register_to_backend(token: &str) -> anyhow::Result<()> { - let client = Client::new(); - let response = client - .post(format!( - "{}/api/v1/servers/register", - config::CONFIG.backend_url - )) - .json(&serde_json::json!({ "token": token })) - .send()?; - - // TODO: When the backend API is established more concretely, change this to something better. - #[derive(Deserialize)] - struct ApiError { - errors: serde_json::Value, - } - - match response.status() { - StatusCode::UNPROCESSABLE_ENTITY => { - let error = response.json::()?; - anyhow::bail!( - "request was unsuccessful: the backend received invalid data: {}", - error.errors.to_string() - ) - } - status if !status.is_success() => { - anyhow::bail!("request was unsuccessful: error {}", status) - } - _ => Ok(()), - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn copy_binary_works() { - let temp_dir = std::env::temp_dir(); - // let temp_dir = tempdir().unwrap(); - let file1_path = temp_dir.join("file1"); - let mut file1 = File::create(&file1_path).unwrap(); - let file2_path = temp_dir.join("file2"); - let mut file2 = File::create(&file2_path).unwrap(); - - writeln!(file1, "old data").unwrap(); - writeln!(file2, "new data").unwrap(); - - copy_binary(&file2_path, &file1_path).expect("could not copy file"); - - let perms = file1_path - .metadata() - .expect("could not retrieve metadata") - .permissions(); - - let new_data = std::fs::read_to_string(file1_path).unwrap(); - - assert_eq!(new_data, "new data\n"); - assert!(perms.mode() & 0o755 == 0o755); - } -} diff --git a/agent/src/server/agent.rs b/agent/src/server/agent.rs deleted file mode 100644 index 9c9d405..0000000 --- a/agent/src/server/agent.rs +++ /dev/null @@ -1,224 +0,0 @@ -use std::{pin::Pin, process::Stdio, sync::Mutex}; - -use tokio::{io::AsyncWriteExt, process::Command}; -use tokio_stream::{ - wrappers::{ReceiverStream, WatchStream}, - Stream, StreamExt, -}; -use tokio_util::codec::{BytesCodec, FramedRead}; -use tonic::{Request, Response, Status, Streaming}; - -use crate::{ - debian, - health::HealthMonitor, - info::Info, - pty::{open_shell, Pty}, - task::TaskBuilder, -}; - -use super::proto::*; - -type AgentResult = std::result::Result, Status>; - -pub struct AgentService<'a> { - pub health: HealthMonitor, - pub info: &'a Mutex, // TODO: Find a way to remove the Mutex dependency here -} - -#[tonic::async_trait] -impl agent_server::Agent for AgentService<'static> { - type HealthStream = Pin> + Send>>; - - async fn health(&self, _: Request<()>) -> AgentResult { - let receiver = self.health.monitor(); - let version = env!("CARGO_PKG_VERSION"); - - let output = WatchStream::new(receiver).map(|health| { - Ok(HealthResponse { - version: version.to_owned(), - system: Some(health.system().into()), - tasks: health - .tasks() - .iter() - .map(|(k, v)| (k.clone(), v.into())) - .collect(), - }) - }); - - Ok(Response::new(Box::pin(output))) - } - - async fn get_sys_info(&self, _: Request<()>) -> AgentResult { - Ok(Response::new(SysInfoResponse::from( - &*self.info.lock().unwrap(), - ))) - } - - type SysUpdateStream = Pin> + Send>>; - - async fn sys_update( - &self, - req: Request, - ) -> AgentResult { - let dry_run = req.get_ref().dry_run; - - let mut receiver = - TaskBuilder::new("system update".to_owned()).health_monitor(self.health.clone()); - - if dry_run { - receiver = receiver - .add_step(async { Ok("simulating a system update...".to_owned()) }) - .add_step(async { - const DUR: std::time::Duration = std::time::Duration::from_secs(5); - tokio::time::sleep(DUR).await; - Ok("completed running an artifical delay...".to_owned()) - }); - } - - let receiver = receiver - .add_step(async move { - tokio::task::spawn_blocking(move || { - let output = debian::run_updates(dry_run).map_err(|err| { - tracing::error!(%err, "failed to run updates"); - err - })?; - - let out = if !output.status.success() { - tracing::error!(?output, "child process exited unsuccessfuly"); - - match output.status.code() { - Some(exit_code) => Err(Status::internal(format!( - "operation exited with error (code {exit_code})" - ))), - None => Err(Status::cancelled("operation was cancelled by signal")), - } - } else { - Ok(String::from_utf8_lossy(output.stdout.as_slice()).to_string()) - }; - - // TODO: We could split the output by lines and emit those as "steps" so the - // upgrade process is more interactive - out - }) - .await - .unwrap() - }) - .build() - .into_background(); - - let stream = ReceiverStream::new(receiver).map(|output| { - output - .map(|output| SysUpdateResponse { - output, - progress: 1, - }) - .map_err(|err| Status::internal(err.to_string())) - }); - - Ok(Response::new(Box::pin(stream))) - } - - type ExecStream = Pin> + Send>>; - - async fn exec(&self, req: Request) -> AgentResult { - use exec_response::Out; - - let ExecRequest { - user, - program, - args, - } = req.get_ref(); - - if user.is_empty() { - return Err(Status::invalid_argument("you must specify a user")); - } - - if program.is_empty() { - return Err(Status::invalid_argument("you must specify a program")); - } - - let mut command = if user != "root" { - let mut cmd = Command::new("sudo"); - cmd.arg("-iu").arg(user).arg("--").arg(program); - cmd - } else { - Command::new(program) - }; - - let mut io = command - .args(args) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; - - let stdout = FramedRead::new(io.stdout.take().unwrap(), BytesCodec::new()).map(|stdout| { - let stdout = stdout.unwrap(); - Out::Stdout(String::from_utf8_lossy(&stdout[..]).to_string()) - }); - - let stderr = FramedRead::new(io.stderr.take().unwrap(), BytesCodec::new()).map(|stderr| { - let stderr = stderr.unwrap(); - Out::Stderr(String::from_utf8_lossy(&stderr[..]).to_string()) - }); - - let exit = TaskBuilder::new(format!("exec {program}")) - .health_monitor(self.health.clone()) - .add_step(async move { io.wait().await.unwrap() }) - .build() - .into_stream(); - - let stream = stdout - .merge(stderr) - .chain(exit.map(|code| Out::ExitCode(code.code().unwrap_or_default()))) - .map(|out| Ok(ExecResponse { out: Some(out) })); - - Ok(Response::new(Box::pin(stream))) - } - - type TerminalStream = Pin> + Send>>; - - async fn terminal( - &self, - req: Request>, - ) -> AgentResult { - let mut in_stream = req.into_inner(); - let mut pty = Pty::open()?; - let pty_clone = pty.try_clone()?; - let pty_child = pty.child()?; - let mut child = open_shell(pty_child)?; - - tokio::spawn(async move { - // TODO: Handle errors inside here - while let Some(result) = in_stream.next().await { - match result { - Ok(req) => { - if let Some(resize) = req.resize { - pty.resize_window(resize.rows as u16, resize.cols as u16) - .unwrap(); - } - - pty.write_all(&req.input[..]).await.unwrap(); - } - Err(err) => { - // Log and ignore the error... - tracing::warn!(%err, "received an incoming stream error"); - } - } - } - - // TODO: Maybe there's a more graceful way to stop the process? - child.kill().await.unwrap(); - }); - - let out_stream = FramedRead::new(pty_clone, BytesCodec::new()).map(|inner| { - inner - .map(|b| TerminalResponse { output: b.to_vec() }) - .map_err(|err| { - tracing::error!(%err, "read error on pseudoterminal"); - Status::internal("terminal read error") - }) - }); - - Ok(Response::new(Box::pin(out_stream))) - } -} diff --git a/agent/src/server/mod.rs b/agent/src/server/mod.rs deleted file mode 100644 index fb015b5..0000000 --- a/agent/src/server/mod.rs +++ /dev/null @@ -1,128 +0,0 @@ -use std::time::Duration; - -use tokio::{signal, sync::oneshot}; -use tower_http::trace::TraceLayer; - -use crate::{ - health::HealthMonitor, - info, - server::{agent::AgentService, proto::agent_server}, -}; - -mod agent; -mod proto { - tonic::include_proto!("prymn"); - - impl From<&crate::health::SystemHealth> for SystemHealth { - fn from(val: &crate::health::SystemHealth) -> Self { - if let crate::health::SystemStatus::Critical(ref reasons) = val.status { - SystemHealth { - status: itertools::join(reasons.iter().map(ToString::to_string), ","), - } - } else { - SystemHealth { - status: val.status.to_string(), - } - } - } - } - - impl From<&crate::task::TaskStatus> for TaskHealth { - fn from(value: &crate::task::TaskStatus) -> Self { - Self { - started_on: value.started_on().to_string(), - progress: value.progress(), - } - } - } - - impl From<&crate::info::Info> for SysInfoResponse { - fn from(info: &crate::info::Info) -> Self { - use sysinfo::{CpuExt, DiskExt, SystemExt}; - - let system = info.system(); - - let cpus = system - .cpus() - .iter() - .map(|cpu| sys_info_response::Cpu { - freq_mhz: cpu.frequency(), - usage: cpu.cpu_usage(), - }) - .collect(); - - let disks = system - .disks() - .iter() - .map(|disk| sys_info_response::Disk { - name: disk.name().to_string_lossy().into_owned(), - total_bytes: disk.total_space(), - avail_bytes: disk.available_space(), - mount_point: disk.mount_point().to_string_lossy().into_owned(), - }) - .collect(); - - Self { - uptime: system.uptime(), - hostname: system.host_name().unwrap_or_default(), - os: system.long_os_version().unwrap_or_default(), - mem_total_bytes: system.total_memory(), - mem_avail_bytes: system.available_memory(), - swap_total_bytes: system.total_swap(), - swap_free_bytes: system.free_swap(), - updates_available: info.updates().len() as u32, - cpus, - disks, - } - } - } -} - -/// Run the server. This is the main entry point of the application. -#[tokio::main] -pub async fn run() -> anyhow::Result<()> { - let (shutdown_tx, shutdown_rx) = oneshot::channel(); - - // Listen for shutdown signals - tokio::spawn(async { - signal::ctrl_c() - .await - .expect("failed to listen to a ctrl-c signal"); - - let _ = shutdown_tx.send(()); - }); - - let info = info::spawn_info_subsystem(); - let health_monitor = HealthMonitor::new(); - - // Monitor system info forever - // TODO: Maybe we can move it inside the server response function? - // We could spawn a new loop whenever we need it, but the problem is when does it get - // destroyed? - { - let health_monitor = health_monitor.clone(); - tokio::spawn(async move { - loop { - health_monitor.check_system_info(&info.lock().unwrap()); - tokio::time::sleep(Duration::from_secs(1)).await; - } - }); - } - - let agent_service = agent_server::AgentServer::new(AgentService { - health: health_monitor.clone(), - info, - }); - - let addr = "[::]:50012".parse()?; - tracing::info!("listening on {}", addr); - tonic::transport::Server::builder() - .layer(TraceLayer::new_for_grpc()) - .add_service(agent_service) - .serve_with_shutdown(addr, async { - let _ = shutdown_rx.await; - }) - .await?; - - Ok(()) -} diff --git a/agent/src/task.rs b/agent/src/task.rs deleted file mode 100644 index 323c6ea..0000000 --- a/agent/src/task.rs +++ /dev/null @@ -1,154 +0,0 @@ -//! A task is an atomic executing routine that the agent is running, potentially in the background. -//! The task is tracked by the system monitor. - -// TODO: Take a look at futures::stream::FuturesOrdered -// It is used to store futures in an ordered fashion, and it also implements Stream - -use std::{ - future::Future, - pin::Pin, - task::{Context, Poll}, -}; - -use chrono::{DateTime, Utc}; -use tokio::sync::{mpsc, watch}; -use tokio_stream::{Stream, StreamExt}; - -use super::health::HealthMonitor; - -#[derive(Clone, Default)] -pub struct TaskStatus { - started_on: DateTime, - curr_step: usize, - max_steps: usize, -} - -impl TaskStatus { - /// Returns the task progress as a percentage value - pub fn progress(&self) -> f32 { - 100.0 * (self.curr_step as f32 / self.max_steps as f32) - } - - /// Returns the datetime when this task began executing - pub fn started_on(&self) -> &DateTime { - &self.started_on - } - - fn next_step(&mut self) { - if self.curr_step < self.max_steps { - self.curr_step += 1; - } - } -} - -type BoxFuture = Pin + Send>>; - -pub struct TaskBuilder { - task: Task, -} - -impl TaskBuilder { - pub fn new(name: String) -> Self { - let (sender, _) = watch::channel(TaskStatus::default()); - - Self { - task: Task { - name, - health_monitor: None, - status_channel: sender, - steps: Vec::new(), - }, - } - } - - /// Attaches a health monitor to notify the health system on progress made. - pub fn health_monitor(mut self, health_monitor: HealthMonitor) -> Self { - self.task.health_monitor = Some(health_monitor); - self - } - - pub fn build(self) -> Task { - self.task - } -} - -impl TaskBuilder> { - pub fn add_step(mut self, step: impl Future + Send + 'static) -> Self { - self.task.add_step(step); - self - } -} - -pub struct Task { - name: String, - health_monitor: Option, - status_channel: watch::Sender, - steps: Vec, -} - -impl Task> { - fn add_step(&mut self, step: impl Future + Send + 'static) { - self.steps.push(Box::pin(step)) - } - - /// Turn this Task into an object that implements [Stream]. - /// - /// The new stream will output each step's future output. - pub fn into_stream(self) -> TaskStream { - if let Some(health) = &self.health_monitor { - health.track_task(self.name.clone(), self.status_channel.subscribe()); - } - - // Immediately notify the initial status (step 0) - self.status_channel.send_replace(TaskStatus { - started_on: Utc::now(), - curr_step: 0, - max_steps: self.steps.len(), - }); - - TaskStream { inner: self } - } - - /// Run this task concurrently in the background. - /// - /// Returns a [mpsc::Receiver] which receives the returned values of each step's future - /// output. - pub fn into_background(self) -> mpsc::Receiver { - let (sender, receiver) = mpsc::channel(10); - - tokio::spawn(async move { - let mut stream = self.into_stream(); - while let Some(value) = stream.next().await { - let _ = sender.send(value).await; - } - }); - - receiver - } -} - -pub struct TaskStream { - inner: Task>, -} - -impl Stream for TaskStream { - type Item = T; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match self.inner.steps.get_mut(0) { - Some(fut) => match fut.as_mut().poll(cx) { - Poll::Ready(value) => { - self.inner.steps.remove(0); - - self.inner - .status_channel - .send_modify(|task| task.next_step()); - - Poll::Ready(Some(value)) - } - Poll::Pending => Poll::Pending, - }, - None => Poll::Ready(None), - } - } -} diff --git a/agent/tests/task_health.rs b/agent/tests/task_health.rs deleted file mode 100644 index 7d1f5d6..0000000 --- a/agent/tests/task_health.rs +++ /dev/null @@ -1,18 +0,0 @@ -use prymn_agent::{health::HealthMonitor, task::TaskBuilder}; - -#[tokio::test] -async fn task_is_gone_from_health_monitor_when_complete() { - let health_monitor = HealthMonitor::new(); - let health_recv = health_monitor.monitor(); - - let mut task_recv = TaskBuilder::new("test task".to_owned()) - .health_monitor(health_monitor) - .add_step(async { "foo" }) - .add_step(async { "bar" }) - .build() - .into_background(); - - assert_eq!(task_recv.recv().await.unwrap(), "foo"); - assert_eq!(task_recv.recv().await.unwrap(), "bar"); - assert!(health_recv.borrow().tasks().is_empty()); -}