From 8e98ba6d27c35767eea8f8b59673c47448873c3c Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Mon, 22 Dec 2025 17:08:44 +0100 Subject: [PATCH 1/4] feat(k8s-intf): add utils to read crd from json/yaml Signed-off-by: Fredi Raspall --- Cargo.lock | 1 + k8s-intf/Cargo.toml | 1 + k8s-intf/src/lib.rs | 1 + k8s-intf/src/utils.rs | 45 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 k8s-intf/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 5010fe1de..786c1951b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1409,6 +1409,7 @@ dependencies = [ "serde", "serde-duration-ext", "serde_json", + "serde_yaml_ng", "thiserror 2.0.17", "tokio", "tracing", diff --git a/k8s-intf/Cargo.toml b/k8s-intf/Cargo.toml index a3efed406..95fc5fc8f 100644 --- a/k8s-intf/Cargo.toml +++ b/k8s-intf/Cargo.toml @@ -27,6 +27,7 @@ schemars = { workspace = true, features = ["derive", "std"] } serde = { workspace = true } serde-duration-ext = { workspace = true } serde_json = { workspace = true } +serde_yaml_ng = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } diff --git a/k8s-intf/src/lib.rs b/k8s-intf/src/lib.rs index b6beb6718..d7d8dc0b2 100644 --- a/k8s-intf/src/lib.rs +++ b/k8s-intf/src/lib.rs @@ -9,6 +9,7 @@ pub mod bolero; pub mod client; pub mod generated; +pub mod utils; pub mod gateway_agent_crd { pub use crate::generated::gateway_agent_crd::*; diff --git a/k8s-intf/src/utils.rs b/k8s-intf/src/utils.rs new file mode 100644 index 000000000..1828da73c --- /dev/null +++ b/k8s-intf/src/utils.rs @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Open Network Fabric Authors + +//! Utils to build the gateway CRD `GatewayAgentSpec` from JSON / YAML text files. + +use crate::gateway_agent_crd::GatewayAgentSpec; +use serde_yaml_ng; +use std::fs; +use std::path::Path; + +/// Read the file at `path` and deserialize it from YAML into a `GatewayAgentSpec` object. +fn load_crd_from_yaml(path: &str) -> Result { + let yaml = fs::read_to_string(path) + .map_err(|e| format!("Failed to read CRD from YAML file ({path}): {e}"))?; + let crd: GatewayAgentSpec = serde_yaml_ng::from_str(&yaml) + .map_err(|e| format!("Failed to deserialize CRD from YAML file ({path}): {e}"))?; + Ok(crd) +} + +/// Read the file at `path` and deserialize it from JSON into a `GatewayAgentSpec` object. +fn load_crd_from_json(path: &str) -> Result { + let json = fs::read_to_string(path) + .map_err(|e| format!("Failed to read CRD from JSON file ({path}): {e}"))?; + let crd: GatewayAgentSpec = serde_json::from_str(&json) + .map_err(|e| format!("Failed to deserialize CRD from JSON file ({path}): {e}"))?; + Ok(crd) +} + +/// Read the file at `path` and deserialize into a `GatewayAgentSpec` object. +/// The file is assumed to contain a gateway spec CRD in JSON or YAML. +/// +/// # Errors +/// This function may fail if the file does not exist or cannot be opened / read, or if the contents +/// cannot be deserialized. +pub fn load_crd_from_file(path: &str) -> Result { + let ext = Path::new(path).extension(); + match ext { + Some(ext) if ext.eq_ignore_ascii_case("yaml") || ext.eq_ignore_ascii_case("yml") => { + load_crd_from_yaml(path) + } + Some(ext) if ext.eq_ignore_ascii_case("json") => load_crd_from_json(path), + Some(ext) => Err(format!("Unsupported file extension {}", ext.display())), + None => Err("Missing file extension".to_string()), + } +} From 5c124097abe6f3012a0757da284015cfa8904067 Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Mon, 22 Dec 2025 19:02:37 +0100 Subject: [PATCH 2/4] feat(k8s-less): add k8s-less crate Adds a new crate to support kubeless mode (k8s-less), where dataplane learns its configuration by monitoring changes in files inside a directory (using inotify) that contain the gateway spec in yaml or json. Files that change in (or get added to) the watched directory get read and their contents (yaml or json) deserialized into a crd spec. From that spec, a GatewayAgent object (representing the main CRD) is built and passed to a user-provided callback. This crate attempts to mimic k8s-intf and deals only with: - the watching of files in a directory using inotify - the deserialization of those files into the GatewayAgent type. It does not attempt to populate/build any of the configuration types in crate dataplane-config. As this mode of operation may be used only for testing or development, we implement it outside of the k8s-intf crate. Signed-off-by: Fredi Raspall --- Cargo.lock | 235 ++++++++++++++++++++++++------------------ Cargo.toml | 3 + args/Cargo.toml | 2 +- k8s-less/Cargo.toml | 16 +++ k8s-less/src/lib.rs | 8 ++ k8s-less/src/local.rs | 171 ++++++++++++++++++++++++++++++ 6 files changed, 335 insertions(+), 100 deletions(-) create mode 100644 k8s-less/Cargo.toml create mode 100644 k8s-less/src/lib.rs create mode 100644 k8s-less/src/local.rs diff --git a/Cargo.lock b/Cargo.lock index 786c1951b..dcef264cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -198,7 +198,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -209,7 +209,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -398,7 +398,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -512,7 +512,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -621,7 +621,7 @@ checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -667,13 +667,13 @@ checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" dependencies = [ "clap", "heck 0.4.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "log", "proc-macro2", "quote", "serde", "serde_json", - "syn 2.0.113", + "syn 2.0.114", "tempfile", "toml", ] @@ -767,7 +767,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -854,7 +854,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1070,7 +1070,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1084,7 +1084,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1106,7 +1106,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1117,7 +1117,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1236,7 +1236,7 @@ version = "0.7.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1379,7 +1379,7 @@ dependencies = [ "dataplane-tracectl", "derive_builder 0.20.2", "futures", - "libc 1.0.0-alpha.1", + "libc 1.0.0-alpha.2", "multi_index_map", "nix 0.30.1", "rtnetlink", @@ -1416,6 +1416,19 @@ dependencies = [ "ureq", ] +[[package]] +name = "dataplane-k8s-less" +version = "0.7.0" +dependencies = [ + "dataplane-gwname", + "dataplane-k8s-intf", + "dataplane-tracectl", + "inotify", + "tokio", + "tracing", + "tracing-test", +] + [[package]] name = "dataplane-left-right-tlcache" version = "0.7.0" @@ -1767,7 +1780,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1787,7 +1800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core 0.20.2", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1809,7 +1822,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.113", + "syn 2.0.114", "unicode-xid", ] @@ -1870,7 +1883,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1949,7 +1962,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1961,7 +1974,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -1993,7 +2006,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2009,7 +2022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc 0.2.179", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2098,7 +2111,7 @@ source = "git+https://github.com/githedgehog/fixin?branch=main#5e0de31606466b173 dependencies = [ "proc-macro-error2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2231,7 +2244,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -2364,9 +2377,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -2374,7 +2387,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.12.1", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -2410,6 +2423,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "equivalent", "foldhash 0.2.0", ] @@ -2794,9 +2808,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -2804,6 +2818,28 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inotify" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +dependencies = [ + "bitflags 2.10.0", + "futures-core", + "inotify-sys", + "libc 0.2.179", + "tokio", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc 0.2.179", +] + [[package]] name = "instant" version = "0.1.13" @@ -3034,7 +3070,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3089,9 +3125,9 @@ checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "libc" -version = "1.0.0-alpha.1" +version = "1.0.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7222002e5385b4d9327755661e3847c970e8fbf9dea6da8c57f16e8cfbff53a8" +checksum = "85272f924988b0557659867ecbb172a88990b2c5175bebd38c44956e7c74e701" [[package]] name = "libflate" @@ -3150,7 +3186,7 @@ checksum = "e5cec0ec4228b4853bb129c84dbf093a27e6c7a20526da046defc334a1b017f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3283,7 +3319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3589659543c04c7dc5526ec858591015b87cd8746583b51b48ef4353f99dbcda" dependencies = [ "base64 0.22.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "metrics", "metrics-util", "quanta", @@ -3333,7 +3369,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3410,7 +3446,7 @@ checksum = "4568f25ccbd45ab5d5603dc34318c1ec56b117531781260002151b8530a9f931" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3442,7 +3478,7 @@ source = "git+https://github.com/githedgehog/testn.git?tag=v0.0.9#299344af36ed01 dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3650,7 +3686,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3753,11 +3789,11 @@ dependencies = [ [[package]] name = "ordermap" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed637741ced8fb240855d22a2b4f208dab7a06bcce73380162e5253000c16758" +checksum = "cfa78c92071bbd3628c22b1a964f7e0eb201dc1456555db072beb1662ecd6715" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", ] [[package]] @@ -3872,7 +3908,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3940,7 +3976,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -3968,7 +4004,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64 0.22.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "quick-xml", "serde", "time", @@ -4057,7 +4093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93980406f12d9f8140ed5abe7155acb10bb1e69ea55c88960b9c2f117445ef96" dependencies = [ "equivalent", - "indexmap 2.12.1", + "indexmap 2.13.0", ] [[package]] @@ -4088,14 +4124,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] name = "proc-macro2" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ "unicode-ident", ] @@ -4164,7 +4200,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4184,7 +4220,7 @@ checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4242,9 +4278,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" dependencies = [ "proc-macro2", ] @@ -4432,7 +4468,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4530,7 +4566,7 @@ dependencies = [ "bytecheck", "bytes", "hashbrown 0.16.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "munge", "ptr_meta", "rancor", @@ -4548,7 +4584,7 @@ checksum = "7f6dffea3c91fa91a3c0fc8a061b0e27fef25c6304728038a6d6bcb1c58ba9bd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4611,14 +4647,14 @@ dependencies = [ "errno", "libc 0.2.179", "linux-raw-sys 0.11.0", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "aws-lc-rs", "log", @@ -4763,7 +4799,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4870,7 +4906,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4881,14 +4917,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] name = "serde_json" -version = "1.0.148" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", @@ -4905,7 +4941,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -4939,7 +4975,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.12.1", + "indexmap 2.13.0", "schemars 0.9.0", "schemars 1.2.0", "serde_core", @@ -4953,7 +4989,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "ryu", "serde", @@ -4966,7 +5002,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "ryu", "serde", @@ -4993,7 +5029,7 @@ checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5118,9 +5154,9 @@ dependencies = [ [[package]] name = "small-map" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3212e658a14154c44759b0e2fe264bcfa369cf2aa2f789b6915de9db366d8d19" +checksum = "64c0b79fa0e86d80062670059d27f93911776cdeba2555bf428b455d8738c32f" dependencies = [ "hashbrown 0.16.1", ] @@ -5183,7 +5219,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5249,9 +5285,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.113" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -5275,7 +5311,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5294,7 +5330,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5354,7 +5390,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5365,7 +5401,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5467,7 +5503,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5560,7 +5596,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "toml_datetime", "winnow 0.5.40", ] @@ -5571,7 +5607,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_spanned", "toml_datetime", @@ -5633,7 +5669,7 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "indexmap 2.12.1", + "indexmap 2.13.0", "pin-project-lite", "slab", "sync_wrapper", @@ -5697,7 +5733,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5767,7 +5803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -5881,14 +5917,15 @@ dependencies = [ [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -6040,7 +6077,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "wasm-bindgen-shared", ] @@ -6115,7 +6152,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6126,7 +6163,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6388,28 +6425,28 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] @@ -6429,7 +6466,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", "synstructure", ] @@ -6469,11 +6506,11 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.113", + "syn 2.0.114", ] [[package]] name = "zmij" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e0d8dffbae3d840f64bda38e28391faef673a7b5a6017840f2a106c8145868" +checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8" diff --git a/Cargo.toml b/Cargo.toml index 317eeb906..b0046f199 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ "init", "interface-manager", "k8s-intf", + "k8s-less", "left-right-tlcache", "mgmt", "nat", @@ -63,6 +64,7 @@ id = { path = "./id", package = "dataplane-id", features = [] } init = { path = "./init", package = "dataplane-init", features = [] } interface-manager = { path = "./interface-manager", package = "dataplane-interface-manager", features = [] } k8s-intf = { path = "./k8s-intf", package = "dataplane-k8s-intf", features = [] } +k8s-less = { path = "./k8s-less", package = "dataplane-k8s-less", features = [] } left-right-tlcache = { path = "./left-right-tlcache", package = "dataplane-left-right-tlcache", features = [] } lpm = { path = "./lpm", package = "dataplane-lpm", features = [] } mgmt = { path = "./mgmt", package = "dataplane-mgmt", features = [] } @@ -116,6 +118,7 @@ hashbrown = { version = "0.16.1", default-features = false, features = [] } hwlocality = { version = "1.0.0-alpha.11", default-features = false, features = [] } hyper = { version = "1.8.1", default-features = false, features = [] } hyper-util = { version = "0.1.19", default-features = false, features = [] } +inotify = { version = "0.11.0", default-features = false, features = [] } ipnet = { version = "2.11.0", default-features = false, features = [] } k8s-openapi = { version = "0.26.1", default-features = false, features = [] } kanal = { version = "0.1.1", default-features = false, features = [] } diff --git a/args/Cargo.toml b/args/Cargo.toml index 8a31b0cd5..ba9226a76 100644 --- a/args/Cargo.toml +++ b/args/Cargo.toml @@ -22,7 +22,7 @@ serde = { workspace = true, features = ["derive"] } sha2 = { workspace = true, features = [] } thiserror = { workspace = true, features = [] } tracing = { workspace = true, features = ["std"] } -url = { workspace = true, features = ["std"] } +url = { workspace = true, features = ["std", "serde"] } uuid = { workspace = true, features = [] } [dev-dependencies] diff --git a/k8s-less/Cargo.toml b/k8s-less/Cargo.toml new file mode 100644 index 000000000..bd4a62d94 --- /dev/null +++ b/k8s-less/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "dataplane-k8s-less" +version.workspace = true +edition.workspace = true +license.workspace = true +publish.workspace = true +repository.workspace = true + +[dependencies] +gwname = { workspace = true } +inotify = { workspace = true, features = ["stream"] } +k8s-intf = { workspace = true } +tokio = { workspace = true, features = ["macros", "rt", "fs"] } +tracectl = { workspace = true } +tracing = { workspace = true } +tracing-test = { workspace = true } \ No newline at end of file diff --git a/k8s-less/src/lib.rs b/k8s-less/src/lib.rs new file mode 100644 index 000000000..a72f5070e --- /dev/null +++ b/k8s-less/src/lib.rs @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Open Network Fabric Authors + +//! Support for k8s-less mode where CRDs are learnt from a file + +mod local; + +pub use local::kubeless_watch_gateway_agent_crd; diff --git a/k8s-less/src/local.rs b/k8s-less/src/local.rs new file mode 100644 index 000000000..f1e3c85d4 --- /dev/null +++ b/k8s-less/src/local.rs @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Open Network Fabric Authors + +use gwname::get_gw_name; +use inotify::{Event, EventMask, Inotify, WatchMask}; +use k8s_intf::gateway_agent_crd::GatewayAgent; +use k8s_intf::utils::load_crd_from_file; +use std::collections::BTreeSet; +use std::ffi::OsStr; +use std::os::fd::AsRawFd; +use std::path::{Path, PathBuf}; +use tokio::fs::create_dir_all; +use tokio::io::unix::AsyncFd; + +#[allow(unused)] +use tracing::{debug, error, trace, warn}; + +/// Tell if an event reported by `Inotify` is worth checking according +/// to our configuration. This function is somewhat heuristic to accommodate +/// for changes done by text editors, which may create temporary files when +/// editing them instead of modifying them in-place. This helper returns +/// the name of the file to process or `None` if the event should be ignored. +fn check_event(event: &Event<&OsStr>, dir: &str) -> Option { + // trace!("event: {:?}, name: {:?}", event.mask, event.name); + + // we watch a directory; so `Inotify` should report the name of a file. + let filename = event.name?; + + // OsStr should be valid Unicode + let filename = filename.to_str()?; + + // some editors create '.swp/.swx' (e.g. nano) files or temporary hidden files (vi) + if filename.contains(".sw") || filename.starts_with('.') { + return None; + } + + // This is sanity + if event.mask != EventMask::CLOSE_WRITE { + return None; + } + + // name of file to read a crd spec from + Some(Path::new(dir).join(filename)) +} + +/// Watch for changes in the directory named `path`. If the directory does not exist, +/// it gets created. When files are created or modified in the watched directory: +/// - read their contents (assumed to contain a crd spec in yaml or json) +/// - deserialize them into a `GatewayAgentSpec` +/// - build a GatewayAgent object +/// - call the caller-specified callback. +/// +/// The generation id of the GatewayAgent is automatically set by this function and +/// monotonically increases every time a `GatewayAgentSpec` is successfully deserialized +/// from a file. +/// +/// # Errors +/// Returns an error if the directory or the corresponding watch cannot be created. +pub async fn kubeless_watch_gateway_agent_crd( + path: &str, + callback: impl AsyncFn(&GatewayAgent), +) -> Result<(), String> { + let gwname = get_gw_name().unwrap_or_else(|| { + let name = "test-gw"; + warn!("Warning, gateway name is NOT set. Setting to '{name}'..."); + name + }); + + create_dir_all(path) + .await + .map_err(|e| format!("Failed to create directory '{path}': {e}"))?; + + let mut inotify = Inotify::init().map_err(|e| format!("Failed to initialize inotify: {e}"))?; + inotify + .watches() + .add(Path::new(path), WatchMask::CLOSE_WRITE) + .map_err(|e| format!("Failed to add watch for path {path}: {e}"))?; + + // generation id is automatically set and will monotonically increase + let mut generation: i64 = 1; + + let async_fd = AsyncFd::new(inotify.as_raw_fd()) + .map_err(|e| format!("Failed to create async fd for inotify: {e}"))?; + + debug!("Starting kubeless watcher for directory '{path}'..."); + loop { + trace!("Waiting for changes..."); + let Ok(mut guard) = async_fd.readable().await else { + error!("Failure checking async fd readiness"); + continue; + }; + + let mut buffer = [0u8; 4096]; + match inotify.read_events(&mut buffer) { + Ok(events) => { + // collapse all events by filename: `check_event` will filter out unwanted events. + let files: BTreeSet = + events.filter_map(|e| check_event(&e, path)).collect(); + + // iterate over the set of files. Deserialize their contents and call user callback. + for file in files.iter() { + debug!("Processing file {file:#?}..."); + match load_crd_from_file(file.to_str().unwrap()) { + Ok(crd_spec) => { + let mut crd = GatewayAgent::new(gwname, crd_spec); + crd.metadata.generation = Some(generation); + crd.metadata.namespace = Some("fab".to_string()); + generation += 1; + callback(&crd).await; + } + Err(e) => error!("Failed to load crd spec from file: {e}"), + }; + } + } + Err(e) => error!("Failed to read events from file: {e}"), + } + guard.clear_ready(); + } +} + +#[cfg(test)] +mod test { + use std::fs::File; + use std::io::Write; + use std::path::PathBuf; + use std::time::Duration; + + use super::kubeless_watch_gateway_agent_crd; + use tracing::debug; + use tracing_test::traced_test; + + #[tokio::test] + #[traced_test] + async fn test_kubeless() { + let path = "/tmp/kubeless-dir"; + + // spawn a task to create a config file in the directory watched by kubeless + tokio::spawn(async move { + // wait 2 seconds before creating config + tokio::time::sleep(Duration::from_secs(2)).await; + + // build minimal config for us to know that it was deserialized successfully + let yaml = " +agentVersion: MINIMAL +gateway: + asn: 65000 +"; + let mut filepath = PathBuf::from(path).join("minimal-config"); + filepath.add_extension("yaml"); + let mut file = File::create(filepath.to_str().unwrap()).unwrap(); + file.write_all(yaml.as_bytes()).unwrap(); + }); + + // start watcher. Watcher will exit as soon as a config is detected and successfully + // deserialized into a GatewayAgent object + kubeless_watch_gateway_agent_crd(path, async move |crd| { + let generation = crd.metadata.generation.unwrap(); + let name = crd.metadata.name.as_ref().unwrap(); + let asn = crd.spec.gateway.as_ref().unwrap().asn.unwrap(); + let agent_version = crd.spec.agent_version.as_ref().unwrap(); + debug!("Got CRD to chew:\n generation: {generation}\n name: {name}\n agentVersion: {agent_version}\n asn: {asn}"); + assert_eq!(generation, 1); + assert_eq!(name, "test-gw"); + assert_eq!(agent_version, "MINIMAL"); + assert_eq!(asn, 65000); + std::process::exit(0); + }) + .await + .unwrap(); + } +} From e504bfa261e38386596182e9bfa45e5c97cf5611 Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Mon, 29 Dec 2025 19:09:48 +0100 Subject: [PATCH 3/4] feat(args): add cmd line arg for k8sless mode Adds --config-dir cmd line option to specify the directory in k8s- less mode and augments the ConfigServerSection to include it. Signed-off-by: Fredi Raspall --- args/src/lib.rs | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/args/src/lib.rs b/args/src/lib.rs index 32f2db251..5ead9fa62 100644 --- a/args/src/lib.rs +++ b/args/src/lib.rs @@ -555,7 +555,8 @@ pub struct RoutingConfigSection { #[rkyv(attr(derive(PartialEq, Eq, Debug)))] pub struct ConfigServerSection { /// gRPC server address (TCP or Unix socket) - pub address: GrpcAddress, + pub address: Option, + pub config_dir: Option, } /// Complete dataplane launch configuration. @@ -1088,12 +1089,12 @@ impl TryFrom for LaunchConfiguration { general: GeneralConfigSection { name: value.get_name().cloned(), }, - config_server: value - .grpc_address() - .map_err(InvalidCmdArguments::InvalidGrpcAddress)? - .map(|grpc_address| ConfigServerSection { - address: grpc_address, - }), + config_server: Some(ConfigServerSection { + address: value + .grpc_address() + .map_err(InvalidCmdArguments::InvalidGrpcAddress)?, + config_dir: value.config_dir().cloned(), + }), driver: match &value.driver { Some(driver) if driver == "dpdk" => { // TODO: adjust command line to specify lcore usage more flexibly in next PR @@ -1275,6 +1276,17 @@ E.g. default=error,all=info,nat=debug will set the default target to error, and #[arg(long, help = "Set the name of this gateway")] name: Option, + + #[arg( + long, + help = "Run in k8s-less mode using this directory to watch for configurations. +You can copy json/yaml config files in this directory to reconfigure dataplane. You can modify existing +files or just 'touch' them to trigger a new reconfiguration. Every change will increase the generation id by one. +NOTE: dataplane tracks file 'save' events. If you modify an existing file, depending on the editor used, this will +trigger more than one reconfiguration (e.g. gedit). If this is undesired, use nano or vi(m), or edit your file +elsewhere and copy it in the configuration directory. This mode is meant mostly for debugging or early testing." + )] + config_dir: Option, } impl CmdArgs { @@ -1464,6 +1476,14 @@ impl CmdArgs { pub fn get_name(&self) -> Option<&String> { self.name.as_ref() } + + /// Get the configuration directory. + /// Setting the configuration directory enables k8s-less mode, where configurations are retrieved from files + /// or their changes in the configuration directory. + #[must_use] + pub fn config_dir(&self) -> Option<&String> { + self.config_dir.as_ref() + } } #[cfg(test)] From 0678410948aee92ab7a328398ea0ba779f8d7a35 Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Mon, 29 Dec 2025 11:22:27 +0100 Subject: [PATCH 4/4] feat(mgmt): add k8s-less mode Add a k8s-less client that watches the config directory and uses the config client to request the config processor to apply a new config. Signed-off-by: Fredi Raspall --- Cargo.lock | 1 + dataplane/src/main.rs | 1 + mgmt/Cargo.toml | 1 + mgmt/src/processor/k8s_less_client.rs | 69 +++++++++++++++++++++++++++ mgmt/src/processor/launch.rs | 17 ++++++- mgmt/src/processor/mod.rs | 1 + 6 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 mgmt/src/processor/k8s_less_client.rs diff --git a/Cargo.lock b/Cargo.lock index dcef264cf..755a22fbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1472,6 +1472,7 @@ dependencies = [ "dataplane-id", "dataplane-interface-manager", "dataplane-k8s-intf", + "dataplane-k8s-less", "dataplane-lpm", "dataplane-nat", "dataplane-net", diff --git a/dataplane/src/main.rs b/dataplane/src/main.rs index bc95d53a2..4aad85604 100644 --- a/dataplane/src/main.rs +++ b/dataplane/src/main.rs @@ -158,6 +158,7 @@ fn main() { /* start management */ start_mgmt(MgmtParams { grpc_addr, + config_dir: args.config_dir().cloned(), hostname: get_gw_name().unwrap_or_else(|| unreachable!()).to_owned(), processor_params: ConfigProcessorParams { router_ctl: setup.router.get_ctl_tx(), diff --git a/mgmt/Cargo.toml b/mgmt/Cargo.toml index 5fb394b73..97cb77b86 100644 --- a/mgmt/Cargo.toml +++ b/mgmt/Cargo.toml @@ -24,6 +24,7 @@ gateway_config = { workspace = true } id = { workspace = true } interface-manager = { workspace = true } k8s-intf = { workspace = true } +k8s-less = { workspace = true } lpm = { workspace = true } nat = { workspace = true } net = { workspace = true } diff --git a/mgmt/src/processor/k8s_less_client.rs b/mgmt/src/processor/k8s_less_client.rs new file mode 100644 index 000000000..3dfc328c5 --- /dev/null +++ b/mgmt/src/processor/k8s_less_client.rs @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Open Network Fabric Authors + +use config::{ExternalConfig, GwConfig}; +use futures::TryFutureExt; +use k8s_less::kubeless_watch_gateway_agent_crd; +use std::sync::Arc; +use tracing::{error, info}; + +use crate::processor::mgmt_client::{ConfigClient, ConfigProcessorError}; + +#[derive(Debug, thiserror::Error)] +pub enum K8sLessError { + #[error("K8sless exited early")] + EarlyTermination, + #[error("Watching error: {0}")] + WatchError(String), +} + +pub struct K8sLess { + pathdir: String, + client: ConfigClient, +} + +impl K8sLess { + pub fn new(pathdir: &str, client: ConfigClient) -> Self { + Self { + pathdir: pathdir.to_string(), + client, + } + } + + pub async fn start_config_watch(k8sless: Arc) -> Result<(), K8sLessError> { + info!("Starting config watcher for directory {}", k8sless.pathdir); + + kubeless_watch_gateway_agent_crd(&k8sless.pathdir.clone(), async move |ga| { + info!("Attempting to deserialize new gateway CRD ..."); + + let external_config = ExternalConfig::try_from(ga); + match external_config { + Err(e) => error!("Failed to convert K8sGatewayAgent to ExternalConfig: {e}"), + Ok(external_config) => { + let genid = external_config.genid; + let applied_genid = match k8sless.client.get_generation().await { + Ok(genid) => genid, + Err(ConfigProcessorError::NoConfigApplied) => 0, + Err(e) => { + error!("Failed to get current config generation: {e}"); + return; + } + }; + info!("Current configuration is {applied_genid}"); + + let gwconfig = GwConfig::new(external_config); + + // request the config processor to apply the config and update status on success + match k8sless.client.apply_config(gwconfig).await { + Ok(()) => info!("Config for generation {genid} was successfully applied"), + Err(e) => error!("Failed to apply the config for generation {genid}: {e}"), + } + } + } + }) + .map_err(K8sLessError::WatchError) + .await?; + + Err(K8sLessError::EarlyTermination) + } +} diff --git a/mgmt/src/processor/launch.rs b/mgmt/src/processor/launch.rs index e51b17fa8..2e6882074 100644 --- a/mgmt/src/processor/launch.rs +++ b/mgmt/src/processor/launch.rs @@ -2,6 +2,7 @@ // Copyright Open Network Fabric Authors use crate::processor::k8s_client::{K8sClient, K8sClientError}; +use crate::processor::k8s_less_client::{K8sLess, K8sLessError}; use crate::processor::proc::ConfigProcessor; use std::fmt::Display; @@ -47,6 +48,9 @@ pub enum LaunchError { ProcessorError(std::io::Error), #[error("Error starting/waiting for Config Processor task: {0}")] ProcessorJoinError(tokio::task::JoinError), + + #[error("Error in k8s-less mode: {0}")] + K8LessError(#[from] K8sLessError), } /// Start the gRPC server on TCP @@ -181,6 +185,7 @@ impl Display for ServerAddress { pub struct MgmtParams { pub grpc_addr: Option, + pub config_dir: Option, pub hostname: String, pub processor_params: ConfigProcessorParams, } @@ -229,7 +234,17 @@ pub fn start_mgmt( Err(LaunchError::PrematureGrpcExit) } }) - } else { + } else if let Some(config_dir) = ¶ms.config_dir { + warn!("Running in k8s-less mode...."); + rt.block_on(async { + let (processor, client) = ConfigProcessor::new(params.processor_params); + let k8sless = Arc::new(K8sLess::new(config_dir, client)); + tokio::spawn(async { processor.run().await }); + K8sLess::start_config_watch(k8sless).await + })?; + Ok(()) + } + else { debug!("Will start watching k8s for configuration changes"); rt.block_on(async { let (processor, client) = ConfigProcessor::new(params.processor_params); diff --git a/mgmt/src/processor/mod.rs b/mgmt/src/processor/mod.rs index 05fff069f..20c8ddc36 100644 --- a/mgmt/src/processor/mod.rs +++ b/mgmt/src/processor/mod.rs @@ -8,6 +8,7 @@ pub(crate) mod confbuild; mod display; pub(crate) mod gwconfigdb; pub(crate) mod k8s_client; +pub(crate) mod k8s_less_client; pub(crate) mod launch; pub(crate) mod mgmt_client; pub(crate) mod proc;