diff --git a/Cargo.lock b/Cargo.lock index e2d7e26..8885015 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,6 +103,132 @@ version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "tracing", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -125,6 +251,12 @@ dependencies = [ "syn", ] +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.85" @@ -249,6 +381,19 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -632,6 +777,33 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -670,6 +842,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -792,6 +974,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-lite" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.31" @@ -958,6 +1153,27 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "hostd" +version = "0.2.0" +dependencies = [ + "anyhow", + "clap", + "dropshot", + "http", + "schemars", + "serde", + "slog", + "slog-async", + "sqlx", + "tokio", + "trace-request", + "tracing", + "tracing-slog", + "zbus", + "zbus_systemd", +] + [[package]] name = "hostname" version = "0.3.1" @@ -1477,6 +1693,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" @@ -1537,6 +1762,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1776,6 +2014,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "overload" version = "0.1.1" @@ -1902,6 +2150,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkcs1" version = "0.7.5" @@ -1929,6 +2188,21 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "polling" +version = "3.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -1944,6 +2218,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.93" @@ -2519,9 +2802,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.135" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", @@ -2539,6 +2822,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_spanned" version = "0.6.8" @@ -2947,6 +3241,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "stringprep" version = "0.1.5" @@ -2972,9 +3272,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.96" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", @@ -3286,7 +3586,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.24", ] [[package]] @@ -3529,6 +3829,17 @@ dependencies = [ "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" @@ -4006,6 +4317,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" +dependencies = [ + "memchr", +] + [[package]] name = "write16" version = "1.0.0" @@ -4018,6 +4338,16 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "xtask" version = "0.2.0" @@ -4052,6 +4382,80 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbddd8b6cb25d5d8ec1b23277b45299a98bfb220f1761ca11e186d5c702507f8" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-util", + "hex", + "nix", + "ordered-stream", + "serde", + "serde_repr", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.59.0", + "winnow 0.7.1", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac404d48b4e9cf193c8b49589f3280ceca5ff63519e7e64f55b4cf9c47ce146" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +dependencies = [ + "serde", + "static_assertions", + "winnow 0.7.1", + "zvariant", +] + +[[package]] +name = "zbus_systemd" +version = "0.25701.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b772577120750e5a5ab5a5530f38fd462a35fafd9ed475098714afd1b1855ec" +dependencies = [ + "futures", + "serde", + "zbus", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -4149,3 +4553,45 @@ dependencies = [ "cc", "pkg-config", ] + +[[package]] +name = "zvariant" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c951c21879c6e1d46ac5adfc34f698fefb465d498cf4ac87545849bd71bb5a" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "winnow 0.7.1", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eeb539471af098d9e63faf428c71ac4cd4efe0b5baa3c8a6b991c5f2543b70e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "static_assertions", + "syn", + "winnow 0.7.1", +] diff --git a/Cargo.toml b/Cargo.toml index d61baf6..5afc72d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "agent", "controller", "instrumentation", + "hostd", "trace-request", "xtask", ] @@ -44,7 +45,5 @@ slog = "2.7.0" slog-async = "2.8.0" tokio = { version = "1.43.0", features = ["full"] } tracing = "0.1.41" -tracing-core = "0.1.33" -tracing-chrome = "0.7.2" tracing-slog = { git = "https://github.com/oxidecomputer/tracing-slog", default-features = false } uuid = { version = "1", features = [ "serde", "v4" ] } 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..f3322c7 --- /dev/null +++ b/hostd/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "hostd" +version.workspace = true +edition.workspace = true + +[dependencies] +anyhow.workspace = true +tokio.workspace = true +sqlx = { version = "0.8.3", default-features = false, features = [ + "macros", "migrate", "postgres", "runtime-tokio", "tls-rustls", "time", "uuid" + ] } +dropshot.workspace = true +clap.workspace = true +slog.workspace = true +slog-async.workspace = true +tracing-slog.workspace = true +tracing.workspace = true +trace-request = { path = "../trace-request" } +schemars.workspace = true +serde.workspace = true +http.workspace = true +zbus_systemd = { version = "0.25701.0", features = ["hostname1", "sysupdate1", "network1", "portable1", "resolve1", "systemd1"] } +zbus = "5.4.0" diff --git a/hostd/src/api.rs b/hostd/src/api.rs new file mode 100644 index 0000000..7f68d70 --- /dev/null +++ b/hostd/src/api.rs @@ -0,0 +1,17 @@ +use anyhow::Result; +use dropshot::ApiDescription; + +use std::sync::Arc; + +use crate::context::ControllerContext; +use crate::machine; +use crate::sysupdate; + +type ControllerApiDescription = ApiDescription>; + +pub fn api() -> Result { + let mut api = ControllerApiDescription::new(); + api.register(machine::describe)?; + api.register(sysupdate::list_versions)?; + Ok(api) +} diff --git a/hostd/src/bin/hostd-controller.rs b/hostd/src/bin/hostd-controller.rs new file mode 100644 index 0000000..003671e --- /dev/null +++ b/hostd/src/bin/hostd-controller.rs @@ -0,0 +1,75 @@ +use anyhow::{anyhow, Result}; + +use clap::Parser; +use dropshot::{ConfigDropshot, ServerBuilder}; +use slog::Drain; +use std::net::SocketAddr; +use std::str::FromStr; +use std::sync::Arc; +use tracing_slog::TracingSlogDrain; + +use hostd::api; +use hostd::context::ControllerContext; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Cli { + #[arg( + long = "telemetry-otlp-endpoint", + default_value = "http://localhost:4317", + env = "OTEL_EXPORTER_OTLP_ENDPOINT" + )] + otlp_endpoint: Option, + + #[arg( + long = "log-stderr", + short = 'v', + default_value = "false", + env = "LOG_TO_STDERR" + )] + log_stderr: bool, + + #[arg( + long = "listen-address", + default_value = "127.0.0.1:9478", + env = "LISTEN_ADDRESS" + )] + listen_address: String, + + #[arg( + long = "database-url", + default_value = "postgresql://localhost/patagia", + env = "DATABASE_URL" + )] + database_url: Option, +} + +#[tokio::main] +async fn main() -> Result<()> { + let args = Cli::parse(); + + let config = ConfigDropshot { + bind_address: SocketAddr::from_str(&args.listen_address).unwrap(), + ..Default::default() + }; + + let logger = { + let level_drain = slog::LevelFilter(TracingSlogDrain, slog::Level::Debug).fuse(); + let async_drain = slog_async::Async::new(level_drain).build().fuse(); + slog::Logger::root(async_drain, slog::o!()) + }; + + let dbus = zbus::Connection::system().await.unwrap(); + let ctx = ControllerContext::new(dbus); + + let api = api::api()?; + + println!("Listening on http://{}", config.bind_address); + + ServerBuilder::new(api, Arc::new(ctx), logger) + .config(config) + .start() + .map_err(|e| anyhow!("Error starting server: {:?}", e))? + .await + .map_err(|e| anyhow!(e)) +} diff --git a/hostd/src/context.rs b/hostd/src/context.rs new file mode 100644 index 0000000..de20783 --- /dev/null +++ b/hostd/src/context.rs @@ -0,0 +1,9 @@ +pub struct ControllerContext { + pub dbus: zbus::Connection, +} + +impl ControllerContext { + pub fn new(dbus: zbus::Connection) -> ControllerContext { + ControllerContext { dbus } + } +} diff --git a/hostd/src/lib.rs b/hostd/src/lib.rs new file mode 100644 index 0000000..3b7a5eb --- /dev/null +++ b/hostd/src/lib.rs @@ -0,0 +1,4 @@ +pub mod api; +pub mod context; +pub mod machine; +pub mod sysupdate; diff --git a/hostd/src/machine.rs b/hostd/src/machine.rs new file mode 100644 index 0000000..a2926c2 --- /dev/null +++ b/hostd/src/machine.rs @@ -0,0 +1,43 @@ +use dropshot::{endpoint, HttpError, HttpResponseOk, RequestContext}; +use schemars::JsonSchema; +use serde::Serialize; +use std::sync::Arc; +use trace_request::trace_request; + +use crate::context::ControllerContext; + +/// Machine information +#[derive(Serialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +struct MachineInfo { + machine_id: String, +} + +/// Fetch machine info +#[endpoint { + method = GET, + path = "/machine_info", +}] +#[trace_request] +pub async fn describe( + rqctx: RequestContext>, +) -> Result, HttpError> { + let hostnamed = zbus_systemd::hostname1::HostnamedProxy::new(&rqctx.context().dbus) + .await + .unwrap(); + + let machine_id = hostnamed + .machine_id() + .await + .map_err(|e| match e { + err => HttpError::for_internal_error(format!("Error: {}", err)), + })? + // convert bytes to hex string + .iter() + .map(|&b| format!("{:02x}", b)) + .collect(); + + let machine_info = MachineInfo { machine_id }; + + Ok(HttpResponseOk(machine_info)) +} diff --git a/hostd/src/sysupdate.rs b/hostd/src/sysupdate.rs new file mode 100644 index 0000000..43873cd --- /dev/null +++ b/hostd/src/sysupdate.rs @@ -0,0 +1,52 @@ +use dropshot::{endpoint, HttpError, HttpResponseOk, RequestContext}; +use schemars::JsonSchema; +use serde::Serialize; +use std::sync::Arc; +use trace_request::trace_request; + +use crate::context::ControllerContext; + +const SYSUPDATE_HOST_PATH: &str = "/org/freedesktop/sysupdate1/target/host"; + +#[derive(Serialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +struct SysUpdate { + current_version: String, + versions: Vec, +} + +#[endpoint { + method = GET, + path = "/list_versions", +}] +#[trace_request] +pub async fn list_versions( + rqctx: RequestContext>, +) -> Result, HttpError> { + let sysupdate_target = zbus_systemd::sysupdate1::TargetProxy::builder(&rqctx.context().dbus) + .path(SYSUPDATE_HOST_PATH) + .unwrap() + .build() + .await + .map_err(|e| match e { + err => HttpError::for_internal_error(format!("Error: {}", err)), + })?; + + let versions = sysupdate_target.list(0).await.map_err(|e| match e { + err => { + println!("Error: {}", err); + HttpError::for_internal_error(format!("Error: {}", err)) + } + })?; + + let current_version = sysupdate_target.get_version().await.map_err(|e| match e { + err => HttpError::for_internal_error(format!("Error: {}", err)), + })?; + + let sysupdate = SysUpdate { + versions, + current_version, + }; + + Ok(HttpResponseOk(sysupdate)) +}