From 3b04b8299881248cd0f888ffed496dd15008e7ca Mon Sep 17 00:00:00 2001 From: Daniel Lundin <dln@arity.se> Date: Sun, 12 Jan 2025 14:27:46 +0100 Subject: [PATCH 1/3] chore(clippy): cleanup --- instrumentation/src/lib.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/instrumentation/src/lib.rs b/instrumentation/src/lib.rs index 31df7f6..fd69950 100644 --- a/instrumentation/src/lib.rs +++ b/instrumentation/src/lib.rs @@ -96,20 +96,18 @@ pub fn init_tracing(otel_endpoint: Option<&String>, log_stderr: bool) -> Result< None => None, }; - let metrics_layer = match meter_provider { - Some(ref p) => Some(MetricsLayer::new(p.to_owned())), - None => None, - }; + let metrics_layer = meter_provider + .as_ref() + .map(|p| MetricsLayer::new(p.to_owned())); let tracer_provider = match otel_endpoint { Some(endpoint) => Some(init_tracer_provider(endpoint, resource)?), None => None, }; - let trace_layer = match tracer_provider { - Some(ref p) => Some(OpenTelemetryLayer::new(p.tracer("tracing-otel-subscriber"))), - None => None, - }; + let trace_layer = tracer_provider + .as_ref() + .map(|p| OpenTelemetryLayer::new(p.tracer("tracing-otel-subscriber"))); opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new()); From 9b7e1fb226e99f6a1f3e3c968960a62102147183 Mon Sep 17 00:00:00 2001 From: Daniel Lundin <dln@arity.se> Date: Wed, 8 Jan 2025 11:58:35 +0100 Subject: [PATCH 2/3] feat: Add user resource w/database as storage --- .cargo/audit.toml | 8 + Cargo.lock | 687 +++++++++++++++++- Cargo.toml | 1 + agent/Cargo.toml | 2 + api.json | 135 +++- ...9d5910bfdb2a6c9b82ddb296854973369594c.json | 47 ++ ...dc8fdfc05f489328e8376513124dfb42996e3.json | 46 ++ controller/Cargo.toml | 4 + controller/build.rs | 5 + .../migrations/20250108132540_users.sql | 7 + controller/src/api.rs | 2 + controller/src/bin/patagia-controller.rs | 23 +- controller/src/context.rs | 16 +- controller/src/lib.rs | 1 + controller/src/user/api.rs | 110 +++ controller/src/user/mod.rs | 14 + flake.nix | 5 + justfile | 34 +- 18 files changed, 1117 insertions(+), 30 deletions(-) create mode 100644 .cargo/audit.toml create mode 100644 controller/.sqlx/query-40dee0d539971f95bb3dc2ba4c49d5910bfdb2a6c9b82ddb296854973369594c.json create mode 100644 controller/.sqlx/query-843923b9a0257cf80f1dff554e7dc8fdfc05f489328e8376513124dfb42996e3.json create mode 100644 controller/build.rs create mode 100644 controller/migrations/20250108132540_users.sql create mode 100644 controller/src/user/api.rs create mode 100644 controller/src/user/mod.rs diff --git a/.cargo/audit.toml b/.cargo/audit.toml new file mode 100644 index 0000000..352d558 --- /dev/null +++ b/.cargo/audit.toml @@ -0,0 +1,8 @@ +[advisories] +ignore = [ + # Advisory about a vulnerability in rsa, which we don't use, but comes via sqlx due + # to a bug in cargo. For context, see: + # https://github.com/launchbadge/sqlx/issues/2911 + # and https://github.com/rust-lang/cargo/issues/10801 + "RUSTSEC-2023-0071" +] diff --git a/Cargo.lock b/Cargo.lock index 0c8d346..67b0d67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,6 +147,15 @@ dependencies = [ "syn", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -218,7 +227,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -227,11 +236,20 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -302,7 +320,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -352,6 +370,21 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "core-foundation" version = "0.9.4" @@ -387,6 +420,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.2" @@ -405,6 +453,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -427,6 +484,17 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe7ed1d93f4553003e20b629abe9085e1e81b1429520f897f8f8860bc6dfc21" +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "deranged" version = "0.3.11" @@ -443,7 +511,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -478,6 +548,12 @@ dependencies = [ "syn", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "dropshot" version = "0.15.1" @@ -554,6 +630,9 @@ name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] [[package]] name = "encoding_rs" @@ -580,6 +659,28 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -596,12 +697,29 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + [[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "foreign-types" version = "0.3.2" @@ -668,6 +786,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.31" @@ -790,6 +919,20 @@ name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.2", +] [[package]] name = "heck" @@ -803,6 +946,39 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "hostname" version = "0.3.1" @@ -1221,6 +1397,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libc" @@ -1228,6 +1407,12 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "libredox" version = "0.1.3" @@ -1238,6 +1423,16 @@ dependencies = [ "libc", ] +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -1287,6 +1482,16 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.7.4" @@ -1363,12 +1568,49 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1376,6 +1618,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1560,6 +1803,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -1580,7 +1829,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1595,6 +1844,7 @@ version = "0.2.0" dependencies = [ "anyhow", "clap", + "futures", "instrumentation", "progenitor", "reqwest", @@ -1602,6 +1852,7 @@ dependencies = [ "serde", "tokio", "tracing", + "uuid", ] [[package]] @@ -1617,10 +1868,21 @@ dependencies = [ "serde", "slog", "slog-async", + "sqlx", "tokio", "trace-request", "tracing", "tracing-slog", + "uuid", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", ] [[package]] @@ -1661,6 +1923,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.31" @@ -2011,6 +2294,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rsa" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2314,6 +2617,17 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2338,6 +2652,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "slab" version = "0.4.9" @@ -2407,6 +2731,9 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "socket2" @@ -2423,6 +2750,217 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlx" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" +dependencies = [ + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.15.2", + "hashlink", + "indexmap 2.7.0", + "log", + "memchr", + "once_cell", + "percent-encoding", + "rustls 0.23.20", + "rustls-pemfile", + "serde", + "serde_json", + "sha2", + "smallvec", + "thiserror 2.0.9", + "time", + "tokio", + "tokio-stream", + "tracing", + "url", + "uuid", + "webpki-roots", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" +dependencies = [ + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" +dependencies = [ + "atoi", + "base64", + "bitflags", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.9", + "time", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" +dependencies = [ + "atoi", + "base64", + "bitflags", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.9", + "time", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "time", + "tracing", + "url", + "uuid", +] [[package]] name = "stable_deref_trait" @@ -2430,6 +2968,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strsim" version = "0.11.1" @@ -2861,6 +3410,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3000,12 +3550,33 @@ dependencies = [ "typify-impl", ] +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -3099,6 +3670,12 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.99" @@ -3208,6 +3785,16 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3237,7 +3824,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3246,7 +3833,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3257,7 +3844,7 @@ checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3266,7 +3853,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3276,7 +3863,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ "windows-result", - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -3285,7 +3881,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3294,7 +3890,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -3303,28 +3914,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3337,24 +3966,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 6cf8849..ca5b5c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ clap = { version = "4.5.23", features = [ "string", ] } dropshot = "0.15.1" +futures = "0.3" http = "1.2.0" once_cell = "1.20.2" progenitor = "0.8.0" diff --git a/agent/Cargo.toml b/agent/Cargo.toml index 4edcf82..2305f9f 100644 --- a/agent/Cargo.toml +++ b/agent/Cargo.toml @@ -7,6 +7,7 @@ version.workspace = true [dependencies] anyhow.workspace = true clap.workspace = true +futures.workspace = true instrumentation = { path = "../instrumentation" } progenitor.workspace = true reqwest.workspace = true @@ -14,6 +15,7 @@ schemars.workspace = true serde.workspace = true tokio.workspace = true tracing.workspace = true +uuid.workspace = true [package.metadata.cargo-machete] ignored = ["reqwest", "serde"] diff --git a/api.json b/api.json index 9c88ea6..4ea6803 100644 --- a/api.json +++ b/api.json @@ -5,6 +5,96 @@ "version": "1.0.0" }, "paths": { + "/users": { + "get": { + "tags": [ + "user" + ], + "summary": "List users", + "operationId": "list_users", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + } + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retrieve the subsequent page", + "schema": { + "nullable": true, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": { + "required": [] + } + } + }, + "/users/{userId}": { + "get": { + "tags": [ + "user" + ], + "summary": "Fetch user info.", + "operationId": "get_user_by_id", + "parameters": [ + { + "in": "path", + "name": "userId", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, "/version": { "get": { "summary": "Fetch version info.", @@ -51,6 +141,44 @@ "request_id" ] }, + "User": { + "description": "User", + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "UserResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, "VersionInfo": { "description": "Version and build information", "type": "object", @@ -80,5 +208,10 @@ } } } - } + }, + "tags": [ + { + "name": "user" + } + ] } diff --git a/controller/.sqlx/query-40dee0d539971f95bb3dc2ba4c49d5910bfdb2a6c9b82ddb296854973369594c.json b/controller/.sqlx/query-40dee0d539971f95bb3dc2ba4c49d5910bfdb2a6c9b82ddb296854973369594c.json new file mode 100644 index 0000000..2c440e7 --- /dev/null +++ b/controller/.sqlx/query-40dee0d539971f95bb3dc2ba4c49d5910bfdb2a6c9b82ddb296854973369594c.json @@ -0,0 +1,47 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT * FROM users WHERE id > coalesce($1, '00000000-0000-0000-0000-000000000000'::UUID) ORDER BY id LIMIT $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "time_deleted", + "type_info": "Timestamptz" + }, + { + "ordinal": 3, + "name": "time_created", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "time_modified", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Int8" + ] + }, + "nullable": [ + false, + false, + true, + false, + false + ] + }, + "hash": "40dee0d539971f95bb3dc2ba4c49d5910bfdb2a6c9b82ddb296854973369594c" +} diff --git a/controller/.sqlx/query-843923b9a0257cf80f1dff554e7dc8fdfc05f489328e8376513124dfb42996e3.json b/controller/.sqlx/query-843923b9a0257cf80f1dff554e7dc8fdfc05f489328e8376513124dfb42996e3.json new file mode 100644 index 0000000..043a176 --- /dev/null +++ b/controller/.sqlx/query-843923b9a0257cf80f1dff554e7dc8fdfc05f489328e8376513124dfb42996e3.json @@ -0,0 +1,46 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT * FROM users WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "time_deleted", + "type_info": "Timestamptz" + }, + { + "ordinal": 3, + "name": "time_created", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "time_modified", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + true, + false, + false + ] + }, + "hash": "843923b9a0257cf80f1dff554e7dc8fdfc05f489328e8376513124dfb42996e3" +} diff --git a/controller/Cargo.toml b/controller/Cargo.toml index baa4054..7157501 100644 --- a/controller/Cargo.toml +++ b/controller/Cargo.toml @@ -15,10 +15,14 @@ schemars.workspace = true serde.workspace = true slog-async.workspace = true slog.workspace = true +sqlx = { version = "0.8.3", default-features = false, features = [ + "macros", "migrate", "postgres", "runtime-tokio", "tls-rustls", "time", "uuid" + ] } tokio.workspace = true trace-request = { path = "../trace-request" } tracing-slog.workspace = true tracing.workspace = true +uuid.workspace = true [package.metadata.cargo-machete] ignored = ["http"] diff --git a/controller/build.rs b/controller/build.rs new file mode 100644 index 0000000..d506869 --- /dev/null +++ b/controller/build.rs @@ -0,0 +1,5 @@ +// generated by `sqlx migrate build-script` +fn main() { + // trigger recompilation when a new migration is added + println!("cargo:rerun-if-changed=migrations"); +} diff --git a/controller/migrations/20250108132540_users.sql b/controller/migrations/20250108132540_users.sql new file mode 100644 index 0000000..f6e7e8d --- /dev/null +++ b/controller/migrations/20250108132540_users.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS patagia.public.Users( + id UUID PRIMARY KEY, + name VARCHAR(63) NOT NULL, + time_deleted TIMESTAMP WITH TIME ZONE, -- non-NULL if deleted + time_created TIMESTAMP WITH TIME ZONE NOT NULL, + time_modified TIMESTAMP WITH TIME ZONE NOT NULL +); diff --git a/controller/src/api.rs b/controller/src/api.rs index 1906567..5be86ce 100644 --- a/controller/src/api.rs +++ b/controller/src/api.rs @@ -4,12 +4,14 @@ use dropshot::ApiDescription; use std::sync::Arc; use crate::context::ControllerContext; +use crate::user; use crate::version; type ControllerApiDescription = ApiDescription<Arc<ControllerContext>>; pub fn api() -> Result<ControllerApiDescription> { let mut api = ControllerApiDescription::new(); + user::register_api(&mut api)?; api.register(version::version)?; Ok(api) } diff --git a/controller/src/bin/patagia-controller.rs b/controller/src/bin/patagia-controller.rs index 845cfd6..a73f4a7 100644 --- a/controller/src/bin/patagia-controller.rs +++ b/controller/src/bin/patagia-controller.rs @@ -1,8 +1,8 @@ use anyhow::{anyhow, Result}; use clap::Parser; use dropshot::{ConfigDropshot, ServerBuilder}; - use slog::Drain; +use sqlx::postgres::PgPool; use tracing_slog::TracingSlogDrain; use std::net::SocketAddr; @@ -36,6 +36,13 @@ struct Cli { env = "LISTEN_ADDRESS" )] listen_address: String, + + #[arg( + long = "database-url", + default_value = "postgresql://localhost/patagia", + env = "DATABASE_URL" + )] + database_url: Option<String>, } #[tokio::main] @@ -57,7 +64,19 @@ async fn main() -> Result<()> { slog::Logger::root(async_drain, slog::o!()) }; - let ctx = ControllerContext::new(); + let database_url = args.database_url.unwrap(); + + tracing::info!( + database_url, + listen_address = args.listen_address, + "Starting server" + ); + + let pg = PgPool::connect(&database_url).await?; + + sqlx::migrate!().run(&pg).await?; + + let ctx = ControllerContext::new(pg); let api = api::api()?; ServerBuilder::new(api, Arc::new(ctx), logger) .config(config) diff --git a/controller/src/context.rs b/controller/src/context.rs index d994d44..b99d559 100644 --- a/controller/src/context.rs +++ b/controller/src/context.rs @@ -1,13 +1,11 @@ -pub struct ControllerContext {} +use sqlx::postgres::PgPool; + +pub struct ControllerContext { + pub pg_pool: PgPool, +} impl ControllerContext { - pub fn new() -> ControllerContext { - ControllerContext {} - } -} - -impl Default for ControllerContext { - fn default() -> Self { - Self::new() + pub fn new(pg_pool: PgPool) -> ControllerContext { + ControllerContext { pg_pool } } } diff --git a/controller/src/lib.rs b/controller/src/lib.rs index 0caaf72..2d12df1 100644 --- a/controller/src/lib.rs +++ b/controller/src/lib.rs @@ -1,4 +1,5 @@ pub mod api; pub mod context; +mod user; mod version; diff --git a/controller/src/user/api.rs b/controller/src/user/api.rs new file mode 100644 index 0000000..c9b82e1 --- /dev/null +++ b/controller/src/user/api.rs @@ -0,0 +1,110 @@ +use dropshot::{ + endpoint, EmptyScanParams, HttpError, HttpResponseOk, PaginationParams, Path, Query, + RequestContext, ResultsPage, WhichPage, +}; +use dropshot::{ApiDescription, ApiDescriptionRegisterError}; +use schemars::JsonSchema; +use serde::Deserialize; +use serde::Serialize; +use trace_request::trace_request; +use uuid::Uuid; + +use std::sync::Arc; + +use super::User; +use crate::context::ControllerContext; + +#[derive(Deserialize, JsonSchema, Serialize)] +#[serde(rename_all = "camelCase")] +struct UsersPathParams { + user_id: Uuid, +} + +#[derive(Deserialize, JsonSchema, Serialize)] +#[serde(rename_all = "camelCase")] +struct UserPage { + user_id: Uuid, +} + +pub fn register_api( + api: &mut ApiDescription<Arc<ControllerContext>>, +) -> Result<(), ApiDescriptionRegisterError> { + api.register(get_user_by_id)?; + api.register(list_users) +} + +/// Fetch user info. +#[endpoint { + method = GET, + path = "/users/{userId}", + tags = [ "user" ], +}] +#[trace_request] +async fn get_user_by_id( + rqctx: RequestContext<Arc<ControllerContext>>, + params: Path<UsersPathParams>, +) -> Result<HttpResponseOk<User>, HttpError> { + let id = params.into_inner().user_id; + tracing::debug!(id = id.to_string(), "Getting user by id"); + + let pg = rqctx.context().pg_pool.to_owned(); + + let rec = sqlx::query!(r#"SELECT * FROM users WHERE id = $1"#, id) + .fetch_one(&pg) + .await + .map_err(|e| match e { + sqlx::Error::RowNotFound => { + HttpError::for_not_found(None, format!("User not found by id: {:?}", id)) + } + err => HttpError::for_internal_error(format!("Error: {}", err)), + })?; + + let user = User { + id: rec.id, + name: rec.name, + }; + + Ok(HttpResponseOk(user)) +} + +/// List users +#[endpoint { + method = GET, + path = "/users", + tags = [ "user" ], +}] +#[trace_request] +async fn list_users( + rqctx: RequestContext<Arc<ControllerContext>>, + query: Query<PaginationParams<EmptyScanParams, UserPage>>, +) -> Result<HttpResponseOk<ResultsPage<User>>, HttpError> { + let pag_params = query.into_inner(); + let limit = rqctx.page_limit(&pag_params)?.get() as i64; + let pg = rqctx.context().pg_pool.to_owned(); + + let last_seen = match &pag_params.page { + WhichPage::Next(UserPage { user_id: id }) => Some(id), + _ => None, + }; + + let users = sqlx::query!( + r#"SELECT * FROM users WHERE id > coalesce($1, '00000000-0000-0000-0000-000000000000'::UUID) ORDER BY id LIMIT $2"#, + last_seen, + limit + ) + .fetch_all(&pg) + .await + .map_err(|e| HttpError::for_internal_error(format!("Error: {}", e)))? + .into_iter() + .map(|rec| User { + id: rec.id, + name: rec.name, + }) + .collect(); + + Ok(HttpResponseOk(ResultsPage::new( + users, + &EmptyScanParams {}, + |u: &User, _| UserPage { user_id: u.id }, + )?)) +} diff --git a/controller/src/user/mod.rs b/controller/src/user/mod.rs new file mode 100644 index 0000000..46397e9 --- /dev/null +++ b/controller/src/user/mod.rs @@ -0,0 +1,14 @@ +use schemars::JsonSchema; +use serde::Serialize; +use uuid::Uuid; + +mod api; + +pub use self::api::register_api; + +/// User +#[derive(Serialize, JsonSchema)] +struct User { + id: Uuid, + name: String, +} diff --git a/flake.nix b/flake.nix index 4b22c31..ac97f6e 100644 --- a/flake.nix +++ b/flake.nix @@ -49,6 +49,8 @@ root = ./.; fileset = pkgs.lib.fileset.unions [ ./api.json + ./controller/.sqlx + ./controller/migrations (craneLib.fileset.commonCargoSources ./.) ]; }; @@ -116,6 +118,7 @@ formatter = (treefmt-nix.lib.evalModule pkgs { projectRootFile = "flake.nix"; + programs = { nixfmt.enable = true; nixfmt.package = pkgs.nixfmt-rfc-style; @@ -141,6 +144,8 @@ just nixfmt-rfc-style rust-dev-toolchain + sqls + sqlx-cli watchexec ] ++ commonArgs.buildInputs; diff --git a/justfile b/justfile index f7b69d7..a953f53 100644 --- a/justfile +++ b/justfile @@ -5,11 +5,13 @@ default: @just --choose # Run controller +[group('controller')] run-controller $RUST_LOG="debug,h2=info,hyper_util=info,tower=info": cargo run --package patagia-controller -- --log-stderr # Run controller local development -dev-controller: +[group('controller')] +dev-controller: dev-controller-db-migrate watchexec --clear --restart --stop-signal INT --debounce 300ms -- just run-controller # Run agent @@ -48,6 +50,10 @@ machete: open-api: cargo xtask open-api +# Update OpenAPI spec +gen-open-api: + cargo xtask open-api > api.json + # Run all tests check: check-nix @@ -56,7 +62,12 @@ check-nix: nix flake check # Run PostgreSQL for development and testing +[group('controller')] dev-postgres: + #!/usr/bin/env sh + if podman ps --filter "name=patagia-postgres" --filter "status=running" -q | grep -q .; then + exit 0 + fi mkdir -p "${XDG_RUNTIME_DIR}/patagia-postgres" podman volume exists patagia-postgres || podman volume create patagia-postgres podman run \ @@ -69,12 +80,33 @@ dev-postgres: --volume patagia-postgres:/var/lib/postgresql/data \ --volume "${XDG_RUNTIME_DIR}/patagia-postgres:/var/run/postgresql" \ docker.io/postgres:17 + sleep 0.3 # Clean up PostgreSQL data +[group('controller')] dev-postgres-clean: podman rm -f patagia-postgres || true podman volume rm patagia-postgres || true # Connect to PostgreSQL with psql +[group('controller')] dev-postgres-psql: podman exec -it patagia-postgres psql -U patagia + +[group('controller')] +[working-directory: 'controller'] +dev-controller-db-migrate: dev-postgres + cargo sqlx migrate run + +[group('controller')] +[working-directory: 'controller'] +dev-controller-db-reset: + cargo sqlx db reset -y + +[group('controller')] +[working-directory: 'controller'] +gen-controller-sqlx-prepare: + cargo sqlx prepare + +gen: gen-open-api gen-controller-sqlx-prepare fmt + From d7f4d877b65ea9cac1d032aad960abd48a2d888f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Sj=C3=B6strom?= <lars@radicore.se> Date: Wed, 8 Jan 2025 11:09:34 +0100 Subject: [PATCH 3/3] feat(hostd): varlink interfaced host controller to manage machine configuration and boot mgmt --- Cargo.lock | 255 +++++++++++++++++----- Cargo.toml | 1 + hostd/.gitignore | 1 + hostd/Cargo.toml | 12 ++ hostd/build.rs | 6 + hostd/src/io.patagia.Hostd.varlink | 27 +++ hostd/src/io.systemd.Hostname.varlink | 32 +++ hostd/src/io_patagia_Hostd.rs | 264 +++++++++++++++++++++++ hostd/src/io_systemd_Hostname.rs | 295 ++++++++++++++++++++++++++ hostd/src/main.rs | 3 + 10 files changed, 846 insertions(+), 50 deletions(-) create mode 100644 hostd/.gitignore create mode 100644 hostd/Cargo.toml create mode 100644 hostd/build.rs create mode 100644 hostd/src/io.patagia.Hostd.varlink create mode 100644 hostd/src/io.systemd.Hostname.varlink create mode 100644 hostd/src/io_patagia_Hostd.rs create mode 100644 hostd/src/io_systemd_Hostname.rs create mode 100644 hostd/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 67b0d67..b9cefe0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", "version_check", "zerocopy", @@ -59,6 +59,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anstream" version = "0.6.18" @@ -133,7 +142,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -144,7 +153,7 @@ checksum = "1b1244b10dcd56c92219da4e14caa97e312079e185f04ba3eea25061561dc0a0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -222,7 +231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -298,6 +307,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -310,6 +325,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chainerror" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce1bb7fb0c258a6600d699950da347a7a9dad66c3ce815769b5f11cf8fce78e" + [[package]] name = "chrono" version = "0.4.39" @@ -355,7 +376,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -441,7 +462,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -522,7 +543,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "dirs-sys-next", ] @@ -545,7 +566,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -616,7 +637,7 @@ dependencies = [ "semver", "serde", "serde_tokenstream", - "syn", + "syn 2.0.95", ] [[package]] @@ -640,7 +661,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -665,7 +686,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "home", "windows-sys 0.48.0", ] @@ -811,7 +832,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -854,13 +875,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "libc", "wasi", @@ -979,6 +1009,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "hostd" +version = "0.2.0" +dependencies = [ + "anyhow", + "tokio", + "varlink", + "varlink_generator", +] + [[package]] name = "hostname" version = "0.3.1" @@ -996,7 +1036,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "windows", ] @@ -1272,7 +1312,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -1488,7 +1528,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "digest", ] @@ -1498,6 +1538,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[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" @@ -1663,7 +1712,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags", - "cfg-if", + "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", @@ -1679,7 +1728,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -1825,7 +1874,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -1876,6 +1925,33 @@ dependencies = [ "uuid", ] +[[package]] +name = "peg" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f76678828272f177ac33b7e2ac2e3e73cc6c1cd1e3e387928aa69562fa51367" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "636d60acf97633e48d266d7415a9355d4389cea327a193f87df395d88cd2b14d" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555b1514d2d99d78150d3c799d4c357a3e2c2a8062cd108e93a06d9057629c5" + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -1908,7 +1984,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -2016,7 +2092,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "syn", + "syn 2.0.95", "thiserror 1.0.69", "typify", "unicode-ident", @@ -2037,7 +2113,7 @@ dependencies = [ "serde_json", "serde_tokenstream", "serde_yaml", - "syn", + "syn 2.0.95", ] [[package]] @@ -2060,7 +2136,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -2286,7 +2362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.0", "getrandom", "libc", "spin", @@ -2453,7 +2529,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 2.0.95", ] [[package]] @@ -2524,7 +2600,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -2535,7 +2611,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -2578,7 +2654,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn", + "syn 2.0.95", ] [[package]] @@ -2612,7 +2688,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -2623,7 +2699,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -2825,7 +2901,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn", + "syn 2.0.95", ] [[package]] @@ -2848,7 +2924,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn", + "syn 2.0.95", "tempfile", "tokio", "url", @@ -2991,6 +3067,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.95" @@ -3019,7 +3106,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -3055,7 +3142,7 @@ version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "getrandom", "once_cell", @@ -3110,7 +3197,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -3121,7 +3208,7 @@ checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -3130,7 +3217,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -3218,7 +3305,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -3400,7 +3487,7 @@ dependencies = [ "http", "proc-macro2", "quote", - "syn", + "syn 2.0.95", "tracing", ] @@ -3424,7 +3511,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -3528,7 +3615,7 @@ dependencies = [ "semver", "serde", "serde_json", - "syn", + "syn 2.0.95", "thiserror 1.0.69", "unicode-ident", ] @@ -3546,10 +3633,21 @@ dependencies = [ "serde", "serde_json", "serde_tokenstream", - "syn", + "syn 2.0.95", "typify-impl", ] +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + [[package]] name = "unicode-bidi" version = "0.3.18" @@ -3577,6 +3675,22 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unix_socket" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aa2700417c405c38f5e6902d699345241c28c0b7ade4abaad71e35a87eb1564" +dependencies = [ + "cfg-if 0.1.10", + "libc", +] + [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -3634,6 +3748,47 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "varlink" +version = "11.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "409e275987d74665c23610c0959c133360cafd761c1a6ddb1ca6d0685c8cef5d" +dependencies = [ + "libc", + "serde", + "serde_derive", + "serde_json", + "tempfile", + "uds_windows", + "unix_socket", + "winapi", +] + +[[package]] +name = "varlink_generator" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8ff746c5b65d4bfb3a50f630b85cfb6a9d59f18720126e3ebd6bc98527fa51" +dependencies = [ + "chainerror", + "getopts", + "proc-macro2", + "quote", + "syn 1.0.109", + "varlink_parser", +] + +[[package]] +name = "varlink_parser" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb9f3c1e8ccb33cdb6c84a4477ef3f3884ce6f4b70514ef1fbf7686eae921e" +dependencies = [ + "ansi_term", + "chainerror", + "peg", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -3682,7 +3837,7 @@ version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", "wasm-bindgen-macro", ] @@ -3697,7 +3852,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.95", "wasm-bindgen-shared", ] @@ -3707,7 +3862,7 @@ version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "once_cell", "wasm-bindgen", @@ -3732,7 +3887,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4065,7 +4220,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", "synstructure", ] @@ -4087,7 +4242,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] @@ -4107,7 +4262,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", "synstructure", ] @@ -4136,7 +4291,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.95", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ca5b5c1..653c291 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "agent", "controller", "instrumentation", + "hostd", "trace-request", "xtask", ] diff --git a/hostd/.gitignore b/hostd/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/hostd/.gitignore @@ -0,0 +1 @@ +/target diff --git a/hostd/Cargo.toml b/hostd/Cargo.toml new file mode 100644 index 0000000..f6d79cc --- /dev/null +++ b/hostd/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "hostd" +version.workspace = true +edition.workspace = true + +[dependencies] +anyhow.workspace = true +tokio.workspace = true +varlink = "11.0.1" + +[build-dependencies] +varlink_generator = "10.1.0" diff --git a/hostd/build.rs b/hostd/build.rs new file mode 100644 index 0000000..c12279a --- /dev/null +++ b/hostd/build.rs @@ -0,0 +1,6 @@ +extern crate varlink_generator; + +fn main() { + varlink_generator::cargo_build_tosource("src/io.systemd.Hostname.varlink", true); + varlink_generator::cargo_build_tosource("src/io.patagia.Hostd.varlink", true); +} diff --git a/hostd/src/io.patagia.Hostd.varlink b/hostd/src/io.patagia.Hostd.varlink new file mode 100644 index 0000000..46123a8 --- /dev/null +++ b/hostd/src/io.patagia.Hostd.varlink @@ -0,0 +1,27 @@ +interface io.patagia.Hostd + +type Label ( + key: string, + value: string +) + +type PatagiaAgentConfig ( + url: string, + extraMounts: [string]string +) + +type Machine( + machineId: string, + nodeLabels: ?[]Label, + patagiaAgent: ?PatagiaAgentConfig +) + +method Describe() -> ( + machine: Machine +) + +method Apply( + machine: Machine +) -> () + +error InvalidMachineConfig() diff --git a/hostd/src/io.systemd.Hostname.varlink b/hostd/src/io.systemd.Hostname.varlink new file mode 100644 index 0000000..be4cf01 --- /dev/null +++ b/hostd/src/io.systemd.Hostname.varlink @@ -0,0 +1,32 @@ +interface io.systemd.Hostname + +method Describe() -> ( + Hostname: string, + StaticHostname: ?string, + PrettyHostname: ?string, + DefaultHostname: ?string, + HostnameSource: string, + IconName: ?string, + Chassis: ?string, + Deployment: ?string, + Location: ?string, + KernelName: string, + KernelRelease: string, + KernelVersion: string, + OperatingSystemPrettyName: ?string, + OperatingSystemCPEName: ?string, + OperatingSystemHomeURL: ?string, + OperatingSystemSupportEnd: ?int, + OperatingSystemReleaseData: ?[]string, + MachineInformationData: ?[]string, + HardwareVendor: ?string, + HardwareModel: ?string, + HardwareSerial: ?string, + FirmwareVersion: ?string, + FirmwareVendor: ?string, + FirmwareDate: ?int, + MachineID: string, + BootID: string, + ProductUUID: ?string, + VSockCID: ?int +) diff --git a/hostd/src/io_patagia_Hostd.rs b/hostd/src/io_patagia_Hostd.rs new file mode 100644 index 0000000..a2de13d --- /dev/null +++ b/hostd/src/io_patagia_Hostd.rs @@ -0,0 +1,264 @@ +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + InvalidMachineConfig(Option<InvalidMachineConfig_Args>), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::InvalidMachineConfig(v) => { + write!(f, "io.patagia.Hostd.InvalidMachineConfig: {:#?}", v) + } + } + } +} +pub struct Error( + pub ErrorKind, + pub Option<Box<dyn std::error::Error + 'static + Send + Sync>>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From<ErrorKind> for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result<T> = std::result::Result<T, Error>; +impl From<varlink::Error> for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::<varlink::Error>()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { + error: Some(ref t), .. + } if t == "io.patagia.Hostd.InvalidMachineConfig" => match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::InvalidMachineConfig(v), + Err(_) => ErrorKind::InvalidMachineConfig(None), + }, + _ => ErrorKind::InvalidMachineConfig(None), + }, + _ => ErrorKind::VarlinkReply_Error, + } + } +} +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_invalid_machine_config(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "io.patagia.Hostd.InvalidMachineConfig", + None, + )) + } +} +impl<'a> VarlinkCallError for varlink::Call<'a> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#Label { + pub r#key: String, + pub r#value: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#Machine { + pub r#machineId: String, + pub r#nodeLabels: Option<Vec<Label>>, + pub r#patagiaAgent: Option<PatagiaAgentConfig>, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#PatagiaAgentConfig { + pub r#url: String, + pub r#extraMounts: varlink::StringHashMap<String>, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct InvalidMachineConfig_Args {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Apply_Reply {} +impl varlink::VarlinkReply for Apply_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Apply_Args { + pub r#machine: Machine, +} +pub trait Call_Apply: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl<'a> Call_Apply for varlink::Call<'a> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Describe_Reply { + pub r#machine: Machine, +} +impl varlink::VarlinkReply for Describe_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Describe_Args {} +pub trait Call_Describe: VarlinkCallError { + fn reply(&mut self, r#machine: Machine) -> varlink::Result<()> { + self.reply_struct(Describe_Reply { r#machine }.into()) + } +} +impl<'a> Call_Describe for varlink::Call<'a> {} +pub trait VarlinkInterface { + fn apply(&self, call: &mut dyn Call_Apply, r#machine: Machine) -> varlink::Result<()>; + fn describe(&self, call: &mut dyn Call_Describe) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result<Vec<u8>> { + Ok(Vec::new()) + } +} +pub trait VarlinkClientInterface { + fn apply(&mut self, r#machine: Machine) -> varlink::MethodCall<Apply_Args, Apply_Reply, Error>; + fn describe(&mut self) -> varlink::MethodCall<Describe_Args, Describe_Reply, Error>; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc<RwLock<varlink::Connection>>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc<RwLock<varlink::Connection>>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn apply(&mut self, r#machine: Machine) -> varlink::MethodCall<Apply_Args, Apply_Reply, Error> { + varlink::MethodCall::<Apply_Args, Apply_Reply, Error>::new( + self.connection.clone(), + "io.patagia.Hostd.Apply", + Apply_Args { r#machine }, + ) + } + fn describe(&mut self) -> varlink::MethodCall<Describe_Args, Describe_Reply, Error> { + varlink::MethodCall::<Describe_Args, Describe_Reply, Error>::new( + self.connection.clone(), + "io.patagia.Hostd.Describe", + Describe_Args {}, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box<dyn VarlinkInterface + Send + Sync>, +} +#[allow(dead_code)] +pub fn new(inner: Box<dyn VarlinkInterface + Send + Sync>) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "interface io.patagia.Hostd\n\ntype Label (\n key: string,\n value: string\n)\n\ntype PatagiaAgentConfig (\n url: string,\n extraMounts: [string]string\n)\n\ntype Machine(\n machineId: string,\n nodeLabels: ?[]Label,\n patagiaAgent: ?PatagiaAgentConfig\n)\n\nmethod Describe() -> (\n machine: Machine\n)\n\nmethod Apply(\n machine: Machine\n) -> ()\n\nerror InvalidMachineConfig()\n" + } + fn get_name(&self) -> &'static str { + "io.patagia.Hostd" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result<Vec<u8>> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "io.patagia.Hostd.Apply" => { + if let Some(args) = req.parameters.clone() { + let args: Apply_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .apply(call as &mut dyn Call_Apply, args.r#machine) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "io.patagia.Hostd.Describe" => self.inner.describe(call as &mut dyn Call_Describe), + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/hostd/src/io_systemd_Hostname.rs b/hostd/src/io_systemd_Hostname.rs new file mode 100644 index 0000000..e9fa185 --- /dev/null +++ b/hostd/src/io_systemd_Hostname.rs @@ -0,0 +1,295 @@ +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + } + } +} +pub struct Error( + pub ErrorKind, + pub Option<Box<dyn std::error::Error + 'static + Send + Sync>>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From<ErrorKind> for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result<T> = std::result::Result<T, Error>; +impl From<varlink::Error> for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::<varlink::Error>()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + _ => ErrorKind::VarlinkReply_Error, + } + } +} +pub trait VarlinkCallError: varlink::CallTrait {} +impl<'a> VarlinkCallError for varlink::Call<'a> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Describe_Reply { + pub r#Hostname: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#StaticHostname: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#PrettyHostname: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#DefaultHostname: Option<String>, + pub r#HostnameSource: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#IconName: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#Chassis: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#Deployment: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#Location: Option<String>, + pub r#KernelName: String, + pub r#KernelRelease: String, + pub r#KernelVersion: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#OperatingSystemPrettyName: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#OperatingSystemCPEName: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#OperatingSystemHomeURL: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#OperatingSystemSupportEnd: Option<i64>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#OperatingSystemReleaseData: Option<Vec<String>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#MachineInformationData: Option<Vec<String>>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#HardwareVendor: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#HardwareModel: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#HardwareSerial: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#FirmwareVersion: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#FirmwareVendor: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#FirmwareDate: Option<i64>, + pub r#MachineID: String, + pub r#BootID: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#ProductUUID: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#VSockCID: Option<i64>, +} +impl varlink::VarlinkReply for Describe_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Describe_Args {} +pub trait Call_Describe: VarlinkCallError { + fn reply( + &mut self, + r#Hostname: String, + r#StaticHostname: Option<String>, + r#PrettyHostname: Option<String>, + r#DefaultHostname: Option<String>, + r#HostnameSource: String, + r#IconName: Option<String>, + r#Chassis: Option<String>, + r#Deployment: Option<String>, + r#Location: Option<String>, + r#KernelName: String, + r#KernelRelease: String, + r#KernelVersion: String, + r#OperatingSystemPrettyName: Option<String>, + r#OperatingSystemCPEName: Option<String>, + r#OperatingSystemHomeURL: Option<String>, + r#OperatingSystemSupportEnd: Option<i64>, + r#OperatingSystemReleaseData: Option<Vec<String>>, + r#MachineInformationData: Option<Vec<String>>, + r#HardwareVendor: Option<String>, + r#HardwareModel: Option<String>, + r#HardwareSerial: Option<String>, + r#FirmwareVersion: Option<String>, + r#FirmwareVendor: Option<String>, + r#FirmwareDate: Option<i64>, + r#MachineID: String, + r#BootID: String, + r#ProductUUID: Option<String>, + r#VSockCID: Option<i64>, + ) -> varlink::Result<()> { + self.reply_struct( + Describe_Reply { + r#Hostname, + r#StaticHostname, + r#PrettyHostname, + r#DefaultHostname, + r#HostnameSource, + r#IconName, + r#Chassis, + r#Deployment, + r#Location, + r#KernelName, + r#KernelRelease, + r#KernelVersion, + r#OperatingSystemPrettyName, + r#OperatingSystemCPEName, + r#OperatingSystemHomeURL, + r#OperatingSystemSupportEnd, + r#OperatingSystemReleaseData, + r#MachineInformationData, + r#HardwareVendor, + r#HardwareModel, + r#HardwareSerial, + r#FirmwareVersion, + r#FirmwareVendor, + r#FirmwareDate, + r#MachineID, + r#BootID, + r#ProductUUID, + r#VSockCID, + } + .into(), + ) + } +} +impl<'a> Call_Describe for varlink::Call<'a> {} +pub trait VarlinkInterface { + fn describe(&self, call: &mut dyn Call_Describe) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result<Vec<u8>> { + Ok(Vec::new()) + } +} +pub trait VarlinkClientInterface { + fn describe(&mut self) -> varlink::MethodCall<Describe_Args, Describe_Reply, Error>; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc<RwLock<varlink::Connection>>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc<RwLock<varlink::Connection>>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn describe(&mut self) -> varlink::MethodCall<Describe_Args, Describe_Reply, Error> { + varlink::MethodCall::<Describe_Args, Describe_Reply, Error>::new( + self.connection.clone(), + "io.systemd.Hostname.Describe", + Describe_Args {}, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box<dyn VarlinkInterface + Send + Sync>, +} +#[allow(dead_code)] +pub fn new(inner: Box<dyn VarlinkInterface + Send + Sync>) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "interface io.systemd.Hostname\n\nmethod Describe() -> (\n\tHostname: string,\n\tStaticHostname: ?string,\n\tPrettyHostname: ?string,\n\tDefaultHostname: ?string,\n\tHostnameSource: string,\n\tIconName: ?string,\n\tChassis: ?string,\n\tDeployment: ?string,\n\tLocation: ?string,\n\tKernelName: string,\n\tKernelRelease: string,\n\tKernelVersion: string,\n\tOperatingSystemPrettyName: ?string,\n\tOperatingSystemCPEName: ?string,\n\tOperatingSystemHomeURL: ?string,\n\tOperatingSystemSupportEnd: ?int,\n\tOperatingSystemReleaseData: ?[]string,\n\tMachineInformationData: ?[]string,\n\tHardwareVendor: ?string,\n\tHardwareModel: ?string,\n\tHardwareSerial: ?string,\n\tFirmwareVersion: ?string,\n\tFirmwareVendor: ?string,\n\tFirmwareDate: ?int,\n\tMachineID: string,\n\tBootID: string,\n\tProductUUID: ?string,\n\tVSockCID: ?int\n)\n" + } + fn get_name(&self) -> &'static str { + "io.systemd.Hostname" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result<Vec<u8>> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "io.systemd.Hostname.Describe" => self.inner.describe(call as &mut dyn Call_Describe), + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/hostd/src/main.rs b/hostd/src/main.rs new file mode 100644 index 0000000..47ad8c6 --- /dev/null +++ b/hostd/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World!"); +}