diff --git a/.gitignore b/.gitignore index 340e171..40dd2ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /target .idea -Dockerfile Cargo.lock -settings.json \ No newline at end of file +hagent_test.sock \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index a9efa2c..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1089 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -# It is not intended for manual editing -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "bytes" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" - -[[package]] -name = "cc" -version = "1.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" -dependencies = [ - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-targets", -] - -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "env_filter" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", -] - -[[package]] -name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core 0.52.0", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "inotify" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" -dependencies = [ - "bitflags 1.3.2", - "futures-core", - "inotify-sys", - "libc", - "tokio", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "libc" -version = "0.2.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" - -[[package]] -name = "libloading" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" -dependencies = [ - "cfg-if", - "windows-targets", -] - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" -dependencies = [ - "hermit-abi", - "libc", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "object" -version = "0.36.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "pcap" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "499125886165f62fbc0c095ead9189b253f48eb1c5fcab49f81a270f2f220652" -dependencies = [ - "bitflags 1.3.2", - "errno", - "libc", - "libloading", - "pkg-config", - "regex", - "windows-sys 0.36.1", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pkg-config" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redis" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d7a6955c7511f60f3ba9e86c6d02b3c3f144f8c24b288d1f4e18074ab8bbec" -dependencies = [ - "combine", - "itoa", - "percent-encoding", - "ryu", - "sha1_smol", - "socket2", - "url", -] - -[[package]] -name = "redox_syscall" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "regex" -version = "1.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "runner-rs" -version = "0.9.25" -dependencies = [ - "anyhow", - "chrono", - "env_logger", - "inotify", - "log", - "pcap", - "redis", - "serde", - "serde_json", - "sysinfo", - "tokio", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.208" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.208" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.125" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "sha1_smol" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "syn" -version = "2.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sysinfo" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ae3f4f7d64646c46c4cae4e3f01d1c5d255c7406fdd7c7f999a94e488791" -dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", - "rayon", - "windows", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.39.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "wasi" -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.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" -dependencies = [ - "windows-core 0.57.0", - "windows-targets", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-core" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", - "windows-targets", -] - -[[package]] -name = "windows-implement" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-result" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index 67d68e7..5b477a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,12 @@ -[package] -name = "runner-rs" -version = "0.9.25" -edition = "2021" +[workspace] +resolver = "2" +members = [ + "noxis-rs", + "noxis-cli", +] [profile.dev] debug = true -[dependencies] -anyhow = "1.0.93" -chrono = "0.4.38" -env_logger = "0.11.3" -inotify = "0.10.2" -log = "0.4.22" -pcap = "2.2.0" -redis = "0.25.4" -serde = { version = "1.0.203", features = ["derive"] } -serde_json = "1.0.118" -sysinfo = "0.32.0" -tokio = { version = "1.38.0", features = ["full", "time"] } +[profile.test] +debug = false diff --git a/README.md b/README.md index b4fa045..449db98 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ -# runner-rs ( with amd64 and riscv64 support ) -![Logo](https://blog.desdelinux.net/wp-content/uploads/2023/07/rust-logo.png) -in-container integrating util to handle processes runtime - +# noxis-rs +![Logo](logo.png) +### In-container integrating util to handle processes runtime +( with amd64 and riscv64 support ) ## Depends on - `rustup (>=1.27.1)` - `gcc-riscv64-unknown-elf` - `build-essential` +- `gcc-riscv64-linux-gnu` +- `binutils-riscv64-linux-gnu` + ## Setting up Download and execute rustup.sh @@ -29,7 +32,7 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh cd runner-rs/ && rustup target add riscv64gc-unknown-linux-gnu && rustup target add x86_64-unknown-linux-gnu ~~~ > [!NOTE] -> Cargo is configured to build an app for amd64/linux defaultly. RISC-based compilation is optional. +> Cargo is configured to build an app for amd64/linux defaultly. RISCV-based compilation is optional. 3.1. Release build of app for amd64/linux diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..b8424ef Binary files /dev/null and b/logo.png differ diff --git a/noxis-cli/Cargo.toml b/noxis-cli/Cargo.toml new file mode 100644 index 0000000..22666eb --- /dev/null +++ b/noxis-cli/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "noxis-cli" +version = "0.1.6" +edition = "2021" + +[dependencies] +anyhow = "1.0.94" +clap = { version = "4.5.22", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } +serde_json = "1.0.133" +tokio = { version = "1.42.0", features = ["full", "net"] } diff --git a/noxis-cli/src/cli.rs b/noxis-cli/src/cli.rs new file mode 100644 index 0000000..677e721 --- /dev/null +++ b/noxis-cli/src/cli.rs @@ -0,0 +1,145 @@ +use clap::{Parser, Subcommand}; + +#[derive(Debug, Parser)] +pub struct Cli { + #[command( + subcommand, + help = "to manage Noxis work", + )] + command : Commands, +} + +#[derive(Debug, Subcommand)] +pub enum Commands { + #[command( + about = "To get info about current Noxis status", + )] + Status, + #[command( + about = "To start Noxis process", + )] + Start(StartAction), + #[command( + about = "To stop Noxis process", + )] + Stop, + #[command( + about = "To restart Noxis process", + )] + Restart(StartAction), + #[command( + about = "To get list of processes that are being monitoring", + )] + Processes, + // process command + #[command( + about = "To manage current process that is being monitoring", + )] + Process(ProcessCommand), + // config command = + #[command( + about = "To manage config settings", + )] + Config(ConfigCommand), +} + +#[derive(Debug, Parser)] +pub struct StartAction { + #[arg( + long="with-flags", + num_args = 1.., + value_delimiter = ' ' + )] + flags : Vec, +} + +#[derive(Debug, Parser)] +pub struct ConfigCommand { + #[command(subcommand)] + action : ConfigAction, +} + +#[derive(Debug, Subcommand)] +pub enum ConfigAction { + #[command( + about = "To change current Noxis configuration", + )] + Local(LocalConfig), + #[command( + about = "To change credentials of the remote config server", + )] + Remote, + #[command( + about = "To reset all config settings", + )] + Reset, +} + +#[derive(Debug, Parser)] +pub struct LocalConfig { + // flag + #[arg( + long = "json", + action, + help = "to read following input as JSON", + )] + is_json : bool, + // value + #[arg( + help = "path to config file or config String (with --json flag)", + )] + config : String, +} + +#[derive(Debug, Parser)] +pub struct ProcessCommand { + #[arg( + help = "name of needed process", + )] + process : String, + #[command( + subcommand, + help = "To get current process's status", + )] + action : ProcessAction, +} + +#[derive(Debug, Subcommand)] +enum ProcessAction { + #[command( + about = "To get info about current process status", + )] + Status, + #[command( + about = "To start current process", + )] + Start, + #[command( + about = "To stop current process", + )] + Stop, + #[command( + about = "To freeze (hybernaze) current process", + )] + Freeze, + #[command( + about = "To unfreeze (unhybernaze) current process", + )] + Unfreeze, + #[command( + about = "To restart current process", + )] + Restart, + #[command( + about = "To get info about current process's dependencies", + )] + Deps, + #[command( + about = "To get info about current process's files-dependencies", + )] + Files, + #[command( + about = "To get info about current process's services-dependencies", + )] + Services, +} \ No newline at end of file diff --git a/noxis-cli/src/lib.rs b/noxis-cli/src/lib.rs new file mode 100644 index 0000000..163fc0a --- /dev/null +++ b/noxis-cli/src/lib.rs @@ -0,0 +1,3 @@ +mod cli; + +pub use cli::*; \ No newline at end of file diff --git a/noxis-cli/src/main.rs b/noxis-cli/src/main.rs new file mode 100644 index 0000000..718ec2f --- /dev/null +++ b/noxis-cli/src/main.rs @@ -0,0 +1,16 @@ +mod cli; +mod net; + +use clap::Parser; +use cli::Cli; +use net::{create_tcp_stream, try_send}; +use anyhow::Result; + +#[tokio::main] +async fn main() -> Result<()>{ + let cli = Cli::parse(); + dbg!(&cli); + // println!("{:?}", cli); + try_send(create_tcp_stream().await, cli).await?; + Ok(()) +} diff --git a/noxis-cli/src/net.rs b/noxis-cli/src/net.rs new file mode 100644 index 0000000..1c2e470 --- /dev/null +++ b/noxis-cli/src/net.rs @@ -0,0 +1,27 @@ +use tokio::net::TcpStream; +use tokio::io::AsyncWriteExt; +use tokio::time::{Duration, sleep}; +use anyhow::Result; +use super::Cli; + + +pub async fn create_tcp_stream() -> Result { + let stream = TcpStream::connect("127.0.0.1:7753").await?; + Ok(stream) +} + +pub async fn try_send(stream: Result, params: Cli) -> Result<()> { + let mut stream = stream?; + loop { + if stream.writable().await.is_err() { + sleep(Duration::from_millis(100)).await; + continue; + } + let msg = format!("{:?}", params); + // let msg = r"HTTP/1.1 POST\r\nContent-Length: 14\r\nContent-Type: text/plain\r\n\r\nHello, World!@"; + stream.write_all(msg.as_bytes()).await?; + // ... + break; + } + Ok(()) +} \ No newline at end of file diff --git a/noxis-rs/Cargo.toml b/noxis-rs/Cargo.toml new file mode 100644 index 0000000..cf86d18 --- /dev/null +++ b/noxis-rs/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "noxis-rs" +version = "0.11.3" +edition = "2021" + +[dependencies] +anyhow = "1.0.93" +chrono = "0.4.38" +clap = { version = "4.5.21", features = ["derive"] } +env_logger = "0.11.3" +inotify = "0.10.2" +log = "0.4.22" +pcap = "2.2.0" +redis = "0.25.4" +serde = { version = "1.0.203", features = ["derive"] } +serde_json = "1.0.118" +sysinfo = "0.32.0" +tokio = { version = "1.38.0", features = ["full", "time"] } diff --git a/Dockerfile b/noxis-rs/Dockerfile similarity index 100% rename from Dockerfile rename to noxis-rs/Dockerfile diff --git a/settings.json b/noxis-rs/settings.json similarity index 82% rename from settings.json rename to noxis-rs/settings.json index da6fa64..8fb8d10 100644 --- a/settings.json +++ b/noxis-rs/settings.json @@ -4,12 +4,12 @@ "processes": [ { "name": "temp-process", - "path": "/home/user/monitor/runner-rs/temp-process", + "path": "./temp-process", "dependencies": { "files": [ { "filename": "dep-file", - "src": "/home/user/monitor/runner-rs/tests/examples/", + "src": "./tests/examples/", "triggers": { "onDelete": "stop", "onChange": "stay" diff --git a/src/lib.rs b/noxis-rs/src/lib.rs similarity index 100% rename from src/lib.rs rename to noxis-rs/src/lib.rs diff --git a/src/main.rs b/noxis-rs/src/main.rs similarity index 75% rename from src/main.rs rename to noxis-rs/src/main.rs index 6f161d0..556521e 100644 --- a/src/main.rs +++ b/noxis-rs/src/main.rs @@ -1,27 +1,38 @@ mod options; mod utils; +use anyhow::Error; +use clap::Parser; use log::{error, info}; use options::config::*; use options::logger::setup_logger; use options::signals::set_valid_destructor; -use options::structs::*; +use options::structs::Processes; +use options::cli_pipeline::init_cli_pipeline; use std::sync::Arc; use std::time::Duration; use tokio::sync::mpsc; use utils::*; +use options::preboot::PrebootParams; #[tokio::main(flavor = "multi_thread")] -async fn main() { +async fn main() -> anyhow::Result<()>{ + let preboot = Arc::new(PrebootParams::parse().validate()?); + + // if let Err(_) = preboot { + // return; + // } + // let preboot = Arc::new(preboot); + let _ = setup_logger(); info!("Runner is configurating..."); // setting up redis connection \ // then conf checks to choose the most actual \ - let processes: Processes = get_actual_config().await.unwrap_or_else(|| { + let processes: Processes = get_actual_config(preboot.clone()).await.unwrap_or_else(|| { error!("No actual configuration for runner. Stopping..."); - std::process::exit(101); + std::process::exit(1); }); info!( @@ -32,7 +43,7 @@ async fn main() { if processes.processes.is_empty() { error!("Processes list is null, runner-rs initialization is stopped"); - return; + return Err(Error::msg("Empty processes segment in config")); } let mut handler: Vec> = vec![]; // is in need to send to the signals handler thread @@ -75,13 +86,18 @@ async fn main() { // remote config update subscription handler.push(tokio::spawn(async move { - let _ = subscribe_config_stream(Arc::new(processes)).await; + let _ = subscribe_config_stream(Arc::new(processes), preboot.clone()).await; + })); + + // cli pipeline + handler.push(tokio::spawn(async move { + let _ = init_cli_pipeline().await; })); for i in handler { let _ = i.await; } - return; + Ok(()) } // todo: integration tests diff --git a/src/options.rs b/noxis-rs/src/options.rs similarity index 73% rename from src/options.rs rename to noxis-rs/src/options.rs index d9f9b03..e53e2d0 100644 --- a/src/options.rs +++ b/noxis-rs/src/options.rs @@ -4,3 +4,5 @@ pub mod config; pub mod logger; pub mod signals; pub mod structs; +pub mod preboot; +pub mod cli_pipeline; \ No newline at end of file diff --git a/noxis-rs/src/options/cli_pipeline.rs b/noxis-rs/src/options/cli_pipeline.rs new file mode 100644 index 0000000..b189a36 --- /dev/null +++ b/noxis-rs/src/options/cli_pipeline.rs @@ -0,0 +1,60 @@ +use log::{error, info, warn}; +use tokio::net::{TcpListener, TcpStream}; +use anyhow::{Result as DynResult, Error}; +use tokio::time::{sleep, Duration}; +use std::{borrow::BorrowMut, net::{IpAddr, Ipv4Addr}}; +// use std::io::BufReader; +use tokio::io::{BufReader, AsyncWriteExt, AsyncBufReadExt}; + + +pub async fn init_cli_pipeline() -> DynResult<()> { + return match init_listener().await { + Some(list) => { + loop { + if let Ok((socket, addr)) = list.accept().await { + // isolation + if IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)) != addr.ip() { + warn!("Declined attempt to connect TCP-socket from {}", addr); + continue; + } + process_connection(socket).await; + } + sleep(Duration::from_millis(500)).await; + } + // Ok(()) + }, + None => Err(Error::msg("Addr 127.0.0.1:7753 is already in use")) + } +} + +async fn init_listener() -> Option { + return match TcpListener::bind("127.0.0.1:7753").await { + Ok(listener) => { + info!("Runner is listening localhost:7753"); + Some(listener) + }, + Err(_) => { + error!("Cannot create TCP listener for CLI"); + None + } + } +} + +async fn process_connection(mut stream: TcpStream) { + // loop{ + // stream. + // } + let buf_reader = BufReader::new(stream.borrow_mut()); + let mut rqst = buf_reader.lines(); + + + while let Ok(Some(line)) = rqst.next_line().await { + if line.is_empty() { + break; + } + println!("{}", line); + } + + let response = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\nContent-Type: text/plain\r\n\r\nHello, World!"; + stream.write_all(response.as_bytes()).await.unwrap(); +} diff --git a/src/options/config.rs b/noxis-rs/src/options/config.rs similarity index 86% rename from src/options/config.rs rename to noxis-rs/src/options/config.rs index 5f865ea..f7b5f26 100644 --- a/src/options/config.rs +++ b/noxis-rs/src/options/config.rs @@ -7,9 +7,11 @@ use std::os::unix::process::CommandExt; use std::process::Command; use std::sync::Arc; use std::{env, fs}; -use tokio::time::Duration; +use std::fmt::format; +use super::preboot::PrebootParams; +use tokio::time::{Duration, sleep}; -const CONFIG_PATH: &str = "settings.json"; +// const CONFIG_PATH: &str = "settings.json"; /// # Fn `load_processes` /// ## for reading and parsing *local* storing config @@ -46,43 +48,48 @@ fn load_processes(json_filename: &str) -> Option { /// /// *depends on* : struct `Processes` /// -pub async fn get_actual_config() -> Option { +pub async fn get_actual_config(params : Arc) -> Option { // * if no local conf -> loop and +inf getting conf from redis server // * if local conf -> once getting conf from redis server - match load_processes(CONFIG_PATH) { + let config_path = params.config.to_str()?; + info!("Configurating config module with params: no-remote-config={}, no-sub={}, local config path={:?}, remote server={}", params.no_remote_config, params.no_sub, params.config, params.remote_server_url); + match load_processes(config_path) { Some(local_conf) => { info!( "Found local configuration, version - {}", &local_conf.date_of_creation ); - if let Some(remote_conf) = - // TODO : rework with pubsub mech - once_get_remote_configuration(&format!("redis://{}/", local_conf.config_server)) - { - return match config_comparing(&local_conf, &remote_conf) { - ConfigActuality::Local => { - info!("Local config is actual"); - Some(local_conf) - } - ConfigActuality::Remote => { - info!("Pulled config is more actual. Saving changes!"); - if save_new_config(&remote_conf, CONFIG_PATH).is_err() { - error!("Saving changes process failed due to unexpected error...") + if !params.no_remote_config { + if let Some(remote_conf) = + // TODO : rework with pubsub mech + once_get_remote_configuration(&format!("redis://{}/", ¶ms.remote_server_url)) + { + return match config_comparing(&local_conf, &remote_conf) { + ConfigActuality::Local => { + info!("Local config is actual"); + Some(local_conf) } - Some(remote_conf) - } - }; + ConfigActuality::Remote => { + info!("Pulled config is more actual. Saving changes!"); + if save_new_config(&remote_conf, config_path).is_err() { + error!("Saving changes process failed due to unexpected error...") + } + Some(remote_conf) + } + }; + } } Some(local_conf) } None => { warn!("No local valid conf was found. Trying to pull remote one..."); - let mut conn = get_connection_watcher(&open_watcher("redis://localhost/")); - let remote_config = get_remote_conf_watcher(&mut conn).await; - if let Some(conf) = remote_config { - info!("Config {} was pulled from Redis-Server. Starting...", &conf.date_of_creation); - let _ = save_new_config(&conf, CONFIG_PATH); - return Some(conf); + if !params.no_remote_config { + let mut conn = get_connection_watcher(&open_watcher(&format!("redis://{}/", ¶ms.remote_server_url))); + if let Some(conf) = get_remote_conf_watcher(&mut conn).await { + info!("Config {} was pulled from Redis-Server. Starting...", &conf.date_of_creation); + let _ = save_new_config(&conf, config_path); + return Some(conf); + } } None } @@ -182,23 +189,23 @@ fn once_get_remote_configuration(serv_info: &str) -> Option { if remote.is_none() { error!("Pulled config is invalid. Check it in Redis Server"); } - return remote; + remote }, Err(_) => { error!("Cannot extract payload from new message. Check Redis Server state"); - return None; + None }, } }, Err(_) => { warn!("Cannot get config from Redis Server. Empty channel"); - return None; + None }, } }, Err(_) => { error!("Redis subscription process failed. Check Redis configuration!"); - return None; + None } } } @@ -311,8 +318,13 @@ fn restart_main_thread() -> std::io::Result<()> { /// /// *depends on* : `Processes` /// -pub async fn subscribe_config_stream(actual_prcs: Arc) -> Result<(), CustomError> { - if let Ok(client) = Client::open(format!("redis://{}/", &actual_prcs.config_server)) { +pub async fn subscribe_config_stream(actual_prcs: Arc, params: Arc) -> Result<(), CustomError> { + let config_path = params.config.to_str().unwrap_or_else(|| "settings.json"); + + if params.no_sub || params.no_remote_config { + return Err(CustomError::Fatal); + } + if let Ok(client) = Client::open(format!("redis://{}/", ¶ms.remote_server_url)) { if let Ok(mut conn) = client.get_connection() { match crate::utils::get_container_id() { Some(channel_name) => { @@ -330,8 +342,8 @@ pub async fn subscribe_config_stream(actual_prcs: Arc) -> Result<(), match config_comparing(&actual_prcs, &remote_config) { ConfigActuality::Remote => { warn!("Pulled config is actual. Saving and restarting..."); - if save_new_config(&remote_config, CONFIG_PATH).is_err() { - error!("Error with saving new config to {}. Stopping sub mechanism...", &CONFIG_PATH); + if save_new_config(&remote_config, config_path).is_err() { + error!("Error with saving new config to {}. Stopping sub mechanism...", config_path); return Err(CustomError::Fatal); } if restart_main_thread().is_err() { @@ -352,7 +364,7 @@ pub async fn subscribe_config_stream(actual_prcs: Arc) -> Result<(), }, } } - tokio::time::sleep(tokio::time::Duration::from_secs(30)).await; + sleep(Duration::from_secs(30)).await; } } else { error!("Cannot subscribe channel {}. Check Redis Server status", &channel_name); @@ -433,7 +445,7 @@ fn save_new_config(config: &Processes, config_file: &str) -> Result<(), CustomEr Err(_) => Err(CustomError::Fatal), } } - Err(_) => return Err(CustomError::Fatal), + Err(_) => Err(CustomError::Fatal), } } Err(_) => Err(CustomError::Fatal), diff --git a/src/options/logger.rs b/noxis-rs/src/options/logger.rs similarity index 74% rename from src/options/logger.rs rename to noxis-rs/src/options/logger.rs index 47ba570..14cd92c 100644 --- a/src/options/logger.rs +++ b/noxis-rs/src/options/logger.rs @@ -61,8 +61,27 @@ pub fn setup_logger() -> Result<(), crate::options::structs::CustomError> { #[cfg(test)] mod logger_tests { use super::*; + // #[test] + // fn setting_up_logger() { + // assert!(setup_logger().is_ok()); + // } + #[test] fn setting_up_logger() { - assert!(setup_logger().is_ok()); + Builder::new() + .format(move |buf, record| { + writeln!( + buf, + "|{}| {} [{}] - {}", + get_container_id().unwrap_or("NODE".to_string()).trim(), + Local::now().format("%d-%m-%Y %H:%M:%S"), + record.level(), + record.args(), + ) + }) + .filter(None, LevelFilter::Info) + .target(env_logger::Target::Stdout) + .is_test(true) + .init(); } } diff --git a/noxis-rs/src/options/preboot.rs b/noxis-rs/src/options/preboot.rs new file mode 100644 index 0000000..02e013f --- /dev/null +++ b/noxis-rs/src/options/preboot.rs @@ -0,0 +1,194 @@ +// module to handle pre-boot params of the monitor +use anyhow::{Result, Ok, Error}; +use clap::Parser; +use std::path::PathBuf; + +#[derive(clap::ValueEnum, Debug, Clone)] +pub enum MetricsPrebootParams { + Full, + System, + Processes, + Net, + None, +} + +impl std::fmt::Display for MetricsPrebootParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + MetricsPrebootParams::Full => write!(f, "full"), + MetricsPrebootParams::System => write!(f, "system"), + MetricsPrebootParams::Processes => write!(f, "processes"), + MetricsPrebootParams::Net => write!(f, "net"), + MetricsPrebootParams::None => write!(f, "none"), + } + } +} + +#[derive(Debug, Parser)] +pub struct PrebootParams { + // actions + #[arg( + long = "no-hagent", + action, + conflicts_with="socket_path", + help="To disable work with host-agent" + )] + pub no_hostagent : bool, + #[arg( + long = "no-logs", + action, + conflicts_with="log_to", + help="To disable logs" + )] + pub no_logs: bool, + #[arg( + long = "refresh-logs", + action, + conflicts_with="no_logs", + help="To clear logs directory" + )] + pub refresh_logs : bool, + #[arg( + long = "no-remote-config", + action, + help="To disable work with remote config server", + conflicts_with="no_sub")] + pub no_remote_config : bool, + #[arg( + long = "no-sub", + action, + help="To disable subscription mechanism", + conflicts_with="no_remote_config")] + pub no_sub : bool, + + // params (socket_path, log_to, remote_server_url, config) + #[arg( + long = "socket-path", + default_value="/var/run/enode/hostagent.sock", + conflicts_with="no_hostagent", + help="To set .sock file's path used in communication with host-agent" + )] + pub socket_path : PathBuf, + #[arg( + long = "log-to", + default_value="./", + conflicts_with="no_logs", + help="To set a path to logs directory" + )] + pub log_to : PathBuf, + #[arg( + long = "remote-server-url", + default_value="localhost", + conflicts_with="no_remote_config", + help = "To set url of remote config server using in remote config pulling mechanism" + )] + pub remote_server_url : String, + #[arg( + long = "config", + short, + default_value="settings.json", + help="To set local config file path" + )] + pub config : PathBuf, + + // value enum params (metrics) + #[arg( + long = "metrics", + short, + default_value_t=MetricsPrebootParams::Full, + help="To set metrics grubbing mode" + )] + pub metrics: MetricsPrebootParams, +} + +impl PrebootParams { + pub fn validate(self) -> Result { + if !self.socket_path.exists() && !self.no_hostagent { + return Err(Error::msg("Socket-file not found or Noxis can't read it. Cannot start")); + } + // existing log dir + if !self.log_to.exists() && !self.no_logs { + return Err(Error::msg("Log Directory Not Found or Noxis can't read it. Cannot start")); + } + // existing sock file + if !self.config.exists() { + return Err(Error::msg("Local Config Not Found or Noxis can't read it. Cannot start")); + } + // redis server check + Ok(self) + } +} + + +// unit tests of preboot params parsing mech +#[cfg(test)] +mod preboot_unitests{ + use super::*; + + #[test] + fn parsing_zero_args() { + assert!(PrebootParams::try_parse_from(vec!["runner-rs"]).is_ok()) + } + #[test] + fn parsing_hagent_valid_args() { + assert!(PrebootParams::try_parse_from(vec![ + "runner-rs", + "--socket-path", "/path/to/socket" + ]).is_ok()) +} + #[test] + fn parsing_hagent_invalid_args() { + assert!(PrebootParams::try_parse_from(vec![ + "runner-rs", + "--socket-path", "/path/to/socket", + "--no-hagent" + ]).is_err()) + } + #[test] + fn parsing_log_valid_args() { + assert!(PrebootParams::try_parse_from(vec![ + "runner-rs", + "--log-to", "/path/to/log/dir" + ]).is_ok()) + } + #[test] + fn parsing_log_invalid_args() { + assert!(PrebootParams::try_parse_from(vec![ + "runner-rs", + "--log-to /path/to/log/dir", + "--no-logs" + ]).is_err()) + } + #[test] + fn parsing_config_valid_args() { + assert!(PrebootParams::try_parse_from(vec![ + "runner-rs", + "--no-sub", + "--remote-server-url", "redis://127.0.0.1" + ]).is_ok()) + } + #[test] + fn parsing_config_invalid_args_noremote_nosub() { + assert!(PrebootParams::try_parse_from(vec![ + "runner-rs", + "--no-remote-config", "--no-sub" + ]).is_err()) + } + #[test] + fn parsing_config_invalid_args_noremote_remoteurl() { + assert!(PrebootParams::try_parse_from(vec![ + "runner-rs", + "--no-remote-config", + "--remote-server-url", "redis://127.0.0.1" + ]).is_err()) + } + #[test] + fn parsing_metrics_args_using_value_enum() { + assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "full"]).is_ok()); + assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "system"]).is_ok()); + assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "processes"]).is_ok()); + assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "net"]).is_ok()); + assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "none"]).is_ok()); + assert!(PrebootParams::try_parse_from(vec!["runner-rs", "--metrics", "unusual_value"]).is_err()); + } +} \ No newline at end of file diff --git a/src/options/signals.rs b/noxis-rs/src/options/signals.rs similarity index 100% rename from src/options/signals.rs rename to noxis-rs/src/options/signals.rs diff --git a/src/options/structs.rs b/noxis-rs/src/options/structs.rs similarity index 98% rename from src/options/structs.rs rename to noxis-rs/src/options/structs.rs index 8e3ac3f..65c1a19 100644 --- a/src/options/structs.rs +++ b/noxis-rs/src/options/structs.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use std::net::Ipv4Addr; use serde::{Deserialize, Serialize}; @@ -5,6 +7,7 @@ use serde::{Deserialize, Serialize}; pub enum CustomError { Fatal, } + #[derive(Debug, PartialEq)] pub enum ConfigActuality { Local, @@ -18,7 +21,7 @@ pub enum ConfigActuality { /// /// *depends on* : `TrackingProcess` /// -/// ``` +/// ``` json /// { /// -> "dateOfCreation": "1721381809104", /// -> "configServer": "localhost", @@ -44,7 +47,7 @@ pub struct Processes { /// /// *depends on* : `Dependencies` /// -/// ``` +/// ``` json /// ... /// "processes": [ /// -> { @@ -69,7 +72,7 @@ pub struct TrackingProcess { /// /// *depends on* : `Files`, `Services` /// -/// ``` +/// ``` json /// ... /// "path": "/home/user/monitor/runner-rs/temp-process", /// -> "dependencies": { @@ -93,7 +96,7 @@ pub struct Dependencies { /// /// *depends on* : `FileTriggers` /// -/// ``` +/// ``` json /// ... /// "files": [ /// -> { @@ -118,7 +121,7 @@ pub struct Files { /// /// *depends on* : `ServiceTriggers` /// -/// ``` +/// ``` json /// ... /// "services": [ /// -> { @@ -143,7 +146,7 @@ pub struct Services { /// /// *depends on* : - /// -/// ``` +/// ``` json /// ... /// "port": 443, /// -> "triggers": { @@ -168,7 +171,7 @@ pub struct ServiceTriggers { /// /// *depends on* : - /// -/// ``` +/// ``` json /// ... /// "src": "/home/user/monitor/runner-rs/tests/examples/", /// -> "triggers": { diff --git a/noxis-rs/src/utils.rs b/noxis-rs/src/utils.rs new file mode 100644 index 0000000..86e63f5 --- /dev/null +++ b/noxis-rs/src/utils.rs @@ -0,0 +1,271 @@ +pub mod files; +pub mod hagent; +pub mod metrics; +pub mod prcs; +pub mod services; + +// TODO : saving current flags state + +use crate::options::structs::CustomError; +use crate::options::structs::TrackingProcess; +use files::create_watcher; +use files::file_handler; +use inotify::Inotify; +use log::{error, warn}; +use prcs::{ + freeze_process, is_active, is_frozen, restart_process, start_process, terminate_process, + unfreeze_process, +}; +use services::service_handler; +use std::process::Command; +use std::sync::Arc; +use tokio::join; +use tokio::sync::mpsc; +use tokio::time::Duration; + +const GET_ID_CMD: &str = "hostname"; + +/// # Fn `run_daemons` +/// ## async func to run 3 main daemons: process, service and file monitors and manage process state according to given messages into channel +/// +/// *input* : `Arc`, `Arc>`, `&mut mpsc::Receiver`, +/// +/// *output* : () +/// +/// *initiator* : main thread +/// +/// *managing* : Arc to current process struct, Arc to managing channel writer, mut ref to managing channel reader +/// +/// *depends on* : all module `prcs`'s functions, fn `running_handler`, fn `utils::files::create_watcher` +/// +/// > *hint* : give mpsc with capacity 1 to jump over potential errors during running process +/// +pub async fn run_daemons( + proc: Arc, + tx: Arc>, + rx: &mut mpsc::Receiver, +) { + // creating watchers + ---buffers--- + let mut watchers: Vec = vec![]; + for file in proc.dependencies.files.clone().into_iter() { + if let Ok(watcher) = create_watcher(&file.filename, &file.src).await { + watchers.push(watcher); + } else { + let _ = tx.send(121).await; + } + // watchers.push(create_watcher(&file.filename, &file.src).await.unwrap()); + } + let watchers_clone: Arc>> = + Arc::new(tokio::sync::Mutex::new(watchers)); + + loop { + let run_hand = running_handler(proc.clone(), tx.clone(), watchers_clone.clone()); + tokio::select! { + _ = run_hand => continue, + _val = rx.recv() => { + if process_protocol_symbol(proc.clone(), _val.unwrap()).await.is_err() { + return; + } + }, + } + tokio::task::yield_now().await; + } +} + +async fn process_protocol_symbol(proc: Arc, val: u8) -> Result<(), CustomError>{ + match val { + // 1 - File-dependency handling error -> terminating (after waiting) + 1 => { + if is_active(&proc.name).await { + error!("File-dependency handling error: Terminating {} process ..." , &proc.name); + terminate_process(&proc.name).await; + tokio::time::sleep(Duration::from_millis(500)).await; + } + // return; + }, + // 2 - File-dependency handling error -> holding (after waiting) + 2 => { + if !is_frozen(&proc.name).await { + error!("File-dependency handling error: Freezing {} process ..." , &proc.name); + freeze_process(&proc.name).await; + tokio::time::sleep(Duration::from_millis(100)).await; + } + }, + // 3 - Running process error + 3 => { + error!("Error due to starting {} process", &proc.name); + return Err(CustomError::Fatal) + }, + // 4 - Timeout of waiting service-dependency -> staying (after waiting) + 4 => { + // warn!("Timeout of waiting service-dependency: Ignoring on {} process ..." , &proc.name); + tokio::time::sleep(Duration::from_millis(100)).await; + }, + // 5 - Timeout of waiting service-dependency -> terminating (after waiting) + 5 => { + if is_active(&proc.name).await { + error!("Timeout of waiting service-dependency: Terminating {} process ..." , &proc.name); + terminate_process(&proc.name).await; + tokio::time::sleep(Duration::from_millis(500)).await; + } + }, + // 6 - Timeout of waiting service-dependency -> holding (after waiting) + 6 => { + // println!("holding {}-{}", proc.name, is_active(&proc.name).await); + if !is_frozen(&proc.name).await { + error!("Timeout of waiting service-dependency: Freezing {} process ..." , &proc.name); + freeze_process(&proc.name).await; + tokio::time::sleep(Duration::from_secs(1)).await; + } + }, + // // 7 - File-dependency change -> terminating (after check) + 7 => { + error!("File-dependency warning (file changed). Terminating {} process...", &proc.name); + terminate_process(&proc.name).await; + tokio::time::sleep(Duration::from_millis(100)).await; + return Err(CustomError::Fatal) + }, + // // 8 - File-dependency change -> restarting (after check) + 8 => { + warn!("File-dependency warning (file changed). Restarting {} process...", &proc.name); + let _ = restart_process(&proc.name, &proc.path).await; + tokio::time::sleep(Duration::from_millis(100)).await; + }, + // // 9 - File-dependency change -> staying (after check) + 9 => { + // no need to trash logs + warn!("File-dependency warning (file changed). Ignoring event on {} process...", &proc.name); + tokio::time::sleep(Duration::from_millis(100)).await; + }, + + // 10 - Process unfreaze call via file handler (or service handler) + 10 | 11 => { + if is_frozen(&proc.name).await { + warn!("Unfreezing process {} call...", &proc.name); + unfreeze_process(&proc.name).await; + } + tokio::time::sleep(Duration::from_millis(100)).await; + }, + // 11 - Process unfreaze call via service handler + // 11 => { + // if is_frozen(&proc.name).await { + // warn!("Unfreezing process {} call...", &proc.name); + // unfreeze_process(&proc.name).await; + // } + // tokio::time::sleep(Duration::from_millis(100)).await; + // }, + // 101 - Impermissible trigger values in JSON + 101 => { + error!("Impermissible trigger values in JSON in {}'s block. Killing thread...", proc.name); + if is_active(&proc.name).await { + terminate_process(&proc.name).await; + } + return Err(CustomError::Fatal) + }, + // + // 121 - Cannot create valid watcher for file dependency + 121 => { + error!("Cannot create valid watcher for {}'s file dependency. Terminating thread...", proc.name); + let _ = terminate_process("runner-rs").await; + return Err(CustomError::Fatal) + }, + // 111 - global thread termination with killing current child in a face + // of a current process + 111 => { + warn!("Terminating {}'s child processes...", &proc.name); + match is_active(&proc.name).await { + true => { + terminate_process(&proc.name).await; + }, + false => { + log::info!("Process {} is already terminated!", proc.name); + }, + } + }, + _ => {}, + } + Ok(()) +} +// check process status daemon +/// # Fn `run_daemons` +/// ## func to async exec subjobs of checking process, services and files states +/// +/// *input* : `Arc`, `Arc>`, `Arc>>` +/// +/// *output* : () +/// +/// *initiator* : fn `run_daemons` +/// +/// *managing* : Arc to current process struct, Arc to Mutex to list of file watchers +/// +/// *depends on* : fn `utils::files::file_handler`, fn `utils::services::service_handler`, fn `utils::prcs::{is_active, is_frozen, start_process}` +/// +pub async fn running_handler( + prc: Arc, + tx: Arc>, + watchers: Arc>>, +) { + // services and files check (once) + let files_check = file_handler( + &prc.name, + &prc.dependencies.files, + tx.clone(), + watchers.clone(), + ); + let services_check = service_handler(&prc.name, &prc.dependencies.services, tx.clone()); + + let res = join!(files_check, services_check); + // if inactive -> spawn checks -> active is true + if !is_active(&prc.name).await && res.0.is_ok() && res.1.is_ok() { + if start_process(&prc.name, &prc.path).await.is_err() { + tx.send(3).await.unwrap(); + return; + } + } + // if frozen -> spawn checks -> unfreeze is true + else if is_frozen(&prc.name).await && res.0.is_ok() && res.1.is_ok() { + tx.send(10).await.unwrap(); + return; + } + // tokio::time::sleep(Duration::from_millis(100)).await; + tokio::task::yield_now().await; +} + +// todo: cmd across cat /proc/self/mountinfo | grep "/docker/containers/" | head -1 | awk -F '/' '{print $5}' +/// # Fn `get_container_id` +/// ## for getting container id used in logs +/// +/// *input* : - +/// +/// *output* : Some(String) if cont-id was grubbed | None - if not +/// +/// *initiator* : fn `options::logger::setup_logger` +/// +/// *managing* : - +/// +/// *depends on* : - +/// +pub fn get_container_id() -> Option { + match Command::new(GET_ID_CMD).output() { + Ok(output) => { + if !output.status.success() { + return None; + } + let id = String::from_utf8_lossy(&output.stdout).to_string(); + if id.is_empty() { + return None; + } + Some(String::from_utf8_lossy(&output.stdout).to_string()) + } + Err(_) => None, + } +} + +#[cfg(test)] +mod utils_unittests { + use super::get_container_id; + #[test] + fn check_if_container_id_can_be_grabed() { + assert!(get_container_id().is_some()); + } +} diff --git a/src/utils/files.rs b/noxis-rs/src/utils/files.rs similarity index 91% rename from src/utils/files.rs rename to noxis-rs/src/utils/files.rs index 6293c7b..28346c2 100644 --- a/src/utils/files.rs +++ b/noxis-rs/src/utils/files.rs @@ -98,7 +98,10 @@ pub async fn file_handler( // * watcher recreation after dealing with file recreation mechanism in text editors let mutex = notify.borrow_mut(); - *mutex = create_watcher(&file.filename, &file.src).await.unwrap(); + // *mutex = create_watcher(&file.filename, &file.src).await.unwrap(); + if let Ok(watcher) = create_watcher(&file.filename, &file.src).await { + *mutex = watcher; + } } match file.triggers.on_change.as_str() { "stop" => { @@ -159,22 +162,22 @@ mod files_unittests { use super::*; #[tokio::test] async fn try_to_create_watcher() { - let res = create_watcher("dep-file", "/home/user/monitor/runner-rs/tests/examples/").await; + let res = create_watcher("dep-file", "./tests/examples/").await; assert!(res.is_ok()); } #[tokio::test] async fn try_to_create_invalid_watcher() { - let res = create_watcher("invalid-file", "/path/to/the/hell").await; + let res = create_watcher("invalid-file", "/path/to/the/no/dir").await; assert!(res.is_err()); } #[tokio::test] async fn check_existing_file() { - let res = check_file("dep-file", "/home/user/monitor/runner-rs/tests/examples/").await; + let res = check_file("dep-file", "./tests/examples/").await; assert!(res.is_ok()); } #[tokio::test] async fn check_non_existing_file() { - let res = check_file("invalid-file", "/path/to/the/hell").await; + let res = check_file("invalid-file", "/path/to/the/no/dir").await; assert!(res.is_err()); } } diff --git a/src/utils/hagent.rs b/noxis-rs/src/utils/hagent.rs similarity index 58% rename from src/utils/hagent.rs rename to noxis-rs/src/utils/hagent.rs index c794538..79e7dfc 100644 --- a/src/utils/hagent.rs +++ b/noxis-rs/src/utils/hagent.rs @@ -1,5 +1,11 @@ +// // module needed to check host-agent health condition and to communicate with it +// use tokio::{io::Interest, net::UnixStream}; +use anyhow::{Ok, Result, Error}; +// to kill lint bug +#[allow(unused_imports)] +use tokio::net::UnixListener; /// # Fn `open_unix_socket` /// ## opening unix-socket for host-agent communication @@ -14,9 +20,10 @@ use tokio::{io::Interest, net::UnixStream}; /// /// *depends on* : - /// -async fn open_unix_socket() -> Result { - let socket = UnixStream::connect("/var/run/enode/hostagent.sock").await?; - Ok(socket) +#[allow(dead_code)] +async fn open_unix_socket(sock_path: &str) -> Result { + // "/var/run/enode/hostagent.sock" + UnixStream::connect(sock_path).await } /// # Fn `ha_healthcheck` @@ -32,15 +39,11 @@ async fn open_unix_socket() -> Result { /// /// *depends on* : - /// -async fn ha_healthcheck(socket: &UnixStream) -> Result<(), std::io::Error >{ +#[allow(dead_code)] +async fn ha_healthcheck(socket: &UnixStream) -> Result<(), Error> { socket.ready(Interest::WRITABLE).await?; - if socket.writable().await.is_ok() { - if let Err(er) = socket.try_write(b"Hello HAgent") { - return Err(er); - } - } else { - return Err(std::io::ErrorKind::WouldBlock.into()); - } + socket.writable().await?; + socket.try_write(b"Hello HAgent")?; Ok(()) } @@ -57,34 +60,37 @@ async fn ha_healthcheck(socket: &UnixStream) -> Result<(), std::io::Error >{ /// /// *depends on* : - /// -async fn ha_send_data(socket: &UnixStream, data: &str) -> Result<(), std::io::Error > { +#[allow(dead_code)] +async fn ha_send_data(socket: &UnixStream, data: &str) -> Result<(), Error > { socket.ready(Interest::WRITABLE).await?; - if socket.writable().await.is_ok() { - if let Err(er) = socket.try_write(data.as_bytes()) { - return Err(er); - } - } else { - return Err(std::io::ErrorKind::WouldBlock.into()); - } + socket.writable().await?; + socket.try_write(data.as_bytes())?; Ok(()) } #[cfg(test)] mod hagent_unittets { use super::*; - #[tokio::test] - // maybe bool : true -> alive, false -> dead - // simple request on api - async fn hagent_healthcheck() { - let sock = open_unix_socket().await; - assert!(sock.is_ok()); - let sock = sock.unwrap(); - assert!(ha_healthcheck(&sock).await.is_ok()); + const TEST_SOCKET: &str = "./tests/examples/hagent_test.sock"; + + async fn init_listener() -> UnixListener { + let _ = std::fs::remove_file(TEST_SOCKET); + UnixListener::bind(TEST_SOCKET).unwrap() } + // #[tokio::test] + // // maybe bool : true -> alive, false -> dead + // // simple request on api + // async fn hagent_healthcheck() { + // let _ = init_listener().await; + // let sock = open_unix_socket(TEST_SOCKET).await; + // assert!(sock.is_ok()); + // let sock = sock.unwrap(); + // assert!(ha_healthcheck(&sock).await.is_ok()); + // } #[tokio::test] // --Result // one-shot func - async fn send_metrics_to_hagent() { + async fn hagent_communication_test() { use crate::options::structs::{ProcessMetrics, ContainerMetrics, Metrics}; let procm = ProcessMetrics::new("test-prc", 15.0, 5.0); @@ -92,7 +98,9 @@ mod hagent_unittets { let metrics = Metrics::new(contm, vec![procm]); let metrics = &serde_json::to_string_pretty(&metrics).unwrap(); - let sock = open_unix_socket().await; + #[allow(unused_mut)] + let mut _list = init_listener().await; + let sock = open_unix_socket(TEST_SOCKET).await; assert!(sock.is_ok()); let sock = sock.unwrap(); assert!(ha_healthcheck(&sock).await.is_ok()); @@ -101,6 +109,6 @@ mod hagent_unittets { } #[tokio::test] async fn open_unixsocket_test() { - assert!(open_unix_socket().await.is_ok()); + assert!(open_unix_socket("non/valid/socket/file.sock").await.is_err()); } -} +} \ No newline at end of file diff --git a/src/utils/metrics.rs b/noxis-rs/src/utils/metrics.rs similarity index 97% rename from src/utils/metrics.rs rename to noxis-rs/src/utils/metrics.rs index 923106a..0648a3e 100644 --- a/src/utils/metrics.rs +++ b/noxis-rs/src/utils/metrics.rs @@ -27,6 +27,7 @@ use crate::utils::get_container_id; /// /// *depends on* : - /// +#[allow(dead_code)] pub async fn init_metrics_grubber() { let mut system = System::new(); // let mut buffer: Vec = vec![]; @@ -39,6 +40,8 @@ pub async fn init_metrics_grubber() { // let _ = capture_packets(shared_buf.clone()).await; } +#[allow(dead_code)] +#[allow(unused_variables)] async fn gather_metrics(proc: Arc) { } @@ -92,6 +95,7 @@ async fn gather_metrics(proc: Arc) { /// /// *depends on* : `TrackingProcess` /// +#[allow(dead_code)] async fn get_all_container_metrics(sys: Arc, prcs: Arc>) -> ContainerMetrics { let metrics = join!( get_cpu_metrics_container(sys.clone()), @@ -119,6 +123,7 @@ async fn get_all_container_metrics(sys: Arc, prcs: Arc) -> f32 { sys.global_cpu_usage() } @@ -136,6 +141,7 @@ async fn get_cpu_metrics_container(sys: Arc) -> f32 { /// /// *depends on* : - /// +#[allow(dead_code)] async fn get_ram_metrics_container(sys: Arc) -> f32 { (sys.used_memory() / sys.total_memory()) as f32 * 100.0 } @@ -156,6 +162,7 @@ async fn get_ram_metrics_container(sys: Arc) -> f32 { /// /// *depends on* : `TrackingProcess` /// +#[allow(dead_code)] async fn get_subsystems(prcs: Arc>) -> Vec { prcs.iter().map(|process| process.name.clone()).collect() } @@ -173,6 +180,7 @@ async fn get_subsystems(prcs: Arc>) -> Vec { /// /// *depends on* : - /// +#[allow(dead_code)] async fn get_all_metrics_process(proc: Arc, sys: Arc) -> ProcessMetrics { let metrics = join!( get_cpu_metrics_process(proc.clone()), diff --git a/src/utils/prcs.rs b/noxis-rs/src/utils/prcs.rs similarity index 86% rename from src/utils/prcs.rs rename to noxis-rs/src/utils/prcs.rs index 7c718ab..a434c43 100644 --- a/src/utils/prcs.rs +++ b/noxis-rs/src/utils/prcs.rs @@ -233,14 +233,15 @@ mod process_unittests { // rewrite, its a pipe #[tokio::test] async fn full_cycle_with_restart() { - let res1 = start_process("temp-process", "/home/user/monitor/runner-rs/temp-process").await; + // let _ = std::io::stdout().write_all(b""); + let res1 = start_process("restart-prc", "./tests/examples/restart-prc").await; assert!(res1.is_ok()); let res2 = - restart_process("temp-process", "/home/user/monitor/runner-rs/temp-process").await; + restart_process("restart-prc", "./tests/examples/restart-prc").await; assert!(res2.is_ok()); - let _ = terminate_process("temp-process").await; - let res3 = is_active("temp-process").await; - assert!(res3); + let _ = terminate_process("restart-prc").await; + let res3 = is_active("restart-prc").await; + assert!(!res3); } // rewrite, its a pipe #[tokio::test] @@ -249,7 +250,10 @@ mod process_unittests { } #[tokio::test] async fn is_active_check() { - assert!(is_active("systemd").await); + let res1 = start_process("tmp-prc", "./tests/examples/tmp-prc").await; + assert!(res1.is_ok()); + assert!(is_active("tmp-prc").await); + let _ = terminate_process("tmp-prc").await; } #[tokio::test] async fn isnt_active_check() { @@ -257,11 +261,17 @@ mod process_unittests { } #[tokio::test] async fn is_frozen_check() { - assert!(!is_frozen("systemd").await); + let res1 = start_process("freeze-check", "./tests/examples/freeze-check").await; + assert!(res1.is_ok()); + assert!(!is_frozen("freeze-check").await); } #[tokio::test] async fn pidof_active_process() { - assert!(get_pid("systemd").await.is_some()); + assert!(get_pid("pidof-prc").await.is_none()); + let res1 = start_process("pidof-prc", "./tests/examples/pidof-prc").await; + assert!(res1.is_ok()); + assert!(get_pid("pidof-prc").await.is_some()); + let _ = terminate_process("pidof-prc").await; } // broken mechanism need to check diff --git a/src/utils/services.rs b/noxis-rs/src/utils/services.rs similarity index 100% rename from src/utils/services.rs rename to noxis-rs/src/utils/services.rs diff --git a/noxis-rs/temp-process b/noxis-rs/temp-process new file mode 100755 index 0000000..b452711 Binary files /dev/null and b/noxis-rs/temp-process differ diff --git a/tests/examples/dep-file b/noxis-rs/tests/examples/dep-file similarity index 100% rename from tests/examples/dep-file rename to noxis-rs/tests/examples/dep-file diff --git a/noxis-rs/tests/examples/freeze-check b/noxis-rs/tests/examples/freeze-check new file mode 100755 index 0000000..704d548 Binary files /dev/null and b/noxis-rs/tests/examples/freeze-check differ diff --git a/tests/examples/invalid_config.json b/noxis-rs/tests/examples/invalid_config.json similarity index 100% rename from tests/examples/invalid_config.json rename to noxis-rs/tests/examples/invalid_config.json diff --git a/tests/examples/none.json b/noxis-rs/tests/examples/none.json similarity index 100% rename from tests/examples/none.json rename to noxis-rs/tests/examples/none.json diff --git a/noxis-rs/tests/examples/pidof-prc b/noxis-rs/tests/examples/pidof-prc new file mode 100755 index 0000000..704d548 Binary files /dev/null and b/noxis-rs/tests/examples/pidof-prc differ diff --git a/noxis-rs/tests/examples/restart-prc b/noxis-rs/tests/examples/restart-prc new file mode 100755 index 0000000..704d548 Binary files /dev/null and b/noxis-rs/tests/examples/restart-prc differ diff --git a/tests/examples/run.sh b/noxis-rs/tests/examples/run.sh similarity index 100% rename from tests/examples/run.sh rename to noxis-rs/tests/examples/run.sh diff --git a/tests/examples/save-conf.json b/noxis-rs/tests/examples/save-conf.json similarity index 100% rename from tests/examples/save-conf.json rename to noxis-rs/tests/examples/save-conf.json diff --git a/tests/examples/settings.json b/noxis-rs/tests/examples/settings.json similarity index 100% rename from tests/examples/settings.json rename to noxis-rs/tests/examples/settings.json diff --git a/noxis-rs/tests/examples/tmp-prc b/noxis-rs/tests/examples/tmp-prc new file mode 100755 index 0000000..704d548 Binary files /dev/null and b/noxis-rs/tests/examples/tmp-prc differ diff --git a/tests/start_stop.rs b/noxis-rs/tests/start_stop.rs similarity index 100% rename from tests/start_stop.rs rename to noxis-rs/tests/start_stop.rs diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index ac87f1e..0000000 --- a/src/utils.rs +++ /dev/null @@ -1,265 +0,0 @@ -pub mod files; -pub mod hagent; -pub mod metrics; -pub mod prcs; -pub mod services; - -// - -use crate::options::structs::TrackingProcess; -use files::create_watcher; -use files::file_handler; -use inotify::Inotify; -use log::{error, warn}; -use prcs::{ - freeze_process, is_active, is_frozen, restart_process, start_process, terminate_process, - unfreeze_process, -}; -use services::service_handler; -use std::process::Command; -use std::sync::Arc; -use tokio::join; -use tokio::sync::mpsc; -use tokio::time::Duration; - -const GET_ID_CMD: &str = "hostname"; - -/// # Fn `run_daemons` -/// ## async func to run 3 main daemons: process, service and file monitors and manage process state according to given messages into channel -/// -/// *input* : `Arc`, `Arc>`, `&mut mpsc::Receiver`, -/// -/// *output* : () -/// -/// *initiator* : main thread -/// -/// *managing* : Arc to current process struct, Arc to managing channel writer, mut ref to managing channel reader -/// -/// *depends on* : all module `prcs`'s functions, fn `running_handler`, fn `utils::files::create_watcher` -/// -/// > *hint* : give mpsc with capacity 1 to jump over potential errors during running process -/// -pub async fn run_daemons( - proc: Arc, - tx: Arc>, - rx: &mut mpsc::Receiver, -) { - // creating watchers + ---buffers--- - let mut watchers: Vec = vec![]; - for file in proc.dependencies.files.clone().into_iter() { - if let Ok(watcher) = create_watcher(&file.filename, &file.src).await { - watchers.push(watcher); - } else { - let _ = tx.send(121).await; - } - // watchers.push(create_watcher(&file.filename, &file.src).await.unwrap()); - } - let watchers_clone: Arc>> = - Arc::new(tokio::sync::Mutex::new(watchers)); - - loop { - let run_hand = running_handler(proc.clone(), tx.clone(), watchers_clone.clone()); - tokio::select! { - _ = run_hand => {}, - _val = rx.recv() => { - match _val.unwrap() { - // 1 - File-dependency handling error -> terminating (after waiting) - 1 => { - if is_active(&proc.name).await { - error!("File-dependency handling error: Terminating {} process ..." , &proc.name); - terminate_process(&proc.name).await; - tokio::time::sleep(Duration::from_millis(100)).await; - } - return; - }, - // 2 - File-dependency handling error -> holding (after waiting) - 2 => { - if !is_frozen(&proc.name).await { - error!("File-dependency handling error: Freezing {} process ..." , &proc.name); - freeze_process(&proc.name).await; - tokio::time::sleep(Duration::from_millis(100)).await; - } - }, - // 3 - Running process error - 3 => { - error!("Error due to starting {} process", &proc.name); - break; - }, - // 4 - Timeout of waiting service-dependency -> staying (after waiting) - 4 => { - // warn!("Timeout of waiting service-dependency: Ignoring on {} process ..." , &proc.name); - tokio::time::sleep(Duration::from_millis(100)).await; - }, - // 5 - Timeout of waiting service-dependency -> terminating (after waiting) - 5 => { - if is_active(&proc.name).await { - error!("Timeout of waiting service-dependency: Terminating {} process ..." , &proc.name); - terminate_process(&proc.name).await; - tokio::time::sleep(Duration::from_millis(1000)).await; - } - }, - // 6 - Timeout of waiting service-dependency -> holding (after waiting) - 6 => { - // println!("holding {}-{}", proc.name, is_active(&proc.name).await); - if !is_frozen(&proc.name).await { - error!("Timeout of waiting service-dependency: Freezing {} process ..." , &proc.name); - freeze_process(&proc.name).await; - tokio::time::sleep(Duration::from_secs(1)).await; - } - }, - // // 7 - File-dependency change -> terminating (after check) - 7 => { - error!("File-dependency warning (file changed). Terminating {} process...", &proc.name); - terminate_process(&proc.name).await; - tokio::time::sleep(Duration::from_millis(100)).await; - return; - }, - // // 8 - File-dependency change -> restarting (after check) - 8 => { - warn!("File-dependency warning (file changed). Restarting {} process...", &proc.name); - let _ = restart_process(&proc.name, &proc.path).await; - tokio::time::sleep(Duration::from_millis(100)).await; - }, - // // 9 - File-dependency change -> staying (after check) - 9 => { - // no need to trash logs - warn!("File-dependency warning (file changed). Ignoring event on {} process...", &proc.name); - tokio::time::sleep(Duration::from_millis(100)).await; - }, - - // 10 - Process unfreaze call via file handler (or service handler) - 10 | 11 => { - if is_frozen(&proc.name).await { - warn!("Unfreezing process {} call...", &proc.name); - unfreeze_process(&proc.name).await; - } - tokio::time::sleep(Duration::from_millis(100)).await; - }, - // 11 - Process unfreaze call via service handler - // 11 => { - // if is_frozen(&proc.name).await { - // warn!("Unfreezing process {} call...", &proc.name); - // unfreeze_process(&proc.name).await; - // } - // tokio::time::sleep(Duration::from_millis(100)).await; - // }, - // 101 - Impermissible trigger values in JSON - 101 => { - error!("Impermissible trigger values in JSON in {}'s block. Killing thread...", proc.name); - if is_active(&proc.name).await { - terminate_process(&proc.name).await; - } - break; - }, - // - // 121 - Cannot create valid watcher for file dependency - 121 => { - error!("Cannot create valid watcher for {}'s file dependency. Terminating thread...", proc.name); - let _ = terminate_process("runner-rs").await; - break; - }, - // 111 - global thread termination with killing current child in a face - // of a current process - 111 => { - warn!("Terminating {}'s child processes...", &proc.name); - match is_active(&proc.name).await { - true => { - terminate_process(&proc.name).await; - }, - false => { - log::info!("Process {} is already terminated!", proc.name); - }, - } - break; - }, - _ => {}, - } - }, - } - tokio::task::yield_now().await; - } - tokio::task::yield_now().await; -} -// check process status daemon -/// # Fn `run_daemons` -/// ## func to async exec subjobs of checking process, services and files states -/// -/// *input* : `Arc`, `Arc>`, `Arc>>` -/// -/// *output* : () -/// -/// *initiator* : fn `run_daemons` -/// -/// *managing* : Arc to current process struct, Arc to Mutex to list of file watchers -/// -/// *depends on* : fn `utils::files::file_handler`, fn `utils::services::service_handler`, fn `utils::prcs::{is_active, is_frozen, start_process}` -/// -pub async fn running_handler( - prc: Arc, - tx: Arc>, - watchers: Arc>>, -) { - // services and files check (once) - let files_check = file_handler( - &prc.name, - &prc.dependencies.files, - tx.clone(), - watchers.clone(), - ); - let services_check = service_handler(&prc.name, &prc.dependencies.services, tx.clone()); - - let res = join!(files_check, services_check); - // if inactive -> spawn checks -> active is true - if !is_active(&prc.name).await && res.0.is_ok() && res.1.is_ok() { - if start_process(&prc.name, &prc.path).await.is_err() { - tx.send(3).await.unwrap(); - return; - } - } - // if frozen -> spawn checks -> unfreeze is true - else if is_frozen(&prc.name).await && res.0.is_ok() && res.1.is_ok() { - tx.send(10).await.unwrap(); - return; - } - // tokio::time::sleep(Duration::from_millis(100)).await; - tokio::task::yield_now().await; -} - -// todo: cmd across cat /proc/self/mountinfo | grep "/docker/containers/" | head -1 | awk -F '/' '{print $5}' -/// # Fn `get_container_id` -/// ## for getting container id used in logs -/// -/// *input* : - -/// -/// *output* : Some(String) if cont-id was grubbed | None - if not -/// -/// *initiator* : fn `options::logger::setup_logger` -/// -/// *managing* : - -/// -/// *depends on* : - -/// -pub fn get_container_id() -> Option { - match Command::new(GET_ID_CMD).output() { - Ok(output) => { - if !output.status.success() { - return None; - } - let id = String::from_utf8_lossy(&output.stdout).to_string(); - if id.is_empty() { - return None; - } - Some(String::from_utf8_lossy(&output.stdout).to_string()) - } - Err(_) => None, - } -} - -#[cfg(test)] -mod utils_unittests { - use super::get_container_id; - #[test] - fn check_if_container_id_can_be_grabed() { - assert!(get_container_id().is_some()); - } -} diff --git a/temp-process b/temp-process deleted file mode 100755 index 534ffd2..0000000 Binary files a/temp-process and /dev/null differ