diff --git a/build-all.sh b/build-all.sh new file mode 100755 index 0000000..4a0675f --- /dev/null +++ b/build-all.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -e + +echo "Building CortexFlow Agent" +pushd ./core +./agent-api-build.sh +popd + +sleep 1 + +echo "Building CortexFlow Identity" +pushd ./core/src/components/identity +./build-identity.sh +popd + +sleep 1 + +echo "Building CortexFlow Metrics" +pushd ./core/src/components/metrics +./build-metrics.sh +popd + +sleep 1 + +echo "Insert image version. e.g 0.1.2/latest or type skip to skip the uploading processing" +echo +read -p "Insert cortexflow-agent version: " agent_version +read -p "Insert cortexflow-identity version: " identity_version +read -p "Insert cortexflow-metrics version: " metrics_version + +echo +echo "Tagging & pushing docker images..." +echo + +if [ "$metrics_version" != "skip" ]; then + docker tag metrics:0.0.1 lorenzotettamanti/cortexflow-metrics:$metrics_version + docker push lorenzotettamanti/cortexflow-metrics:$metrics_version +else + echo "Skipping cortexflow-metrics image upload" +fi + +if [ "$agent_version" != "skip" ]; then + docker tag cortexflow-agent:0.0.1 lorenzotettamanti/cortexflow-agent:$agent_version + docker push lorenzotettamanti/cortexflow-agent:$agent_version +else + echo "Skipping cortexflow-agent image upload" +fi + +if [ "$identity_version" != "skip" ]; then + docker tag identity:0.0.1 lorenzotettamanti/cortexflow-identity:$identity_version + docker push lorenzotettamanti/cortexflow-identity:$identity_version +else + echo "Skipping cortexflow-identity image upload" +fi diff --git a/cli/Cargo.lock b/cli/Cargo.lock index 7141d32..47db442 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -2,6 +2,36 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anstream" version = "0.6.19" @@ -52,18 +82,227 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "api" +version = "0.1.0" +dependencies = [ + "anyhow", + "aya", + "bytemuck", + "bytemuck_derive", + "identity", + "prost", + "tokio", + "tokio-stream", + "tonic", + "tonic-build", + "tonic-prost", + "tonic-prost-build", + "tonic-reflection", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "axum" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +dependencies = [ + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "aya" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d18bc4e506fbb85ab7392ed993a7db4d1a452c71b75a246af4a80ab8c9d2dd50" +dependencies = [ + "assert_matches", + "aya-obj", + "bitflags", + "bytes", + "libc", + "log", + "object", + "once_cell", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "aya-log" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b600d806c1d07d3b81ab5f4a2a95fd80f479a0d3f1d68f29064d660865f85f02" +dependencies = [ + "aya", + "aya-log-common", + "bytes", + "log", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "aya-log-common" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "befef9fe882e63164a2ba0161874e954648a72b0e1c4b361f532d590638c4eec" +dependencies = [ + "num_enum", +] + +[[package]] +name = "aya-obj" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51b96c5a8ed8705b40d655273bc4212cbbf38d4e3be2788f36306f154523ec7" +dependencies = [ + "bytes", + "core-error", + "hashbrown", + "log", + "object", + "thiserror 1.0.69", +] + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "bytemuck" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "clap" version = "4.5.41" @@ -119,18 +358,44 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "core-error" +version = "0.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efcdb2972eb64230b4c50646d8498ff73f5128d196a90c7236eec4cbe8619b8f" +dependencies = [ + "version_check", +] + [[package]] name = "cortexflow-cli" version = "0.1.2" dependencies = [ + "anyhow", + "api", "clap", "colored", "directories", + "prost", + "prost-types", "serde", "serde_yaml", + "tokio", + "tokio-stream", + "tonic", + "tonic-reflection", "tracing", ] +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "directories" version = "6.0.0" @@ -152,12 +417,91 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -166,7 +510,44 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", ] [[package]] @@ -174,6 +555,11 @@ name = "hashbrown" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "heck" @@ -182,95 +568,618 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "indexmap" -version = "2.10.0" +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "identity" +version = "0.1.0" +dependencies = [ + "anyhow", + "aya", + "aya-log", + "bytemuck", + "bytemuck_derive", + "bytes", + "libc", + "nix", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libredox" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[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.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "crc32fast", + "hashbrown", + "indexmap", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[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.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "prettyplease" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" +dependencies = [ + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +dependencies = [ + "prost", +] + +[[package]] +name = "pulldown-cmark" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5b6a0769a491a08b31ea5c62494a8f144ee0987d86d670a8af4df1e1b7cde75" +dependencies = [ + "pulldown-cmark", +] + +[[package]] +name = "quote" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ - "equivalent", - "hashbrown", + "proc-macro2", ] [[package]] -name = "is_terminal_polyfill" -version = "1.70.1" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "itoa" -version = "1.0.15" +name = "redox_syscall" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +dependencies = [ + "bitflags", +] [[package]] -name = "libc" -version = "0.2.174" +name = "redox_users" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 2.0.12", +] [[package]] -name = "libredox" -version = "0.1.4" +name = "regex" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ - "bitflags", - "libc", + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] -name = "once_cell" -version = "1.21.3" +name = "regex-automata" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] [[package]] -name = "once_cell_polyfill" -version = "1.70.1" +name = "regex-automata" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] [[package]] -name = "option-ext" -version = "0.2.0" +name = "regex-syntax" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] -name = "pin-project-lite" -version = "0.2.16" +name = "regex-syntax" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] -name = "proc-macro2" -version = "1.0.95" +name = "rustc-demangle" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" [[package]] -name = "quote" -version = "1.0.40" +name = "rustix" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "proc-macro2", + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.60.2", ] [[package]] -name = "redox_users" -version = "0.5.0" +name = "rustversion" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -278,6 +1187,12 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[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.219" @@ -311,6 +1226,46 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "strsim" version = "0.11.1" @@ -328,13 +1283,52 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -348,6 +1342,183 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tokio" +version = "1.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "slab", + "socket2", + "tokio-macros", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac5a8627ada0968acec063a4746bf79588aa03ccb66db2f75d7dce26722a40" +dependencies = [ + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e323d8bba3be30833707e36d046deabf10a35ae8ad3cae576943ea8933e25d" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tonic-prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c511b9a96d40cb12b7d5d00464446acf3b9105fd3ce25437cfe41c92b1c87d" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef298fcd01b15e135440c4b8c974460ceca4e6a5af7f1c933b08e4d2875efa1" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn", + "tempfile", + "tonic-build", +] + +[[package]] +name = "tonic-reflection" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0267a0073385cd94996197d12acb1856a3a0a2367482c726a48a769f6fed8a3a" +dependencies = [ + "prost", + "prost-types", + "tokio", + "tokio-stream", + "tonic", + "tonic-prost", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.41" @@ -377,8 +1548,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -397,12 +1610,64 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "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-sys" version = "0.59.0" @@ -548,3 +1813,12 @@ name = "windows_x86_64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index f378e18..069b9e6 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -13,9 +13,17 @@ license = "Apache-2.0" clap = { version = "4.5.38", features = ["derive"] } colored = "3.0.0" directories = "6.0.0" -serde = {version = "1.0.219",features = ["derive"]} +serde = { version = "1.0.219", features = ["derive"] } serde_yaml = "0.9.34" tracing = "0.1.41" +tokio = "1.47.0" +anyhow = "1.0.98" +api = { path = "../core/api" } +tonic = "0.14.1" +tonic-reflection = "0.14.1" +tokio-stream = "0.1.17" +prost-types = "0.14.1" +prost = "0.14.1" [[bin]] name = "cfcli" diff --git a/cli/src/essential.rs b/cli/src/essential.rs index 914ab3b..6ff30d2 100644 --- a/cli/src/essential.rs +++ b/cli/src/essential.rs @@ -148,6 +148,7 @@ pub fn create_configs() -> MetadataConfigFile { }; configs } +//TODO: add here and explaination of what read_configs returns pub fn read_configs(config_path: PathBuf) -> String { let config = fs::File::open(config_path).unwrap(); let parsed_config: Result = @@ -205,6 +206,7 @@ pub fn create_config_file(config_struct: MetadataConfigFile) { ), } } +//TODO: add here an explanation of what are config_dir and file_path pub fn get_config_directory() -> Result<(PathBuf, PathBuf), ()> { let dirs = ProjectDirs::from("org", "cortexflow", "cfcli") .expect("Cannot determine the config directory"); @@ -222,3 +224,4 @@ pub fn get_startup_config_dir() -> bool { }) .unwrap_or(false) } +// TODO: add save to config function \ No newline at end of file diff --git a/cli/src/install.rs b/cli/src/install.rs index a1cc8e1..20d1eec 100644 --- a/cli/src/install.rs +++ b/cli/src/install.rs @@ -1,7 +1,7 @@ -use std::process::{Command, exit}; +use std::process::{ Command, exit }; use crate::essential::Environments; -use crate::essential::{create_config_file, create_configs, get_config_directory, read_configs}; +use crate::essential::{ create_config_file, create_configs, get_config_directory, read_configs }; use colored::Colorize; use std::thread; @@ -14,18 +14,10 @@ fn install_cluster_components(env: String) { match user_env { Ok(cluster_environment) => { let env = cluster_environment.base_command(); - println!( - "{} {}", - "=====>".blue().bold(), - "Copying installation files".white() - ); + println!("{} {}", "=====>".blue().bold(), "Copying installation files".white()); copy_installation_files(); thread::sleep(Duration::from_secs(1)); - println!( - "{} {}", - "=====>".blue().bold(), - "Creating cortexflow namespace".white() - ); + println!("{} {}", "=====>".blue().bold(), "Creating cortexflow namespace".white()); Command::new(env) .args(["create", "namespace", "cortexflow"]) .output() @@ -34,17 +26,31 @@ fn install_cluster_components(env: String) { install_components(env.to_string()); println!("\n"); rm_installation_files(); - println!( - "{} {}", - "=====>".blue().bold(), - "installation completed".white() - ); + println!("{} {}", "=====>".blue().bold(), "installation completed".white()); } Err(e) => { - eprintln!( - "An error occured while installing cortexflow components: {:?}", - e - ); + eprintln!("An error occured while installing cortexflow components: {:?}", e); + exit(1) + } + } +} + +/* example installation function */ +fn install_simple_example_component(env: String) { + let user_env = Environments::try_from(env.to_lowercase()); + match user_env { + Ok(cluster_environment) => { + let env = cluster_environment.base_command(); + println!("{} {}", "=====>".blue().bold(), "Copying installation files".white()); + copy_example_installation_file(); + thread::sleep(Duration::from_secs(1)); + install_example(env.to_string()); + println!("\n"); + rm_example_installation_file(); + println!("{} {}", "=====>".blue().bold(), "installation completed".white()); + } + Err(e) => { + eprintln!("An error occured while installing cortexflow components: {:?}", e); exit(1) } } @@ -52,16 +58,8 @@ fn install_cluster_components(env: String) { /* main installation function */ pub fn install_cortexflow() { - println!( - "{} {}", - "=====>".blue().bold(), - "Preparing cortexflow installation".white() - ); - println!( - "{} {}", - "=====>".blue().bold(), - "Creating the config files".white() - ); + println!("{} {}", "=====>".blue().bold(), "Preparing cortexflow installation".white()); + println!("{} {}", "=====>".blue().bold(), "Creating the config files".white()); let metadata_configs = create_configs(); create_config_file(metadata_configs); @@ -70,6 +68,44 @@ pub fn install_cortexflow() { let env = read_configs(file_path); install_cluster_components(env); } +/* install simple example */ +pub fn install_simple_example() { + println!("{} {}", "=====>".blue().bold(), "Installing simple example".white()); + + let file_path = get_config_directory().unwrap().1; + + let env = read_configs(file_path); + install_simple_example_component(env); +} + + +/* install example component */ +fn install_example(env: String) { + let files_to_install = vec!["deploy-test-pod.yaml"]; + let tot_files = files_to_install.len(); + + println!("{} {}", "=====>".blue().bold(), "Installing cortexflow components".white()); + let user_env = env.as_str(); + debug!("Debugging env var in install components {:?}", user_env); + + let mut i = 1; + + for component in files_to_install { + println!( + "{} {}{}{}{} {} {} {}", + "=====>".blue().bold(), + "(", + i, + "/", + tot_files, + ")", + "Applying ", + component + ); + apply_component(component, user_env); + i = i + 1; + } +} /* Installation functions */ fn install_components(env: String) { @@ -79,32 +115,29 @@ fn install_components(env: String) { "rolebinding.yaml", "cortexflow-rolebinding.yaml", "identity.yaml", + "agent.yaml" ]; let tot_files = files_to_install.len(); - println!( - "{} {}", - "=====>".blue().bold(), - "Installing cortexflow components".white() - ); + println!("{} {}", "=====>".blue().bold(), "Installing cortexflow components".white()); let user_env = env.as_str(); debug!("Debugging env var in install components {:?}", user_env); - let mut i=1; + let mut i = 1; for component in files_to_install { - println!( - "{} {}{}{} {} {} {}", - "=====>".blue().bold(), - "(", - i, - "/", - tot_files, - "Applying ", - component - ); - apply_component(component, user_env); - i=i+1; + println!( + "{} {}{}{} {} {} {}", + "=====>".blue().bold(), + "(", + i, + "/", + tot_files, + "Applying ", + component + ); + apply_component(component, user_env); + i = i + 1; } } @@ -115,11 +148,7 @@ fn apply_component(file: &str, env: &str) { .expect("cannot install component from file"); if !output.status.success() { - eprintln!( - "Error installing file: {}:\n{}", - file, - String::from_utf8_lossy(&output.stderr) - ); + eprintln!("Error installing file: {}:\n{}", file, String::from_utf8_lossy(&output.stderr)); } else { println!("✅ Applied {}", file); } @@ -129,46 +158,51 @@ fn apply_component(file: &str, env: &str) { fn copy_installation_files() { download_file( - "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/configmap.yaml", + "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/configmap.yaml" + ); + download_file( + "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/configmap-role.yaml" ); download_file( - "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/configmap-role.yaml", + "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/rolebinding.yaml" ); download_file( - "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/rolebinding.yaml", + "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/cortexflow-rolebinding.yaml" ); download_file( - "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/cortexflow-rolebinding.yaml", + "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/identity.yaml" + ); + download_file( + "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/feature/ebpf-core/core/src/testing/agent.yaml" ); - download_file("https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/main/core/src/testing/identity.yaml"); println!("\n"); } -fn rm_installation_files() { - println!( - "{} {}", - "=====>".blue().bold(), - "Removing temporary installation files".white() +fn copy_example_installation_file() { + download_file( + "https://raw.githubusercontent.com/CortexFlow/CortexBrain/refs/heads/feature/ebpf-core/core/src/testing/deploy-test-pod.yaml" ); + println!("\n"); +} +fn rm_installation_files() { + println!("{} {}", "=====>".blue().bold(), "Removing temporary installation files".white()); rm_file("configmap.yaml"); rm_file("configmap-role.yaml"); rm_file("rolebinding.yaml"); rm_file("cortexflow-rolebinding.yaml"); rm_file("identity.yaml"); + rm_file("agent.yaml"); +} +fn rm_example_installation_file() { + println!("{} {}", "=====>".blue().bold(), "Removing temporary installation files".white()); + rm_file("deploy-test-pod.yaml"); } /* Auxiliary functions */ fn download_file(src: &str) { - let output = Command::new("wget") - .args([src]) - .output() - .expect("cannot import config file"); + let output = Command::new("wget").args([src]).output().expect("cannot import config file"); if !output.status.success() { - eprintln!( - "Error copying file: {}.\n{}", - src, - String::from_utf8_lossy(&output.stderr) - ); + eprintln!("Error copying file: {}.\n{}", src, String::from_utf8_lossy(&output.stderr)); } else { println!("✅ Copied file from {} ", src); } diff --git a/cli/src/main.rs b/cli/src/main.rs index 83a8194..986667b 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,31 +1,36 @@ -//TODO: add a identity-monitor module //TODO: add an example with test pods during installation mod essential; mod install; mod logs; +mod monitoring; mod service; mod status; mod uninstall; - use clap::command; -use clap::{Args, Error, Parser, Subcommand}; -use tracing::debug; +use clap::{ Args, Error, Parser, Subcommand }; use colored::Colorize; -use std::time::Duration; +use std::result::Result::Ok; use std::thread; +use std::time::Duration; +use tracing::debug; - -use crate::essential::{get_config_directory,get_startup_config_dir, info, read_configs, update_cli}; -use crate::install::install_cortexflow; +use crate::essential::{ + get_config_directory, + get_startup_config_dir, + info, + read_configs, + update_cli, +}; +use crate::install::{install_cortexflow, install_simple_example}; use crate::logs::logs_command; -use crate::service::{describe_service, list_services}; +use crate::monitoring::{ list_features, monitor_identity_events }; +use crate::service::{ describe_service, list_services }; use crate::status::status_command; use crate::uninstall::uninstall; use crate::essential::GeneralData; - #[derive(Parser, Debug)] #[command( author = GeneralData::AUTHOR, @@ -42,24 +47,20 @@ struct Cli { #[derive(Subcommand, Debug, Clone)] enum Commands { /* list of available commands */ - #[command(name = "set-env")] - SetEnv(SetArgs), + #[command(name = "set-env")] SetEnv(SetArgs), #[command(name = "get-env")] GetEnv, - #[command(name = "install")] - Install, + #[command(name = "install")] Install(InstallArgs), #[command(name = "uninstall")] Uninstall, #[command(name = "update")] Update, #[command(name = "info")] Info, - #[command(name = "service")] - Service(ServiceArgs), - #[command(name = "status")] - Status(StatusArgs), - #[command(name = "logs")] - Logs(LogsArgs), + #[command(name = "service")] Service(ServiceArgs), + #[command(name = "status")] Status(StatusArgs), + #[command(name = "logs")] Logs(LogsArgs), + #[command(name = "monitoring")] Monitor(MonitorArgs), } #[derive(Args, Debug, Clone)] struct SetArgs { @@ -72,21 +73,51 @@ struct ServiceArgs { service_cmd: ServiceCommands, } +//install args +#[derive(Args, Debug, Clone)] +struct InstallArgs { + #[command(subcommand)] + install_cmd: InstallCommands, +} +//install subcommands #[derive(Subcommand, Debug, Clone)] -enum ServiceCommands { +enum InstallCommands { + #[command(name = "cortexflow")] + All, + #[command(name = "simple-example")] + TestPods, +} + +//monitoring subcommands +#[derive(Subcommand, Debug, Clone)] +enum MonitorCommands { #[command(name = "list")] - List { + List, + #[command(name = "connections")] + Connections, +} + +//service subcommands +#[derive(Subcommand, Debug, Clone)] +enum ServiceCommands { + #[command(name = "list")] List { #[arg(long)] namespace: Option, }, - #[command(name = "describe")] - Describe { + #[command(name = "describe")] Describe { service_name: String, #[arg(long)] namespace: Option, }, } +// cfcli monitor +#[derive(Args, Debug, Clone)] +struct MonitorArgs { + #[command(subcommand)] + monitor_cmd: MonitorCommands, +} + #[derive(Args, Debug, Clone)] struct StatusArgs { #[arg(long)] @@ -105,22 +136,26 @@ struct LogsArgs { namespace: Option, } -fn args_parser() -> Result<(), Error> { +async fn args_parser() -> Result<(), Error> { let args = Cli::parse(); //get the environment from the config file metadata let config_dir = get_startup_config_dir(); - - if !config_dir{ - eprintln!("{} {}","[SYSTEM]".blue().bold(),"Config files not found. Please proceed with the installation"); + + if !config_dir { + eprintln!( + "{} {}", + "[SYSTEM]".blue().bold(), + "Config files not found. Please proceed with the installation" + ); install_cortexflow(); Ok(()) } else { thread::sleep(Duration::from_secs(1)); - println!("{} {}","[SYSTEM]".blue().bold(),"Founded config files".white()); - let config_file_path=get_config_directory(); - let file_path= config_file_path.unwrap().1; + println!("{} {}", "[SYSTEM]".blue().bold(), "Founded config files".white()); + let config_file_path = get_config_directory(); + let file_path = config_file_path.unwrap().1; let env = read_configs(file_path.to_path_buf()); let general_data = GeneralData::new(env); debug!("Arguments {:?}", args.cmd); @@ -133,10 +168,17 @@ fn args_parser() -> Result<(), Error> { general_data.get_env_output(); Ok(()) } - Some(Commands::Install) => { - install_cortexflow(); - Ok(()) - } + Some(Commands::Install(installation_args)) => + match installation_args.install_cmd { + InstallCommands::All => { + install_cortexflow(); + Ok(()) + } + InstallCommands::TestPods => { + install_simple_example(); + Ok(()) + } + } Some(Commands::Uninstall) => { uninstall(); Ok(()) @@ -149,19 +191,17 @@ fn args_parser() -> Result<(), Error> { info(general_data); Ok(()) } - Some(Commands::Service(service_args)) => match service_args.service_cmd { - ServiceCommands::List { namespace } => { - Some(list_services(namespace)); - Ok(()) - } - ServiceCommands::Describe { - service_name, - namespace, - } => { - describe_service(service_name, &namespace); - Ok(()) + Some(Commands::Service(service_args)) => + match service_args.service_cmd { + ServiceCommands::List { namespace } => { + Some(list_services(namespace)); + Ok(()) + } + ServiceCommands::Describe { service_name, namespace } => { + describe_service(service_name, &namespace); + Ok(()) + } } - }, Some(Commands::Status(status_args)) => { status_command(status_args.output, status_args.namespace); Ok(()) @@ -170,6 +210,17 @@ fn args_parser() -> Result<(), Error> { logs_command(logs_args.service, logs_args.component, logs_args.namespace); Ok(()) } + Some(Commands::Monitor(monitor_args)) => + match monitor_args.monitor_cmd { + MonitorCommands::List => { + let _ = list_features().await; + Ok(()) + } + MonitorCommands::Connections => { + let _ = monitor_identity_events().await; + Ok(()) + } + } None => { eprintln!("CLI unknown argument. Cli arguments passed: {:?}", args.cmd); Ok(()) @@ -178,6 +229,7 @@ fn args_parser() -> Result<(), Error> { } } -fn main() { - let _ = args_parser(); +#[tokio::main] +async fn main() { + let _ = args_parser().await; } diff --git a/cli/src/mod.rs b/cli/src/mod.rs index 61d875e..a4d96ac 100644 --- a/cli/src/mod.rs +++ b/cli/src/mod.rs @@ -3,4 +3,5 @@ pub mod install; pub mod uninstall; pub mod service; pub mod status; -pub mod logs; \ No newline at end of file +pub mod logs; +pub mod monitoring; \ No newline at end of file diff --git a/cli/src/monitoring.rs b/cli/src/monitoring.rs new file mode 100644 index 0000000..e673c0f --- /dev/null +++ b/cli/src/monitoring.rs @@ -0,0 +1,105 @@ +#![allow(warnings)] + +//monitoring CLI function for identity service +use anyhow::Error; +use colored::Colorize; +use prost::Message; +use prost_types::FileDescriptorProto; +use std::result::Result::Ok; +use tonic_reflection::pb::v1::{ + server_reflection_response::MessageResponse, +}; + +use agent_api::client::{connect_to_client, connect_to_server_reflection}; +use agent_api::requests::{get_all_features, send_active_connection_request}; + +pub async fn list_features() -> Result<(), Error> { + match connect_to_server_reflection().await { + Ok(client) => { + println!( + "{} {}", + "=====>".blue().bold(), + "Connected to CortexFlow Server Reflection".green() + ); + match get_all_features(client).await { + Ok(response) => { + let mut streaming = response.into_inner(); + + //decoding the proto file + while let Some(resp) = streaming.message().await? { + if let Some(MessageResponse::FileDescriptorResponse(fdr)) = + resp.message_response + { + println!("Available services:"); + for bytes in fdr.file_descriptor_proto { + //decode file descriptor + let fd = FileDescriptorProto::decode(bytes.as_slice())?; + + for service in fd.service { + for method in service.method { + let method_name = method.name.unwrap_or_default(); + println!("{}", method_name); + } + } + } + } + } + } + Err(e) => { + println!( + "{} {} {} {}", + "=====>".blue().bold(), + "An error occured".red(), + "Error:", + e + ); + } + } + } + Err(_) => println!( + "{} {}", + "=====>".blue().bold(), + "Failed to connect to CortexFlow Server Reflection".red() + ), + } + Ok(()) +} + +pub async fn monitor_identity_events() -> Result<(), Error> { + println!( + "{} {}", + "=====>".blue().bold(), + "Connecting to cortexflow Client".white() + ); + + match connect_to_client().await { + Ok(client) => { + println!( + "{} {}", + "=====>".blue().bold(), + "Connected to CortexFlow Client".green() + ); + match send_active_connection_request(client).await { + Ok(response) => { + println!("{:?}", response.into_inner().events); + } + Err(e) => { + println!( + "{} {} {} {}", + "=====>".blue().bold(), + "An error occured".red(), + "Error:", + e + ); + } + } + } + Err(_) => println!( + "{} {}", + "=====>".blue().bold(), + "Failed to connect to CortexFlow Client".red() + ), + } + + Ok(()) +} diff --git a/core/.dockerignore b/core/.dockerignore index aa97dbc..1e58c2a 100644 --- a/core/.dockerignore +++ b/core/.dockerignore @@ -1,7 +1,4 @@ -src/components/kernel src/components/loadbalancer src/components/proxy src/components/xdp -src/components/maps -src/components/xtask -src/shared \ No newline at end of file +src/components/maps \ No newline at end of file diff --git a/core/Cargo.lock b/core/Cargo.lock index 4792d3b..e6ea0f4 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -44,16 +44,19 @@ version = "0.1.0" dependencies = [ "anyhow", "aya", - "dotenv", + "bytemuck", + "bytemuck_derive", "identity", "prost", "tokio", + "tokio-stream", "tonic", "tonic-build", "tonic-prost", "tonic-prost-build", "tonic-reflection", "tracing", + "tracing-subscriber", ] [[package]] @@ -287,9 +290,23 @@ checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "bytes" @@ -336,12 +353,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - [[package]] name = "either" version = "1.15.0" @@ -596,6 +607,7 @@ dependencies = [ "aya", "aya-log", "bytemuck", + "bytemuck_derive", "bytes", "libc", "nix", @@ -704,6 +716,33 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metrics" +version = "0.1.0" +dependencies = [ + "anyhow", + "aya", + "aya-log", + "bytemuck", + "bytes", + "libc", + "nix", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "metrics_tracer" +version = "0.1.0" +dependencies = [ + "aya-ebpf", + "aya-log-ebpf", + "bytemuck", + "network-types", + "which", +] + [[package]] name = "mime" version = "0.3.17" @@ -736,6 +775,12 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" +[[package]] +name = "network-types" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2df15b1cb023b9d205ae287d5dbe74510ae4d62b5131ceec516f4913ed05230" + [[package]] name = "nix" version = "0.30.1" diff --git a/core/Cargo.toml b/core/Cargo.toml index 3d128e5..088c2e9 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,17 +1,14 @@ [workspace] resolver = "3" members = [ - #"src/components/kernel", #"src/components/loadbalancer", "api", - #"src/shared", #"src/components/proxy", #"src/components/xdp", #"src/components/maps", "src/components/conntracker", - #"xtask", "src/components/identity", - #"src/components/metrics_tracer", - #"src/components/metrics", + "src/components/metrics_tracer", + "src/components/metrics", ] diff --git a/core/api/Cargo.toml b/core/api/Cargo.toml index d25eb40..7c86907 100644 --- a/core/api/Cargo.toml +++ b/core/api/Cargo.toml @@ -14,13 +14,18 @@ aya = "0.13.1" identity = { path = "../src/components/identity" } tonic-reflection = "0.14.0" tonic-build = "0.14.0" -dotenv = "0.15.0" tracing-subscriber = "0.3.19" +tokio-stream = "0.1.17" +bytemuck = {version ="1.23.0"} +bytemuck_derive = "1.10.1" [build-dependencies] tonic-build = "0.14.0" tonic-prost-build = "0.14.0" +[lib] +name = "agent_api" +path = "src/lib.rs" [[bin]] name = "agent-api" diff --git a/core/api/protos/agent.proto b/core/api/protos/agent.proto index f88dd33..dff6026 100644 --- a/core/api/protos/agent.proto +++ b/core/api/protos/agent.proto @@ -4,8 +4,12 @@ package agent; message RequestActiveConnections{ optional string pod_ip = 2 ; } +// TODO: the complete Response will be able to return all the context below +//* "Event Id: {} Protocol: {:?} SRC: {}:{} -> DST: {}:{}", +//* event_id, proto, src, src_port, dst, dst_port message ActiveConnectionResponse{ string status = 1; + map events = 2 ; //for simplicity right now we only return event_id and src } //declare agent api diff --git a/core/api/src/agent.rs b/core/api/src/agent.rs index 9a8b17b..bdf3e72 100644 --- a/core/api/src/agent.rs +++ b/core/api/src/agent.rs @@ -4,10 +4,20 @@ pub struct RequestActiveConnections { #[prost(string, optional, tag = "2")] pub pod_ip: ::core::option::Option<::prost::alloc::string::String>, } -#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +/// TODO: the complete Response will be able to return all the context below +/// +/// * "Event Id: {} Protocol: {:?} SRC: {}:{} -> DST: {}:{}", +/// * event_id, proto, src, src_port, dst, dst_port +#[derive(Clone, PartialEq, ::prost::Message)] pub struct ActiveConnectionResponse { #[prost(string, tag = "1")] pub status: ::prost::alloc::string::String, + /// for simplicity right now we only return event_id and src + #[prost(map = "string, string", tag = "2")] + pub events: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost::alloc::string::String, + >, } /// Generated client implementations. pub mod agent_client { diff --git a/core/api/src/api.rs b/core/api/src/api.rs index ab46874..322b0e4 100644 --- a/core/api/src/api.rs +++ b/core/api/src/api.rs @@ -1,31 +1,69 @@ #![allow(warnings)] -use anyhow::Context; use prost::bytes::BytesMut; -use std::{ - collections::HashMap, - fs, string, - sync::{atomic::AtomicBool, Arc, Mutex}, -}; +use std::sync::Mutex; use tonic::{Request, Response, Status}; +use tracing::info; use aya::{ - maps::{perf::PerfEventArrayBuffer, Map, MapData, PerfEventArray}, + maps::{MapData, PerfEventArray}, util::online_cpus, - Bpf, }; -use identity::helpers::display_events; -use identity::map_handlers::init_bpf_maps; -use std::path::Path; use std::result::Result::Ok; use tonic::async_trait; +use std::collections::HashMap; +use tokio::sync::mpsc; +use tokio::task; + // * contains agent api configuration use crate::agent::{agent_server::Agent, ActiveConnectionResponse, RequestActiveConnections}; +use aya::maps::Map; +use bytemuck_derive::Zeroable; +use identity::enums::IpProtocols; +use std::net::Ipv4Addr; +use tracing::warn; + +#[repr(C)] +#[derive(Clone, Copy, Zeroable)] +pub struct PacketLog { + pub proto: u8, + pub src_ip: u32, + pub src_port: u16, + pub dst_ip: u32, + pub dst_port: u16, + pub pid: u32, +} +unsafe impl aya::Pod for PacketLog {} -#[derive(Debug)] pub struct AgentApi { - name: String, - bpf: Arc>, + //* event_rx is an istance of a mpsc receiver. + //* is used to receive the data from the transmitter (tx) + event_rx: Mutex, Status>>>, + event_tx: mpsc::Sender, Status>>, +} + +//* Event sender trait. Takes an event from a map and send that to the mpsc channel +//* using the send_map function +#[async_trait] +pub trait EventSender: Send + Sync + 'static { + async fn send_event(&self, event: HashMap); + async fn send_map( + &self, + map: HashMap, + tx: mpsc::Sender, Status>>, + ) { + let status = Status::new(tonic::Code::Ok, "success"); + let event = Ok(map); + + let _ = tx.send(event).await; + } +} +// send event function. takes an HashMap and send that using mpsc event_tx +#[async_trait] +impl EventSender for AgentApi { + async fn send_event(&self, event: HashMap) { + self.send_map(event, self.event_tx.clone()).await; + } } const BPF_PATH: &str = "BPF_PATH"; @@ -33,20 +71,119 @@ const BPF_PATH: &str = "BPF_PATH"; //initialize a default trait for AgentApi. Loads a name and a bpf istance. //this trait is essential for init the Agent. impl Default for AgentApi { + //TODO:this part needs a better error handling fn default() -> Self { - let bpf_path = std::env::var(BPF_PATH).context("BPF_PATH variable not found").unwrap(); - let data = fs::read(Path::new(&bpf_path)).context("Cannot load data from path").unwrap(); + // load maps mapdata + let mapdata = MapData::from_pin("/sys/fs/bpf/maps/events_map") + .expect("cannot open events_map Mapdata"); + let map = Map::PerfEventArray(mapdata); //creates a PerfEventArray from the mapdata - AgentApi { - name: "CortexFlow-Agent".to_string(), - bpf: Arc::new(Mutex::new(Bpf::load(&data).unwrap())), - } + //init a mpsc channel + let (tx, rx) = mpsc::channel(1024); + let api = AgentApi { + event_rx: rx.into(), + event_tx: tx.clone(), + }; + + let mut events_array = + PerfEventArray::try_from(map).expect("Error while initializing events array"); + + //spawn an event reader + task::spawn(async move { + let mut net_events_buffer = Vec::new(); + //scan the cpus to read the data + + for cpu_id in online_cpus() + .map_err(|e| anyhow::anyhow!("Error {:?}", e)) + .unwrap() + { + let buf = events_array + .open(cpu_id, None) + .expect("Error during the creation of net_events_buf structure"); + + let buffers = vec![BytesMut::with_capacity(4096); 8]; + net_events_buffer.push((buf, buffers)); + } + + info!("Starting event listener"); + //send the data through a mpsc channel + loop { + for (buf, buffers) in net_events_buffer.iter_mut() { + match buf.read_events(buffers) { + Ok(events) => { + //read the events, this function is similar to the one used in identity/helpers.rs/display_events + if events.read > 0 { + for i in 0..events.read { + let data = &buffers[i]; + if data.len() >= std::mem::size_of::() { + let pl: PacketLog = + unsafe { std::ptr::read(data.as_ptr() as *const _) }; + let src = Ipv4Addr::from(u32::from_be(pl.src_ip)); + let dst = Ipv4Addr::from(u32::from_be(pl.dst_ip)); + let src_port = u16::from_be(pl.src_port as u16); + let dst_port = u16::from_be(pl.dst_port as u16); + let event_id = pl.pid; + + match IpProtocols::try_from(pl.proto) { + Ok(proto) => { + info!( + "Event Id: {} Protocol: {:?} SRC: {}:{} -> DST: {}:{}", + event_id, proto, src, src_port, dst, dst_port + ); + info!("creating hashmap for the aggregated data"); + let mut evt = HashMap::new(); + // insert event in the hashmap + info!("Inserting events into the hashmap"); + //TODO: use a Arc or Box type instead of String type. + //The data doesn't need to implement any .copy() or .clone() trait + // using an Arc type will also waste less resources + evt.insert( + format!("{:?}", event_id.to_string()), + format!("{:?}", src.to_string()), + ); + info!("sending events to the MPSC channel"); + let _ = tx.send(Ok(evt)).await; + } + Err(_) => { + info!( + "Event Id: {} Protocol: Unknown ({})", + event_id, pl.proto + ); + } + }; + } else { + warn!( + "Received packet data too small: {} bytes", + data.len() + ); + } + } + } else if events.read == 0 { + info!("[Agent/API] 0 Events found"); + let mut evt = HashMap::new(); + evt.insert("0".to_string(), "0".to_string()); + let _ = tx.send(Ok(evt)).await; + } + } + Err(e) => { + eprintln!("Errore nella lettura eventi: {}", e); + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + } + } + } + // small delay to avoid cpu congestion + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; + } + }); + + api } } -//TODO: implement a trait that inizialize init_bpf_maps function #[async_trait] impl Agent for AgentApi { + // * read the incoming active_connections requests and returns a response with the + // * active connections. The data are transformed and sent to the api with a mpsc channel async fn active_connections( &self, request: Request, @@ -54,33 +191,26 @@ impl Agent for AgentApi { //read request let req = request.into_inner(); - //initialize maps: - let bpf_maps = init_bpf_maps(Arc::clone(&self.bpf)).unwrap(); - - let mut net_events_buffer = Vec::new(); + //create the hashmap to process events from the mpsc channel queue + let mut aggregated_events: HashMap = HashMap::new(); - //maps are enumerated 0: events map 1: veth events map - let mut events_array = PerfEventArray::try_from(bpf_maps.0).unwrap(); - - //scan the cpus - for cpu_id in online_cpus() - .map_err(|e| anyhow::anyhow!("Error {:?}", e)) - .unwrap() - { - let net_events_buf: PerfEventArrayBuffer = - events_array.open(cpu_id, None).unwrap(); - net_events_buffer.push(net_events_buf); + //aggregate events + while let Ok(evt) = self.event_rx.lock().unwrap().try_recv() { + if let Ok(map) = evt { + aggregated_events.extend(map); + } } - let mut events_buffers = vec![BytesMut::with_capacity(1024); online_cpus().iter().len()]; - - let running = Arc::new(AtomicBool::new(true)); - display_events(net_events_buffer, running, events_buffers); + //log response for debugging + info!( + "DEBUGGING RESPONSE FROM ACTIVE CONNECTION REQUEST: {:?}", + aggregated_events + ); + //return response Ok(Response::new(ActiveConnectionResponse { status: "success".to_string(), + events: aggregated_events, })) } } - -//TODO: add server inizialization diff --git a/core/api/src/client.rs b/core/api/src/client.rs new file mode 100644 index 0000000..f5d30dc --- /dev/null +++ b/core/api/src/client.rs @@ -0,0 +1,28 @@ +use anyhow::Error; +use std::result::Result::Ok; +use tonic::{transport::Channel}; +use tonic_reflection::pb::v1::{ + server_reflection_client::ServerReflectionClient, +}; +use crate::agent::agent_client::AgentClient; + + + +pub async fn connect_to_client() -> Result, Error> { + //this methods force a HTTP/2 connection from a static string + //FIXME: this will require an update to ensure a protected connection + let channel = Channel::from_static("http://192.168.49.2:30092") + .connect() + .await?; + let client = AgentClient::new(channel); + Ok(client) +} + +pub async fn connect_to_server_reflection() -> Result, Error> { + //this methods force a HTTP/2 connection from a static string + let channel = Channel::from_static("http://192.168.49.2:30092") + .connect() + .await?; + let client = ServerReflectionClient::new(channel); + Ok(client) +} diff --git a/core/api/src/lib.rs b/core/api/src/lib.rs new file mode 100644 index 0000000..0b13fb6 --- /dev/null +++ b/core/api/src/lib.rs @@ -0,0 +1,4 @@ +pub mod api; +pub mod agent; +pub mod client; +pub mod requests; \ No newline at end of file diff --git a/core/api/src/requests.rs b/core/api/src/requests.rs new file mode 100644 index 0000000..5a2da02 --- /dev/null +++ b/core/api/src/requests.rs @@ -0,0 +1,35 @@ +use anyhow::Error; +use std::result::Result::Ok; +use tonic::{Request, Response, Streaming, transport::Channel}; +use tonic_reflection::pb::v1::{ + ServerReflectionRequest, ServerReflectionResponse, + server_reflection_client::ServerReflectionClient, server_reflection_request::MessageRequest, +}; + +use crate::agent::agent_client::AgentClient; +use crate::agent::ActiveConnectionResponse; +use crate::agent::RequestActiveConnections; + +pub async fn send_active_connection_request( + mut client: AgentClient, +) -> Result, Error> { + let request = Request::new(RequestActiveConnections { pod_ip: None }); + let response = client.active_connections(request).await?; + Ok(response) +} + +pub async fn get_all_features( + mut client: ServerReflectionClient, +) -> Result>, Error> { + let request = ServerReflectionRequest { + host: "".to_string(), + message_request: Some(MessageRequest::FileContainingSymbol( + "agent.Agent".to_string(), + )), + }; + let response = client + .server_reflection_info(tokio_stream::iter(vec![request])) + .await?; + + Ok(response) +} diff --git a/core/src/components/conntracker/src/data_structures.rs b/core/src/components/conntracker/src/data_structures.rs index b1692aa..65d2ce3 100644 --- a/core/src/components/conntracker/src/data_structures.rs +++ b/core/src/components/conntracker/src/data_structures.rs @@ -1,4 +1,7 @@ -use aya_ebpf::{macros::map, maps::{LruPerCpuHashMap, PerfEventArray}}; +use aya_ebpf::{ + macros::map, + maps::{LruPerCpuHashMap, PerfEventArray}, +}; #[repr(C)] #[derive(Clone, Copy)] @@ -34,7 +37,7 @@ pub struct VethLog { } -#[map(name = "EventsMap")] +#[map(name = "EventsMap", pinning = "by_name")] pub static mut EVENTS: PerfEventArray = PerfEventArray::new(0); //TODO: ConnectionMap needs a rework after implementing issue #105 diff --git a/core/src/components/identity/Cargo.toml b/core/src/components/identity/Cargo.toml index 1c93f88..ea05ad9 100644 --- a/core/src/components/identity/Cargo.toml +++ b/core/src/components/identity/Cargo.toml @@ -12,6 +12,7 @@ anyhow = "1.0" tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } libc = "0.2.172" -bytemuck = "1.23.0" -nix ={version="0.30.1",features=["net"]} +bytemuck = {version ="1.23.0",features = ["derive"]} +bytemuck_derive = "1.10.1" +nix = { version = "0.30.1", features = ["net"] } diff --git a/core/src/components/identity/Dockerfile b/core/src/components/identity/Dockerfile index 0dc89ef..ba65ec0 100644 --- a/core/src/components/identity/Dockerfile +++ b/core/src/components/identity/Dockerfile @@ -30,7 +30,7 @@ COPY conntracker /usr/src/cortexbrain-identity-service/conntracker # Set environment variable ENV BPF_PATH="/usr/src/cortexbrain-identity-service/conntracker" -ENV PIN_MAP_PATH="/sys/fs/bpf/cortexbrain-identity-service/" +ENV PIN_MAP_PATH="/sys/fs/bpf/maps" # Default command CMD ["cortexflow-identity-service"] diff --git a/core/src/components/identity/src/helpers.rs b/core/src/components/identity/src/helpers.rs index d3118ef..102df17 100644 --- a/core/src/components/identity/src/helpers.rs +++ b/core/src/components/identity/src/helpers.rs @@ -1,17 +1,16 @@ +#![allow(warnings)] use crate::enums::IpProtocols; use crate::structs::{PacketLog, VethLog}; use aya::programs::tc::SchedClassifierLinkId; use aya::{ Bpf, - maps::{ - MapData, - perf::{PerfEventArrayBuffer}, - }, + maps::{MapData, perf::PerfEventArrayBuffer}, programs::{SchedClassifier, TcAttachType}, }; use bytes::BytesMut; use nix::net::if_::if_nameindex; use std::collections::HashMap; +use std::result::Result::Ok; use std::sync::Mutex; use std::{ borrow::BorrowMut, @@ -46,6 +45,7 @@ impl TryFrom for IpProtocols { } } +/* helper functions to read and log net events in the container */ pub async fn display_events>( mut perf_buffers: Vec>, running: Arc, diff --git a/core/src/components/identity/src/main.rs b/core/src/components/identity/src/main.rs index c32bf5d..a4fa1c1 100644 --- a/core/src/components/identity/src/main.rs +++ b/core/src/components/identity/src/main.rs @@ -77,7 +77,7 @@ async fn main() -> Result<(), anyhow::Error> { //init bpf data let bpf = Arc::new(Mutex::new(Bpf::load(&data)?)); let bpf_map_save_path = - std::env::var(PIN_MAP_PATH).context("BPF_PATH environment variable required")?; + std::env::var(PIN_MAP_PATH).context("PIN_MAP_PATH environment variable required")?; match init_bpf_maps(bpf.clone()) { std::result::Result::Ok(bpf_maps) => { diff --git a/core/src/components/identity/src/map_handlers.rs b/core/src/components/identity/src/map_handlers.rs index 4656aeb..c0adb41 100644 --- a/core/src/components/identity/src/map_handlers.rs +++ b/core/src/components/identity/src/map_handlers.rs @@ -6,7 +6,7 @@ use std::path::PathBuf; use std::sync::Arc; use std::sync::Mutex; use tokio::fs; -use tracing::error; +use tracing::info; pub fn init_bpf_maps(bpf: Arc>) -> Result<(Map, Map), anyhow::Error> { // this function init the bpfs maps used in the main program @@ -42,20 +42,23 @@ pub fn init_bpf_maps(bpf: Arc>) -> Result<(Map, Map), anyhow::Error> //TODO: save bpf maps path in the cli metadata //takes an array of bpf maps and pin them to persiste session data //TODO: change maps type with a Vec instead of (Map,Map). This method is only for fast development and it's not optimized -//TODO: chmod 700 to setup the permissions to pin maps TODO:add this permission in the CLI //TODO: add bpf mounts during cli installation pub async fn map_pinner(maps: &(Map, Map), path: &PathBuf) -> Result<(), Error> { - //FIXME: add exception for already pinned maps + // check if the map exists if !path.exists() { - error!("Pin path {:?} does not exist. Creating it...", path); - let _ = fs::create_dir_all(path) - .await - .map_err(|e| error!("Failed to create directory: {}", e)); + info!("Pin path {:?} does not exist. Creating it...", path); + fs::create_dir_all(&path).await?; + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + fs::set_permissions(&path, std::fs::Permissions::from_mode(0o755)).await?; + } } let map1_path = path.join("events_map"); let map2_path = path.join("veth_map"); + // maps pinning maps.0.pin(&map1_path)?; maps.1.pin(&map2_path)?; diff --git a/core/src/components/identity/src/structs.rs b/core/src/components/identity/src/structs.rs index e80dff4..ae9c6db 100644 --- a/core/src/components/identity/src/structs.rs +++ b/core/src/components/identity/src/structs.rs @@ -1,23 +1,26 @@ +use bytemuck_derive::Zeroable; + /* * Structure PacketLog * This structure is used to store the packet information */ #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Zeroable)] pub struct PacketLog { pub proto: u8, pub src_ip: u32, pub src_port: u16, pub dst_ip: u32, pub dst_port: u16, - pub event_id: u16, - pub pid : u32 + pub pid: u32, } +unsafe impl aya::Pod for PacketLog {} + /* * Connection Array that contains the hash_id associated with an active connection */ #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Zeroable)] pub struct ConnArray { pub src_ip: u32, pub dst_ip: u32, diff --git a/core/src/components/kernel/Cargo.toml b/core/src/components/kernel/Cargo.toml deleted file mode 100644 index a4d70f8..0000000 --- a/core/src/components/kernel/Cargo.toml +++ /dev/null @@ -1,43 +0,0 @@ -[package] -name = "kernel" -version = "0.1.0" -edition = "2024" - -[dependencies] -actix-web = "4.9.0" -clap = "4.5.21" -tokio = { version = "1", features = ["full"] } -tracing = "0.1.40" -futures = "0.3.31" -anyhow = "1.0.93" -schemas = "0.4.0" -yaml-rust2 = "0.10.3" -kube = { version = "1.1.0", features = ["runtime", "derive", "ws"]} -k8s-openapi = { version = "0.25.0", features = ["latest"] } -serde_json = "1.0.133" -tokio-util = { version = "0.7.8", features = ["io"] } -tokio-stream = { version = "0.1.9", features = ["net"] } -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -serde = { version = "1.0", features = ["derive"] } -hyper-util = "0.1.10" -tower = "0.5.1" -ipnet = "2.10.1" -iptables = "0.5.2" -itertools = "0.14.0" -libc = "0.2.164" -libloading = "0.8.5" -libp2p = "0.56.0" -serde_yaml = "0.9.34" -pnet = "0.35.0" -bytes = "1.9.0" -prost = "0.14.1" -rdkafka = "0.38.0" -trust-dns-server = "0.23.2" -dirs = "6.0.0" - -[dependencies.shared] -path = "../../shared" - -[[bin]] -name = "kernel" -path = "src/main.rs" diff --git a/core/src/components/kernel/Dockerfile b/core/src/components/kernel/Dockerfile deleted file mode 100644 index 51c0f23..0000000 --- a/core/src/components/kernel/Dockerfile +++ /dev/null @@ -1,44 +0,0 @@ -# Phase 1: Build image -FROM rust:1.85 AS builder - -# Set working directory -WORKDIR /usr/src/app - -# Copy the shared library in the correct location -WORKDIR /usr/src/shared -COPY .shared/Cargo.toml . -COPY .shared/src ./src - -# Then create the kernel project structure -WORKDIR /usr/src/app/kernel -COPY Cargo.toml . -COPY src ./src - -# Ensure Cargo recognizes the shared dependency -RUN cargo fetch - -# Build the project -RUN cargo build --release - -# Phase 2: Create final image -FROM ubuntu:22.04 - -# Install runtime dependencies -RUN apt-get update && apt-get install -y \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -# Create directory for the kernel -WORKDIR /usr/src/cortexbrain-kernel - -# Create the /etc/dns directory -RUN mkdir -p /etc/dns - -# Copy the binary from builder -COPY --from=builder /usr/src/app/kernel/target/release/kernel /usr/local/bin/cortexflow-kernel - -# Copy the config.yaml file into /etc/dns -COPY config.yaml /etc/dns/config.yaml - -# Set the kernel execution command -CMD ["cortexflow-kernel"] diff --git a/core/src/components/kernel/build-kernel.sh b/core/src/components/kernel/build-kernel.sh deleted file mode 100755 index 1a4c4d6..0000000 --- a/core/src/components/kernel/build-kernel.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Create temporary shared directory -mkdir -p .shared - -# Copy shared files -cp -r ../../shared/src .shared/ -cp -r ../../shared/Cargo.toml .shared/ -cp -r ../../client/config.yaml config.yaml - -# Run docker build -docker build -t kernel:0.0.1 . - -# Cleanup -rm -rf .shared -rm -rf config.yaml \ No newline at end of file diff --git a/core/src/components/kernel/src/corefile.rs b/core/src/components/kernel/src/corefile.rs deleted file mode 100644 index 3e5854f..0000000 --- a/core/src/components/kernel/src/corefile.rs +++ /dev/null @@ -1,359 +0,0 @@ -/* The corefile.go file in Kubernetes is part of the source code for CoreDNS, which is the default DNS server used in Kubernetes clusters for service name resolution and other internal DNS operations. This file defines the structure and functionality associated with CoreDNS configuration, specifically the object called Corefile. - -Corefile.go's main functionality -CoreDNS configuration parsing: - -Handles the logic for reading, parsing, and interpreting the CoreDNS configuration file, which is usually called Corefile. This file specifies how CoreDNS should behave, which plugins to use, and how to handle DNS queries. -Configuration validation: - -Verifies that the CoreDNS configuration is valid. For example, it checks that the configuration blocks are correct and that the defined plugins are supported. -Configuration Manipulation: - -Allows programmatic changes to the Corefile configuration. For example, if the cluster requires an update of DNS zones or the addition of a new plugin, this file defines the structures and functions to make those changes. -Useful Data Structures: - -Defines data structures to represent the Corefile, with each block and directive described in a structured way for programmable management. -Interface with Kubernetes: - -Provides functionality to integrate CoreDNS with Kubernetes clusters, such as configuring internal DNS services to resolve names such as my-service.my-n - -*/ -#[allow(unused_imports)] -use shared::apiconfig::EdgeDNSConfig; -use kube::Client; -use crate::utilities::{get_interfaces, is_valid_ip, remove_duplicates}; -use anyhow::{anyhow, Error, Result}; -use k8s_openapi::api::core::v1::ConfigMap; -use kube::api::{Patch, PatchParams}; -use kube::api::{Api, ListParams}; -use k8s_openapi::api::core::v1::Service; -use serde::Serialize; -use serde_json::json; -use std::collections::HashSet; -use std::fs; -use std::net::IpAddr; -use tracing::{error, info,instrument, warn}; - -/* template block */ - -const STUB_DOMAIN_BLOCK: &str = r#"{{domain_name}}:{{port}} { - bind {{local_ip}} - log - errors - forward . {{upstream_servers}} { - force_tcp - } - cache {{cache_ttl}} - loop - reload -}"#; - - - -//TODO: add certificate to protect the route -const KUBERNETES_PLUGIN_BLOCK: &str = r#"kubernetes cluster.local in-addr.arpa ip6.arpa{ - pods insecure - fallthrough in-addr.arpa ip6.arpa - ttl {{ttl}} - }"#; - -/* constants */ -const DEFAULT_TTL: u32 = 30; -const DEFAULT_UPSTREAM_SERVER: &str = "/etc/resolv.conf"; - -/* parameters */ -#[derive(Serialize)] -pub struct StubDomainInfo { - domain_name: String, - local_ip: String, - port: String, - cache_ttl: u32, - upstream_servers: String, - kubernetes_plugin: String, -} - -#[derive(Serialize)] -pub struct KubernetesPluginInfo { - api_server: String, - ttl: u32, -} - -fn generate_stub_domain_block(config: StubDomainInfo) -> Result { - let template = STUB_DOMAIN_BLOCK.to_string(); - let mut rendered = template; - - rendered = rendered.replace("{{domain_name}}", &config.domain_name); - rendered = rendered.replace("{{port}}", &config.port.to_string()); - rendered = rendered.replace("{{local_ip}}", &config.local_ip.to_string()); - rendered = rendered.replace("{{cache_ttl}}", &config.cache_ttl.to_string()); - rendered = rendered.replace("{{upstream_servers}}", &config.upstream_servers); - rendered = rendered.replace("{{kubernetes_plugin}}", &config.kubernetes_plugin); - - Ok(rendered) -} - -fn generate_kubernetes_plugin_block(config: KubernetesPluginInfo) -> Result { - let template = KUBERNETES_PLUGIN_BLOCK.to_string(); - let mut rendered = template; - - rendered = rendered.replace("{{api_server}}", &config.api_server); - rendered = rendered.replace("{{ttl}}", &config.ttl.to_string()); - - Ok(rendered) -} - -#[instrument(skip(client))] -pub async fn detect_cluster_dns(client: Client) -> Result, Box> { - let namespace = "kube-system"; - let mut servers = HashSet::new(); - - info!("Running DNS service detection..."); - - let services: Api = Api::namespaced(client.clone(), namespace); - info!("Initialized API for services in namespace: {}", namespace); - - let label_selector = ListParams::default().labels("k8s-app=kube-dns"); - info!("Using label selector: k8s-app=kube-dns"); - - let service_list = match services.list(&label_selector).await { - Ok(list) => { - info!("Successfully retrieved list of services with label k8s-app=kube-dns"); - list - } - Err(e) => { - error!("Failed to retrieve services: {}", e); - return Err(e.into()); - } - }; - - info!("Processing {} services...", service_list.items.len()); - for service in service_list.items { - let service_name = service.metadata.name.clone().unwrap_or_else(|| "unnamed".to_string()); - info!("Processing service: {}", service_name); - - if let Some(spec) = service.spec { - if let Some(cluster_ip) = spec.cluster_ip { - if cluster_ip != "None" { - info!("Found valid ClusterIP: {} for service: {}", cluster_ip, service_name); - servers.insert(cluster_ip); - } else { - info!("Service {} has ClusterIP set to 'None', skipping", service_name); - } - } else { - info!("Service {} has no ClusterIP, skipping", service_name); - } - } else { - info!("Service {} has no spec, skipping", service_name); - } - } - - let servers: Vec = servers.into_iter().collect(); - info!("Detected unique DNS servers: {:?}", servers); - - if servers.is_empty() { - error!("Unable to automatically detect cluster DNS. Do you have CoreDNS or kube-dns installed in your cluster?"); - Err("No DNS service detected".into()) - } else { - info!("Automatically detected cluster DNS: {:?}", servers); - Ok(servers) - } -} -// return the interface ip -fn get_interface_ip(interface: &str) -> Result { - /* - Lib reference: pnet: - https://crates.io/crates/pnet - */ - let interfaces = pnet::datalink::interfaces(); - for iface in interfaces { - if iface.name == interface { - for ip in iface.ips { - if let IpAddr::V4(ipv4) = ip.ip() { - return Ok(IpAddr::V4(ipv4)); - } - } - } - } - get_interfaces(); - Err(anyhow!( - "Failed to find interface with name: {:?}", - interface - )) -} - -//update corefile function -#[instrument(skip(kube_client))] -pub async fn update_corefile(cfg: EdgeDNSConfig, kube_client: &Client) -> Result<(), Error> { - info!("Updating the EdgeDNS corefile configuration\n\n"); - info!("Retrieving the corefile current configuration"); - let configmaps: Api = - Api::namespaced(kube_client.clone(), "kube-system"); - let mut corefile_configmap = configmaps.get("coredns").await?; - info!("{:?}\n\n", corefile_configmap); - - - // obtain the interface ip address - let listen_ip = get_interface_ip(&cfg.listen_interface)?; - - info!("listener ip {}", listen_ip); - - // Set default values for cacheTTL and upstreamServers - let mut cache_ttl = DEFAULT_TTL; - let mut upstream_servers = vec![DEFAULT_UPSTREAM_SERVER.to_string()]; - - info!("Cache ttl {}", cache_ttl); - - info!("upstream server {:?}", upstream_servers); - - // Get the Kubernetes plugin configuration string - let kubernetes_plugin = get_kubernetes_plugin_str(cfg.clone())?; - - info!("kubernetes plugin string: {}", kubernetes_plugin); - - if let Some(cache_dns_config) = cfg.cache_dns { - if cache_dns_config.enable { - upstream_servers.clear(); - - // Automatic detection of upstream servers from the cluster - if cache_dns_config.auto_detect { - info!("\nAuto detecting servers"); - match detect_cluster_dns(kube_client.clone()).await { - Ok(detected_servers) => { - // Add the detected servers to the upstream_servers list - upstream_servers.extend(detected_servers); - info!("Auto detected servers: {:?}\n", upstream_servers); - } - Err(e) => { - // Handle the error if detection fails - error!("Failed to auto-detect servers: {}", e); - } - } - } - - //Add upstream servers configured - for server in &cache_dns_config.upstream_servers { - let server = server.trim(); - if !server.is_empty() { - if is_valid_ip(server) { - upstream_servers.push(server.to_string()); - } else { - error!("Invalid address: {}", server); - } - } - } - - // Remove duplicates - upstream_servers = remove_duplicates(upstream_servers); - - if upstream_servers.is_empty() { - return Err(anyhow!("No valid upstream servers detected")); - } - - // update the cache ttl - cache_ttl = cache_dns_config.cache_ttl; - } - } - - // Create the configuration string for the stub domain - let stub_domain_str = generate_stub_domain_block(StubDomainInfo { - domain_name: "cortexflow-edge.dns".to_string(), - local_ip: listen_ip.to_string(), - port: cfg.listen_port.to_string(), - cache_ttl, - upstream_servers: upstream_servers.join(", "), - kubernetes_plugin, - })?; - - let stub_domain_str_copy = stub_domain_str.clone(); - - // Scrivi la nuova configurazione nel file temporaneo - let temp_corefile_path = "/tmp/Corefile"; - fs::write(temp_corefile_path, stub_domain_str)?; - - //Create a full patched file to check before submission in the k8s coredns file in corefile - - if let Some(coredns_data) = corefile_configmap.data.as_mut() { - //search for corefile in data map - if let Some(corefile) = coredns_data.get_mut("Corefile") { - let mut corefile_copy = corefile.clone(); - - //new config to add--> stub_domain_str - corefile_copy.push_str(&stub_domain_str_copy); //copy trait implementare - - let patched_data = json!({ - "data":{ - "Corefile": corefile_copy - } - }); - - let temp_coredns_patch = "/tmp/PatchedCoreDns"; - fs::write( - temp_coredns_patch, - serde_json::to_string_pretty(&patched_data)?, - )?; - - info!("CoreDNS updated successfully at {}", temp_coredns_patch); - - //apply the corefile patched file after user decision - if corefile.contains("cortexflow-edge.dns:53") { - error!("Configuration block already present, skipping update."); - } else { - /* warn!("Do you want to patch the coredns configuration? Yes[Y] No[N]"); - let mut input = String::new(); - std::io::stdin().read_line(&mut input)?; - *///if input.trim().eq_ignore_ascii_case("Y") { - info!("\nInserting patch:"); - info!("{:?}\n",stub_domain_str_copy); - *corefile = format!("{}{}", corefile, stub_domain_str_copy); - - - //send the patch to the cluster - let patch_data = json!({ - "data": { - "Corefile": corefile.clone() - } - }); - - let patch_new = Patch::Merge(patch_data); - - configmaps - .patch("coredns", &PatchParams::default(), &patch_new) - .await?; - - - //TODO: add error handler - - //logging - info!("Patched corefile successfully:\n"); - info!("{:?}", corefile); - } //else { - //logging - // error!("Corefile not patched"); - //} - } - } - - Ok(()) -} - - -fn get_kubernetes_plugin_str(cfg: EdgeDNSConfig) -> Result { - - if cfg.enable { - let plugin_config = KubernetesPluginInfo { - api_server: cfg - .kube_api_config - .as_ref() - .and_then(|server| server.master.clone()) - .unwrap_or(" ".to_owned()), - - ttl: cfg - .cache_dns - .as_ref().map(|cache| cache.cache_ttl) - .unwrap_or(DEFAULT_TTL), - }; - generate_kubernetes_plugin_block(plugin_config) - } else { - Ok("".to_string()) - } -} diff --git a/core/src/components/kernel/src/kernel.rs b/core/src/components/kernel/src/kernel.rs deleted file mode 100644 index 41dac2d..0000000 --- a/core/src/components/kernel/src/kernel.rs +++ /dev/null @@ -1,219 +0,0 @@ -/* Resource -https://github.com/EmilHernvall/dnsguide/blob/master/chapter1.md -*/ - -/* CoreDNS-->Dns resolver di Kubernetes */ -/* Kubernetes in rust: - https://www.shuttle.dev/blog/2024/10/22/using-kubernetes-with-rust -*/ -#[allow(unused_imports)] - -use anyhow::{Error, Result}; -use std::sync::Arc; -use kube::Client; -use std::net::SocketAddr; -use tokio::net::UdpSocket; -use tracing::{error,info,warn,instrument}; -use trust_dns_server::authority::{AuthorityObject, Catalog}; -use trust_dns_server::proto::rr::{Name,Record,RecordType,RData}; -use trust_dns_server::authority::ZoneType; -use trust_dns_server::server::ServerFuture; -use trust_dns_server::store::in_memory::InMemoryAuthority; -use trust_dns_server::proto::rr::rdata::A; -use std::net::Ipv4Addr; - -use std::fs; -use tokio::signal; -use shared::apiconfig::EdgeDNSConfig; - -use crate::corefile::update_corefile; - -#[derive(Debug)] -pub struct EdgeDNS { - edgednsconfig: Arc, -} - -impl EdgeDNS { - pub fn name(&self) -> &str { - &self.edgednsconfig.module_name - } - pub fn group(&self) -> &str { - &self.edgednsconfig.edge_mode - } - pub fn enable(&self) -> bool { - self.edgednsconfig.enable - } - pub fn get_kernel_info(&self) { - info!("Kernel info:\n"); - info!("name: {}", self.name()); - info!("group: {}", self.group()); - info!("enabled: {}\n", self.enable()); - } - #[instrument] - pub async fn start(&self) { - if self.enable() { - self.run().await; - } else { - warn!("kernel is disabled"); - } - } - #[instrument] - pub async fn run(&self) { - - if !self.enable(){ - error!("EdgeDNS is not enabled"); - } - info!("EdgeDNS is running "); - - //cache_dns_enable - if self.edgednsconfig.cache_dns.clone().unwrap().enable { - info!("Running TrustDNS as a cache DNS server"); - } else { - info!("Running TrustDNS as a local DNS server"); - } - - let addr: SocketAddr = "0.0.0.0:5000".parse().unwrap(); //changed the port from 53-->5000 5353 is the alternative port for the dns - - // TODO: automatic select address - //TODO: add support for recursion - //TODO: add auto port recognition if the port is not available - - let socket = UdpSocket::bind(addr).await.unwrap(); - info!("Listening for DNS requests on {}", addr); - - let local_name = "example.com."; - let origin = Name::root(); - - let authority = Arc::new(InMemoryAuthority::empty( - Name::parse(local_name, Some(&origin)).expect("Failed to parse domain name"), - ZoneType::Primary, // Zone type - false, - )); - - // Create a DNS record - let mut record = Record::with( - Name::parse("www.example.com.", None).unwrap(), - RecordType::A, - self.edgednsconfig.cache_dns.clone().unwrap().cache_ttl, - ); - - record.set_data(Some(RData::A(A(Ipv4Addr::new(192, 168, 0, 1))))); - - // Aggiungi il record all'autorità - authority.upsert(record, 0).await; - - let mut catalog = Catalog::new(); - catalog.upsert( - Name::parse(local_name, Some(&origin)) - .expect("Failed to parse domain name").into(), - Box::new(authority) as Box, // Correzione qui - ); - - let mut server = ServerFuture::new(catalog); - server.register_socket(socket); - - // Inizializzazione di un meccanismo di "shutdown" basato su un errore o su un input - // Esegui la selezione - let server_result:Result<(), anyhow::Error> = tokio::select! { - _ = server.block_until_done() => { - info!("Server stopped gracefully"); - Ok(()) - }, - _ = self.wait_for_shutdown() => { - info!("Shutdown command received"); - Err(anyhow::anyhow!("Shutting down the server")) - } - }; - - // handle the server_result - match server_result { - Ok(_) => { - info!("Server stopped gracefully"); - } - Err(err) => { - error!("Server encountered an error: {}", err); - self.shutdown().await; // Chiamata alla funzione di shutdown - } - } - } - - async fn wait_for_shutdown(&self) -> Result<(), String> { - // wait for sigint for shutting down - let ctrl_c = async { - signal::ctrl_c() - .await - .expect("Failed to listen for Ctrl + C signal"); - info!("Ctrl + C received, shutting down..."); - }; - - tokio::select! { - _ = ctrl_c => { - // if sigint is triggered shut down the server and reutrn an error msg - Err("Ctrl + C received, shutting down".to_string()) - } - } - } - - #[instrument] - pub async fn shutdown(&self) { - info!("Shutting down the EdgeDNS "); - - - info!("Shutting down EdgeDNS server"); - - - // clear the resources - if self.edgednsconfig.kube_api_config.clone().unwrap().delete_kube_config { - if let Err(err) = fs::remove_file("/path/to/temp/kubeconfig") { - error!("Failed to delete kubeconfig: {}", err); - } - //TODO: remove the temp files - } - - info!("EdgeDNS shutdown complete."); - } - - pub async fn new( - edgednscfg: EdgeDNSConfig, - client: Client, - ) -> Result { - // Update Corefile if EdgeDNS is enabled - update_corefile(edgednscfg.clone(), &client.clone()).await?; - - /* Reference as_ref: - https://doc.rust-lang.org/std/convert/trait.AsRef.html - */ - Ok(EdgeDNS { - edgednsconfig: Arc::new(edgednscfg), - }) - } - - //registers a service - - //TODO: delete this part - /* pub fn register(config: ApiConfig, client: Client) -> Result<(), Error> { - // Load the KubeEdge shared library - let library_path = "../../core/kubeedge-wrapper/libkubeedge.so"; - let library = unsafe { - // Load the shared library using libloading::Library - Library::new(library_path).expect("Failed to load libkubeedge.so") - }; - - unsafe { - // Load the InitKubeEdge function from the shared library - let register: Symbol *const i8> = library - .get(b"Register\0") - .expect("Failed to load InitKubeEdge"); - - // Path to the configuration file - let config_path = CString::new("/path/to/config").expect("CString::new failed"); - - // Call the InitKubeEdge function - let result_ptr = register(config_path.as_ptr()); - let result_str = CStr::from_ptr(result_ptr).to_string_lossy(); - - println!("Result from InitKubeEdge: {}", result_str); - } - Ok(()) - } */ -} diff --git a/core/src/components/kernel/src/main.rs b/core/src/components/kernel/src/main.rs deleted file mode 100644 index 89d4691..0000000 --- a/core/src/components/kernel/src/main.rs +++ /dev/null @@ -1,58 +0,0 @@ -// module imports - -mod kernel; -mod corefile; -mod utilities; - -use anyhow::Result; - -use tracing_subscriber::fmt::format::FmtSpan; -use tracing_subscriber::EnvFilter; - -use shared::apiconfig::EdgeDNSConfig; -use shared::default_api_config::ConfigType; - - -use crate::kernel::EdgeDNS; - - -use kube::{api::Api, Client}; -use k8s_openapi::api::core::v1::ConfigMap; - - -const CONFIG_PATH: &str = "CONFIG_PATH"; - -#[tokio::main] -async fn main() -> Result<(), anyhow::Error> { - //tracing subscriber for logging purposes - tracing_subscriber::fmt() - .with_max_level(tracing::Level::INFO) - .with_target(false) - .with_level(true) - .with_span_events(FmtSpan::NONE) - .without_time() - .with_file(false) - .pretty() - .with_env_filter(EnvFilter::new("info")) - .with_line_number(false) - .init(); - - // Load the configuration from the Kubernetes API: - /* Workflow: - - load the configmap from the Kubernetes API - - read the dns config from the configmap - - apply the configmap - - start the server - */ - - let client = Client::try_default().await?; - let configmap: Api = Api::namespaced(client.clone(), "cortexflow"); - - let edgecfg = EdgeDNSConfig::load_from_configmap(configmap, ConfigType::Default).await?; - - let edgedns = EdgeDNS::new(edgecfg, client.clone()).await?; - edgedns.get_kernel_info(); - edgedns.start().await; - - Ok(()) -} \ No newline at end of file diff --git a/core/src/components/kernel/src/mod.rs b/core/src/components/kernel/src/mod.rs deleted file mode 100644 index accc8e6..0000000 --- a/core/src/components/kernel/src/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod kernel; -pub mod corefile; -pub mod utilities; diff --git a/core/src/components/kernel/src/utilities.rs b/core/src/components/kernel/src/utilities.rs deleted file mode 100644 index b2e9b4f..0000000 --- a/core/src/components/kernel/src/utilities.rs +++ /dev/null @@ -1,47 +0,0 @@ -/* - UTILITIES: support functions used in the kernel crate - -*/ -#[allow(unused_imports)] -use std::net::Ipv4Addr; -use itertools::Itertools; -use pnet::datalink::interfaces; - -pub fn is_valid_ip(ip: &str) -> bool { - /* check if an ip address is valid or not*/ - ip.parse::().is_ok() -} -pub fn is_valid_port(port: &str) -> bool { - /* - Workflow: - - convert the port from string to i32 integer - - check if the port is between 0 and 1 - - OK: return true - - Err: return false + error status - */ - let port_enum = port.parse::().unwrap(); - 0 < port_enum && port_enum < 65536 -} -pub fn remove_duplicates(ss: Vec)->Vec { - /* - Workflow: - - into_iter(): - Turns ss into an iterator of owned elements. - - unique(): - Filters out duplicates while maintaining the original order. - - collect(): - Collects the filtered elements into a new container. - - */ - ss.into_iter().unique().collect() -} - - -pub fn get_interfaces(){ - let interfaces = interfaces(); - println!("Eligible interfaces:"); - for iface in interfaces{ - println!("interface:{}",iface.name); - } -} - diff --git a/core/src/shared/Cargo.toml b/core/src/shared/Cargo.toml deleted file mode 100644 index 4779959..0000000 --- a/core/src/shared/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "shared" -version = "0.1.0" -edition = "2021" - -[dependencies] -actix-web = "4.9.0" -clap = "4.5.21" -tokio = { version = "1", features = ["full"] } -tracing = "0.1.40" -futures = "0.3.31" -anyhow = "1.0.93" -schemas = "0.4.0" -yaml-rust2 = "0.10.3" -kube = { version = "1.1.0", features = ["runtime", "derive", "ws"]} -k8s-openapi = { version = "0.25.0", features = ["v1_32"] } -serde_json = "1.0.133" -tokio-util = { version = "0.7.8", features = ["io"] } -tokio-stream = { version = "0.1.9", features = ["net"] } -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -serde = { version = "1.0", features = ["derive"] } -hyper-util = "0.1.10" -tower = "0.5.1" -ipnet = "2.10.1" -iptables = "0.5.2" -itertools = "0.14.0" -libc = "0.2.164" -libloading = "0.8.5" -libp2p = "0.56.0" -serde_yaml = "0.9.34" -pnet = "0.35.0" -bytes = "1.9.0" -prost = "0.14.1" -rdkafka = "0.38.0" -trust-dns-server = "0.23.2" -dirs = "6.0.0" - -[lib] -name = "shared" -path = "src/lib.rs" diff --git a/core/src/shared/src/apiconfig.rs b/core/src/shared/src/apiconfig.rs deleted file mode 100644 index 89e1aa0..0000000 --- a/core/src/shared/src/apiconfig.rs +++ /dev/null @@ -1,188 +0,0 @@ -/*! - This module defines a series of configuration structures for a - distributed network infrastructure. It includes parameters for - components such as Edge Mesh, Gateway, DNS, and CNI (Container Network Interface). - - Key functionalities: - - **Kubernetes API Configuration**: - Manages parameters for interacting with the Kubernetes API using the - `KubeApiConfig` structure. - - - **Edge Mesh Configuration**: - Configures agents (`EdgeMeshAgentConfig`) and gateways (`EdgeMeshGatewayConfig`) - for the Edge Mesh network. - - - **Edge DNS**: - Defines parameters for a custom DNS system, including interfaces, - ports, and caching, through the `EdgeDNSConfig` structure. - - - **Edge Proxy**: - Configures the Edge network proxy, with support for load balancing - and Socks5 (`EdgeProxyConfig`). - - - **CNI Configuration**: - Manages containerized network settings, such as tunneling and Mesh CIDR, - using the `EdgeCNIConfig` structure. - - - **Gateway Components**: - Configures specific gateway settings via `EdgeGatewayConfig`. - - Features: - - **Serialization and Deserialization**: - Uses `Serialize` and `Deserialize` traits to support formats like JSON and YAML. - - **Modularity**: - Independent configurations for clear and scalable management. - - **Flexibility**: - The use of `Option` allows for partial and customizable configurations. - - This module is designed as an integral part of a distributed system's - edge computing configuration. -*/ - - - -#[allow(unused_imports)] - - -use serde::{Deserialize, Serialize}; - -// ================================================================== -// ======================== Agent Section =========================== -// ================================================================== - -pub struct EdgeMeshAgentConfig { - pub kubeapi_config: Option, - pub common_config: Option, - pub modules : Option, -} -pub struct AgentModules { - pub edge_dns_config: Option, - pub edge_proxy_config: Option, - pub edge_cni_config: Option, -} - - -// ================================================================== -// ======================= Gateway Section ========================== -// ================================================================== - -pub struct EdgeMeshGatewayConfig {} -pub struct GatewayModules { - pub edge_gateway_config: Option, -} -pub struct EdgeGatewayConfig { - pub enable: bool, - pub nic: String, - pub include_ip: String, - pub exclude_ip: String, - pub loadbalancer: Option, -} - - - -// ================================================================== -// ======================= KubeAPI Section ========================== -// ================================================================== - -#[derive(Clone, Serialize, Deserialize,Debug)] -pub struct KubeApiConfig { - pub master: Option, - pub content_type: Option, - pub qps: i32, - pub burst: i32, - pub kube_config: Option, - pub meta_server: Option, - pub delete_kube_config: bool, -} -#[derive(Serialize,Deserialize,Clone)] -pub struct CommonConfig { - pub bridge_device_name: String, - pub bridge_device_ip: String, - /* pub pprof : Option */ -} -#[derive(Clone,Serialize,Deserialize)] -pub struct PprofConfig {} - -// ================================================================== -// ======================= MetaServer Section ======================= -// ================================================================== - -pub struct MetaServer { - pub server: String, - pub security: Option, -} -pub struct MetaServerSecurity {} - - -// ================================================================== -// ======================== Proxy Section =========================== -// ================================================================== - -#[derive(Serialize,Deserialize,Clone,Debug)] -pub struct EdgeProxyConfig { - pub enable: bool, - pub listen_interface: String, - //pub loadbalancer: Option, - //pub socks5proxy: Option, - //pub service_filter_mode: String, -} -#[derive(Serialize,Deserialize,Clone,Debug)] -pub struct Socks5Proxy { - pub enable: bool, - pub listen_port: i32, - pub nodename: String, - pub namespace: String, -} - -// ================================================================== -// ========================= CNI Section ============================ -// ================================================================== - - -#[derive(Serialize, Deserialize)] -pub struct EdgeCNIConfig { - pub enable: bool, - pub encap_ip: String, - pub tun_mode: i32, - pub mesh_cidr_config: Option, -} - -#[derive(Serialize, Deserialize)] -pub struct MeshCIDRConfig { - pub cloud_cidr: Vec, - pub edge_cidr: Vec, -} - -// ================================================================== -// ========================= DNS Section ============================ -// ================================================================== - -#[derive(Clone, Serialize, Deserialize,Debug)] -pub struct EdgeDNSConfig { - pub enable: bool, - pub module_name: String, - pub edge_mode: String, - pub listen_interface: String, - pub listen_port: i32, - pub kube_api_config: Option, - pub cache_dns: Option, -} - -#[derive(Clone, Serialize, Deserialize,Debug)] -pub struct CacheDNS { - pub enable: bool, - pub auto_detect: bool, - pub upstream_servers: Vec, - pub cache_ttl: u32, -} - -// ================================================================== -// ====================== LoadBalancer Section ====================== -// ================================================================== - -#[derive(Serialize,Deserialize,Clone,Debug)] -pub struct LoadBalancer { - pub caller: String, - pub nodename: String, - //add consistent hash -} diff --git a/core/src/shared/src/default_api_config.rs b/core/src/shared/src/default_api_config.rs deleted file mode 100644 index 5e45c9b..0000000 --- a/core/src/shared/src/default_api_config.rs +++ /dev/null @@ -1,299 +0,0 @@ -/*! - This module defines the components and parameters for the default API configuration. - - Key functionalities: - - **API Configuration (`ApiConfig`)**: - Provides the primary structure for storing API-related settings, including: - - Base directory and configuration file paths. - - Module names for EdgeMesh Agent, Gateway, DNS, Proxy, Tunnel, and CNI. - - Metadata server settings and device configurations. - - Modes for service filtering, load balancing, and discovery types. - - Other operational modes like edge, cloud, and manual modes. - - - **Configuration Loading**: - Implements methods to load configurations from YAML files for: - - Default settings. - - Version-specific settings (e.g., `V1`). - - - **EdgeCNI and EdgeDNS Configurations**: - Handles parsing of specialized sections (`edgeCNI`, `edge_dns`, `cache_dns`, `kubeapi`) - within the configuration file for fine-grained control. - - Features: - - **Error Handling**: - Uses the `anyhow` crate for detailed context in error reporting. - - **Serialization and Deserialization**: - Supports `Serialize` and `Deserialize` traits for seamless integration with YAML. - - **Configurable Defaults**: - Offers predefined defaults for critical parameters such as `ServiceFilterMode`, - `LoadBalancerCaller`, and `DiscoveryType`. - - This module is essential for initializing and managing configurations in - distributed systems with complex edge and cloud operations. -*/ -#[allow(unused_imports)] -use anyhow::anyhow; -use anyhow::{Context, Result}; -use k8s_openapi::api::core::v1::ConfigMap; -use kube::Api; -use serde::{Deserialize, Serialize}; -use serde_yaml; -use std::fs::File; -use std::result::Result::Ok; -use tracing_subscriber::fmt::format; - -use crate::apiconfig::{ - AgentModules, CommonConfig, EdgeCNIConfig, EdgeDNSConfig, EdgeMeshAgentConfig, EdgeProxyConfig, -}; -use crate::params::{DiscoveryType, LoadBalancerCaller, ServiceFilterMode}; - -#[derive(Debug)] -pub enum ConfigType { - Default, - V1, -} - -#[derive(Clone, Serialize, Deserialize, Debug)] -pub struct ApiConfig { - pub base_dir: String, - pub config_file: String, - pub edgemesh_agent_config_name: String, - pub edgemesh_gateway_config_name: String, - pub edgemesh_proxy_module_name: String, - pub edgemesh_tunnel_module_name: String, - pub edgemesh_cni_module_name: String, - pub bridge_device_name: String, - pub bridge_device_ip: String, - pub tun_device_name: String, - pub temp_kube_config_path: String, - pub temp_core_file_path: String, - pub meta_server_address: String, - pub meta_server_cert_dir: String, - pub meta_server_ca_file: String, - pub meta_server_cert_file: String, - pub meta_server_key_file: String, - pub cloud_mode: String, - pub manual_mode: String, - pub empty_node_name: String, - pub empty_pod_name: String, - pub service_filter_mode: Option, - pub loadbalancer_caller: Option, - pub discovery_type: Option, -} - -impl ApiConfig { - pub fn load_from_file>( - path: P, - config_type: ConfigType, - ) -> Result { - let cur_path = std::env::current_dir()?; - println!("The current directory is {}", cur_path.display()); - println!( - "Trying to load configuration from path: {}", - path.as_ref().display() - ); - let cfg_file = File::open(&path).with_context(|| { - format!( - "Problem opening config file in path {}", - path.as_ref().display() - ) - })?; - let config_map: serde_yaml::Value = - serde_yaml::from_reader(cfg_file).context("Failed to parse YAML")?; - - let config_section = match config_type { - ConfigType::Default => &config_map["default"], - ConfigType::V1 => &config_map["v1"], - }; - - let config: ApiConfig = serde_yaml::from_value(config_section.clone()) - .context("Failed to extract config section")?; - - Ok(ApiConfig { - service_filter_mode: Some(ServiceFilterMode { - filter_if_label_exists_mode: String::from( - ServiceFilterMode::filter_if_label_exists_mode(), - ), - filter_if_label_doesn_not_exists_mode: String::from( - ServiceFilterMode::filter_if_label_doesn_not_exists_mode(), - ), - }), - loadbalancer_caller: Some(LoadBalancerCaller { - proxy_caller: String::from(LoadBalancerCaller::proxy_caller()), - gateway_caller: String::from(LoadBalancerCaller::gateway_caller()), - }), - discovery_type: Some(DiscoveryType { - mdns_discovery: String::from(DiscoveryType::mdns_discovery()), - dht_discovery: String::from(DiscoveryType::dht_discovery()), - }), - ..config - }) - } -} -impl EdgeCNIConfig { - pub fn load_from_file>( - path: P, - config_type: ConfigType, - ) -> Result { - let cfg_file = File::open(path).context("Errore nell'aprire il file di configurazione")?; - - // Analizza il file YAML - let config_map: serde_yaml::Value = - serde_yaml::from_reader(cfg_file).context("Errore nella lettura del file YAML")?; - - // Seleziona la sezione corretta del file di configurazione - let config_section = match config_type { - ConfigType::Default => &config_map["default"], - ConfigType::V1 => &config_map["v1"], - }; - - // EdgeCNI section - let edgecni_section = config_section.get("edgeCNI").ok_or_else(|| { - anyhow::anyhow!("'edgeCNI' section doesn not exists in the config file") - })?; - - let edgecni_config: EdgeCNIConfig = serde_yaml::from_value(edgecni_section.clone()) - .context("Error parsing 'edgeCNI' section")?; - - Ok(EdgeCNIConfig { ..edgecni_config }) - } -} -impl EdgeDNSConfig { - pub async fn load_from_configmap( - configmap: Api, - config_type: ConfigType, - ) -> Result { - // Get the content of config.yaml from Kubernetes ConfigMap - let cm = configmap - .get("cortexbrain-client-config") - .await - .context("Failed to get ConfigMap")?; - let config_data = cm - .data - .ok_or_else(|| anyhow::anyhow!("No data in ConfigMap"))?; - let config_yaml = config_data - .get("config.yaml") - .ok_or_else(|| anyhow::anyhow!("Missing 'config.yaml' in ConfigMap data"))? - .clone(); - // Now parse the YAML content - let config_map: serde_yaml::Value = serde_yaml::from_str(&config_yaml) - .context("Error reading the yaml file from Kubernetes")?; - // Extract the relevant config section - let configs = config_map; - // Select the correct version - let config_section = match config_type { - ConfigType::Default => &configs["default"], - ConfigType::V1 => &configs["v1"], - }; - // Edge DNS Section - let edge_dns_section = config_section.get("edge_dns").ok_or_else(|| { - anyhow::anyhow!("'edge_dns' section does not exist in the config file") - })?; - let edge_dns_config: EdgeDNSConfig = serde_yaml::from_value(edge_dns_section.clone()) - .context("Error parsing 'edge_dns' section")?; - // Cache DNS section - let cache_dns_section = config_section.get("cache_dns"); - let cache_dns_config = if let Some(cache_dns_section) = cache_dns_section { - Some( - serde_yaml::from_value(cache_dns_section.clone()) - .context("Error parsing 'cache dns' section")?, - ) - } else { - None - }; - // KubeAPI section - let kubeapi_section = config_section.get("kubeapi"); - let kubeapi_config = if let Some(kubeapi_section) = kubeapi_section { - Some( - serde_yaml::from_value(kubeapi_section.clone()) - .context("Error parsing 'kubeapi' section")?, - ) - } else { - None - }; - // Return the EdgeDNS configuration - Ok(EdgeDNSConfig { - cache_dns: cache_dns_config, - kube_api_config: kubeapi_config, - ..edge_dns_config - }) - } -} -impl CommonConfig { - pub fn load_from_file>( - path: P, - config_type: ConfigType, - ) -> Result { - let cfg_file = File::open(path); - - let file = match cfg_file { - Ok(file) => file, - Err(error) => panic!("Problem opening the file: {error:?}"), - }; - - let config_map: serde_yaml::Value = - serde_yaml::from_reader(file).context("Failed to parse YAML")?; - - let config_section = match config_type { - ConfigType::Default => &config_map["default"], - ConfigType::V1 => &config_map["v1"], - }; - - let common_config: CommonConfig = serde_yaml::from_value(config_section.clone()) - .context("Failed to extract config section")?; - - // Return the CommonConfig configuration - Ok(CommonConfig { - bridge_device_name: common_config.bridge_device_name, - bridge_device_ip: common_config.bridge_device_ip, - }) - } -} - -impl EdgeProxyConfig { - pub async fn load_from_configmap(configmap: Api, config_type: ConfigType)->Result { - // Get the content of config.yaml from Kubernetes ConfigMap - let cm = configmap - .get("cortexbrain-client-config") - .await - .context("Failed to get ConfigMap")?; - - let config_data = cm - .data - .ok_or_else(|| anyhow::anyhow!("No data in ConfigMap"))?; - - let config_yaml = config_data - .get("config.yaml") - .ok_or_else(|| anyhow::anyhow!("Missing 'config.yaml' in ConfigMap data"))? - .clone(); - - // Now parse the YAML content - let config_map: serde_yaml::Value = serde_yaml::from_str(&config_yaml) - .context("Error reading the yaml file from Kubernetes")?; - - // Extract the relevant config section - let configs = config_map; - // Select the correct version - let config_section = match config_type { - ConfigType::Default => &configs["default"], - ConfigType::V1 => &configs["v1"], - }; - - //read the proxy section - let proxy_section = config_section - .get("proxy") - .ok_or_else(|| anyhow::anyhow!("'Proxy section does not exists in the config file"))?; - - let proxy_config: EdgeProxyConfig = serde_yaml::from_value(proxy_section.clone()).context("Error parsing the 'proxy' section")?; - - - //return the Proxy configuration - Ok(EdgeProxyConfig{ - ..proxy_config - }) - } - -} - -impl EdgeMeshAgentConfig {} -impl AgentModules {} diff --git a/core/src/shared/src/developers_msg.rs b/core/src/shared/src/developers_msg.rs deleted file mode 100644 index fda89cb..0000000 --- a/core/src/shared/src/developers_msg.rs +++ /dev/null @@ -1,53 +0,0 @@ -/* - Dashboard for CortexFlow Developers - Includes: - - Changelog - - Whats new - - Open Issues -*/ - -use tracing::{warn,info,instrument}; - -#[instrument] -pub fn info() { - info!( - " - Welcome to the CortexFlow Developers Dashboard, introduced on January 27th, 2025. - This tool provides a summary of updates, new features, and a list of unresolved issues in the core functionalities. - The dashboard is designed to help CortexBrain developers focus on addressing key challenges in the core system, - enabling efficient collaboration and progress. - \n" - ); - warn!("Requirements: Docker, Kubernetes, Apache Kafka"); - whats_new(); - changelog(); - problems_to_solve(); -} -#[instrument] -pub fn changelog() { - info!("------------------ C H A N G E L O G -------------------\n"); - info!("29.01.2025"); - info!("1-added send message function and consume_and_forward functions in kafka.rs"); - info!("2-added expection handler in update_corefile function. If the interface is unavailable it show the available interfaces"); - info!("27.01.2025"); - info!("- Added APIs for 'Default' and 'V1' base configurations"); - info!("- Introduced a developer message tab"); - info!("- Refactored client code to align with the new crate structure"); - info!("- Added TODO comments for future improvements\n"); -} - -#[instrument] -pub fn whats_new() { - warn!( - "- This is the first pre-alpha version of CortexBrain. Expect some bugs as extensive testing is still required." - ); -} - -#[instrument] -pub fn problems_to_solve() { - warn!("--------------- O P E N I S S U E S ------------------\n"); - warn!("1. The 'validation.rs' module requires full implementation."); - warn!("2. The 'update_corefile' function requires a code review."); - warn!("3. In 'edgecni.rs', the 'run' functionality needs implementation."); - warn!("4. The 'stop' functionality in the 'close_route' function of 'edgecni.rs' needs implementation.\n"); -} diff --git a/core/src/shared/src/lib.rs b/core/src/shared/src/lib.rs deleted file mode 100644 index 22ff467..0000000 --- a/core/src/shared/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod developers_msg; -pub mod apiconfig; -pub mod default_api_config; -pub mod params; \ No newline at end of file diff --git a/core/src/shared/src/main.rs b/core/src/shared/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/core/src/shared/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/core/src/shared/src/params.rs b/core/src/shared/src/params.rs deleted file mode 100644 index eb4b142..0000000 --- a/core/src/shared/src/params.rs +++ /dev/null @@ -1,77 +0,0 @@ -/*! - This module defines structures and parameters for key functionalities - in service filtering, load balancing, and service discovery. - - Key components: - - **Service Filter Mode**: - Encapsulates the filtering logic for services based on label existence, - managed through the `ServiceFilterMode` structure. - - - **Load Balancer Caller**: - Defines the calling logic for proxies and gateways using the - `LoadBalancerCaller` structure. - - - **Service Discovery Type**: - Specifies discovery mechanisms, including mDNS and DHT, via - the `DiscoveryType` structure. - - Features: - - **Serialization and Deserialization**: - Structures implement `Serialize` and `Deserialize` traits for compatibility - with formats such as JSON and YAML. - - **Modularity**: - Clearly separated components allow for scalability and reuse. - - **Convenient Defaults**: - Static methods provide default values for common use cases, such as - `"FilterIfLabelExists"` or `"ProxyCaller"`. - - This module is intended for use in distributed systems requiring flexible - configurations for service filtering, load balancing, and discovery protocols. -*/ - -use serde::{Deserialize, Serialize}; - -/* ServiceFilter Mode */ -#[derive(Debug, Deserialize, Clone, Serialize)] -pub struct ServiceFilterMode { - pub filter_if_label_exists_mode: String, - pub filter_if_label_doesn_not_exists_mode: String, -} -impl ServiceFilterMode { - pub fn filter_if_label_exists_mode() -> &'static str { - "FilterIfLabelExists" - } - pub fn filter_if_label_doesn_not_exists_mode() -> &'static str { - "FilterIfLabelDoesNotExists" - } -} - -/* LoadBalancer Caller */ -#[derive(Debug, Deserialize, Clone, Serialize)] -pub struct LoadBalancerCaller { - pub proxy_caller: String, - pub gateway_caller: String, -} -impl LoadBalancerCaller { - pub fn proxy_caller() -> &'static str { - "ProxyCaller" - } - pub fn gateway_caller() -> &'static str { - "GatewayCaller" - } -} - -//Discovery Type -#[derive(Debug, Deserialize, Clone, Serialize)] -pub struct DiscoveryType { - pub mdns_discovery: String, - pub dht_discovery: String, -} -impl DiscoveryType { - pub fn mdns_discovery() -> &'static str { - "MDNS" - } - pub fn dht_discovery() -> &'static str { - "DHT" - } -} diff --git a/core/src/testing/agent.yaml b/core/src/testing/agent.yaml index 67a79c0..2bdb4a6 100644 --- a/core/src/testing/agent.yaml +++ b/core/src/testing/agent.yaml @@ -37,6 +37,9 @@ spec: echo "checking if conntracker path" ls -l /usr/src/cortexbrain-agent/conntracker + echo "checking if the bpf maps are reachable" + ls -l /sys/fs/bpf/maps + echo "Running application..." exec /usr/local/bin/agent-api || echo "Application exited with code $?" volumeMounts: @@ -87,5 +90,7 @@ spec: name: agent-server-port port: 9090 targetPort: 9090 + appProtocol: grpc + nodePort: 30092 type: NodePort --- diff --git a/core/src/testing/identity.yaml b/core/src/testing/identity.yaml index a8f1956..7c96ce1 100644 --- a/core/src/testing/identity.yaml +++ b/core/src/testing/identity.yaml @@ -17,6 +17,40 @@ spec: spec: hostPID: true hostNetwork: true + initContainers: + - name: bpf-map-permissions + image: ubuntu:24.04 + command: ["/bin/bash","-c"] + args: + - | + echo "mounting the bpf path " + mount -t bpf bpf /sys/fs/bpf + + echo "checking permissions" + ls -ld /sys/fs/bpf + + volumeMounts: + - name: bpf + mountPath: /sys/fs/bpf + mountPropagation: Bidirectional + readOnly: false + - name: proc + mountPath: /host/proc + readOnly: false + - name: kernel-dev + mountPath: /lib/modules + readOnly: false + securityContext: + runAsUser: 0 + privileged: true + allowPrivilegeEscalation: true + capabilities: + add: + - SYS_ADMIN + - NET_ADMIN + - SYS_RESOURCE + - BPF + - SYS_PTRACE containers: - name: identity image: lorenzotettamanti/cortexflow-identity:latest @@ -36,6 +70,13 @@ spec: echo "Running application..." exec /usr/local/bin/cortexflow-identity-service || echo "Application exited with code $?" + resources: + limits: + cpu: "1" + memory: "200Mi" + requests: + cpu: "1" + memory: "100Mi" volumeMounts: - name: bpf mountPath: /sys/fs/bpf @@ -71,6 +112,13 @@ spec: - name: kernel-dev mountPath: /lib/modules readOnly: false + resources: + limits: + cpu: "1" + memory: "200Mi" + requests: + cpu: "1" + memory: "100Mi" securityContext: privileged: true allowPrivilegeEscalation: true diff --git a/core/xtask/Cargo.toml b/core/xtask/Cargo.toml deleted file mode 100644 index c0da400..0000000 --- a/core/xtask/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "xtask" -version = "0.1.0" -edition = "2024" - -[dependencies] -clap = { version = "4.5.38", features = ["derive"] } -aya-tool = { git = "https://github.com/aya-rs/aya" } -anyhow = "1.0.98" diff --git a/core/xtask/src/main.rs b/core/xtask/src/main.rs deleted file mode 100644 index 128cf18..0000000 --- a/core/xtask/src/main.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* copied from https://github.com/aya-rs/book/blob/main/examples/cgroup-skb-egress/xtask/src/main.rs */ -use anyhow::{Context as _, Result}; -use clap::Parser; - -#[derive(Debug, Parser)] -pub struct Options { - #[clap(subcommand)] - command: Command, -} - -#[derive(Debug, Parser)] -enum Command { - Codegen { output: std::path::PathBuf }, -} - -fn main() -> Result<()> { - match Parser::parse() { - Command::Codegen { output } => { - let bindings = aya_tool::generate::generate( - aya_tool::generate::InputFile::Btf(std::path::PathBuf::from( - "/sys/kernel/btf/vmlinux", - )), - &["iphdr"], - &[], - ) - .context("generate")?; - std::fs::write(&output, &bindings).context("write")?; - } - } - Ok(()) -} \ No newline at end of file