feat: track bundle (#90)

* feat: track bundle

* fix: remove apk arch
This commit is contained in:
LowderPlay
2026-08-29 04:23:19 +05:00
committed by GitHub
parent a12f2964ac
commit 7a89ee272f
9 changed files with 77 additions and 12 deletions
Generated
+2 -2
View File
@@ -2577,7 +2577,7 @@ dependencies = [
[[package]] [[package]]
name = "probe" name = "probe"
version = "0.6.0" version = "0.6.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@@ -4652,7 +4652,7 @@ dependencies = [
[[package]] [[package]]
name = "website" name = "website"
version = "1.3.0" version = "1.3.1"
dependencies = [ dependencies = [
"dotenvy", "dotenvy",
"env_logger", "env_logger",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "probe" name = "probe"
version = "0.6.0" version = "0.6.1"
edition = "2024" edition = "2024"
license-file = "../LICENSE" license-file = "../LICENSE"
description = "Dynamic network probe daemon for Cheburcheck" description = "Dynamic network probe daemon for Cheburcheck"
+6 -1
View File
@@ -76,7 +76,12 @@ detect_platform() {
if command_exists apk; then if command_exists apk; then
PLATFORM=openwrt-apk PLATFORM=openwrt-apk
PLATFORM_NAME='OpenWrt (apk)' PLATFORM_NAME='OpenWrt (apk)'
ARCH=$(apk --print-arch) if [ -s /etc/apk/arch ]; then
ARCH=$(head -n 1 /etc/apk/arch)
else
ARCH=$(sed -n 's/^DISTRIB_ARCH=//p' /etc/openwrt_release | tr -d "'\"" | head -n 1)
fi
[ -n "$ARCH" ] || fail "OpenWrt did not report its package architecture"
validate_openwrt_arch "$ARCH" validate_openwrt_arch "$ARCH"
elif command_exists opkg; then elif command_exists opkg; then
PLATFORM=openwrt-opkg PLATFORM=openwrt-opkg
+6
View File
@@ -78,6 +78,7 @@ struct Args {
probe_token: String, probe_token: String,
max_concurrent_tasks: usize, max_concurrent_tasks: usize,
traceroute_retries: u8, traceroute_retries: u8,
bundle_type: &'static str,
} }
impl Cli { impl Cli {
@@ -94,6 +95,7 @@ impl Cli {
.context("--probe-token or PROBE_TOKEN is required when running the probe")?, .context("--probe-token or PROBE_TOKEN is required when running the probe")?,
max_concurrent_tasks: self.max_concurrent_tasks, max_concurrent_tasks: self.max_concurrent_tasks,
traceroute_retries: self.traceroute_retries, traceroute_retries: self.traceroute_retries,
bundle_type: update::bundle_type().context("failed to detect probe bundle type")?,
}) })
} }
} }
@@ -127,6 +129,7 @@ async fn main() -> Result<()> {
online: false, online: false,
probe_id: &args.probe_id, probe_id: &args.probe_id,
version: env!("CARGO_PKG_VERSION"), version: env!("CARGO_PKG_VERSION"),
bundle_type: Some(args.bundle_type),
dpi_hop_v4: None, dpi_hop_v4: None,
dpi_hop_v6: None, dpi_hop_v6: None,
})?; })?;
@@ -456,6 +459,7 @@ async fn publish_status(
online, online,
probe_id: &args.probe_id, probe_id: &args.probe_id,
version: env!("CARGO_PKG_VERSION"), version: env!("CARGO_PKG_VERSION"),
bundle_type: Some(args.bundle_type),
dpi_hop_v4: dpi_hops.v4, dpi_hop_v4: dpi_hops.v4,
dpi_hop_v6: dpi_hops.v6, dpi_hop_v6: dpi_hops.v6,
})?; })?;
@@ -625,6 +629,7 @@ mod tests {
online: true, online: true,
probe_id: "probe-1", probe_id: "probe-1",
version: "1.0.0", version: "1.0.0",
bundle_type: Some("debian"),
dpi_hop_v4: Some(4), dpi_hop_v4: Some(4),
dpi_hop_v6: Some(6), dpi_hop_v6: Some(6),
}; };
@@ -632,6 +637,7 @@ mod tests {
assert_eq!(value["dpi_hop_v4"], 4); assert_eq!(value["dpi_hop_v4"], 4);
assert_eq!(value["dpi_hop_v6"], 6); assert_eq!(value["dpi_hop_v6"], 6);
assert_eq!(value["bundle_type"], "debian");
} }
#[test] #[test]
+49 -6
View File
@@ -33,6 +33,22 @@ enum PackageKind {
Windows, Windows,
} }
impl PackageKind {
const fn bundle_type(self) -> &'static str {
match self {
Self::Debian => "debian",
Self::Apk => "openwrt-apk",
Self::Opkg => "openwrt-opkg",
Self::Linux => "linux",
Self::Windows => "windows",
}
}
}
pub fn bundle_type() -> Result<&'static str> {
detect_platform().map(|(kind, _, _)| kind.bundle_type())
}
#[cfg(unix)] #[cfg(unix)]
struct UpdateLock { struct UpdateLock {
_file: File, _file: File,
@@ -191,14 +207,10 @@ fn detect_platform() -> Result<(PackageKind, String, bool)> {
} else if command_exists("apk") } else if command_exists("apk")
&& command_succeeds("apk", &["info", "--exists", "cheburprobe"])? && command_succeeds("apk", &["info", "--exists", "cheburprobe"])?
{ {
let architecture = output_text("apk", &["--print-arch"])?; let architecture = openwrt_apk_arch()?;
let luci_installed = let luci_installed =
command_succeeds("apk", &["info", "--exists", "luci-app-cheburprobe"])?; command_succeeds("apk", &["info", "--exists", "luci-app-cheburprobe"])?;
Ok(( Ok((PackageKind::Apk, architecture, luci_installed))
PackageKind::Apk,
architecture.trim().to_owned(),
luci_installed,
))
} else if command_exists("opkg") } else if command_exists("opkg")
&& output_text("opkg", &["list-installed", "cheburprobe"])? && output_text("opkg", &["list-installed", "cheburprobe"])?
.lines() .lines()
@@ -227,6 +239,28 @@ fn detect_platform() -> Result<(PackageKind, String, bool)> {
bail!("updates are not supported on this operating system") bail!("updates are not supported on this operating system")
} }
#[cfg(target_os = "linux")]
fn openwrt_apk_arch() -> Result<String> {
if let Ok(architecture) = std::fs::read_to_string("/etc/apk/arch") {
let architecture = architecture.trim();
if !architecture.is_empty() {
return Ok(architecture.to_owned());
}
}
let release = std::fs::read_to_string("/etc/openwrt_release")
.context("failed to read /etc/openwrt_release")?;
parse_openwrt_release_arch(&release).context("OpenWrt did not report DISTRIB_ARCH")
}
#[cfg(target_os = "linux")]
fn parse_openwrt_release_arch(release: &str) -> Option<String> {
release.lines().find_map(|line| {
line.strip_prefix("DISTRIB_ARCH=")
.map(|value| value.trim_matches(['\'', '"']).to_owned())
.filter(|value| !value.is_empty())
})
}
fn select_luci_asset<'a>( fn select_luci_asset<'a>(
assets: &'a [Asset], assets: &'a [Asset],
kind: PackageKind, kind: PackageKind,
@@ -463,6 +497,15 @@ mod tests {
); );
} }
#[cfg(target_os = "linux")]
#[test]
fn parses_full_openwrt_architecture() {
assert_eq!(
parse_openwrt_release_arch("DISTRIB_ID='OpenWrt'\nDISTRIB_ARCH='aarch64_cortex-a53'\n"),
Some("aarch64_cortex-a53".to_owned())
);
}
#[test] #[test]
fn selects_each_package_format() { fn selects_each_package_format() {
let assets = vec![ let assets = vec![
+2
View File
@@ -7,6 +7,8 @@ pub struct ProbeStatus<'a> {
pub probe_id: &'a str, pub probe_id: &'a str,
pub version: &'a str, pub version: &'a str,
#[serde(default)] #[serde(default)]
pub bundle_type: Option<&'a str>,
#[serde(default)]
pub dpi_hop_v4: Option<u8>, pub dpi_hop_v4: Option<u8>,
#[serde(default)] #[serde(default)]
pub dpi_hop_v6: Option<u8>, pub dpi_hop_v6: Option<u8>,
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "website" name = "website"
version = "1.3.0" version = "1.3.1"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
+5
View File
@@ -56,6 +56,7 @@ struct NodeStatus {
connected_at: Option<DateTime<Utc>>, connected_at: Option<DateTime<Utc>>,
online: bool, online: bool,
version: Option<String>, version: Option<String>,
bundle_type: Option<String>,
dpi_hop_v4: Option<u8>, dpi_hop_v4: Option<u8>,
dpi_hop_v6: Option<u8>, dpi_hop_v6: Option<u8>,
} }
@@ -107,6 +108,7 @@ fn build_node_statuses(
connected_at: probe.last_connected_at, connected_at: probe.last_connected_at,
online: status.is_some_and(|status| status.online), online: status.is_some_and(|status| status.online),
version: status.map(|status| status.version.clone()), version: status.map(|status| status.version.clone()),
bundle_type: status.and_then(|status| status.bundle_type.clone()),
dpi_hop_v4: status.and_then(|status| status.dpi_hop_v4), dpi_hop_v4: status.and_then(|status| status.dpi_hop_v4),
dpi_hop_v6: status.and_then(|status| status.dpi_hop_v6), dpi_hop_v6: status.and_then(|status| status.dpi_hop_v6),
} }
@@ -152,6 +154,7 @@ mod tests {
ProbeStatusSnapshot { ProbeStatusSnapshot {
online: true, online: true,
version: "1.2.3".to_string(), version: "1.2.3".to_string(),
bundle_type: Some("debian".to_string()),
dpi_hop_v4: Some(5), dpi_hop_v4: Some(5),
dpi_hop_v6: None, dpi_hop_v6: None,
}, },
@@ -171,6 +174,7 @@ mod tests {
connected_at: Some("2026-08-24T12:34:56Z".parse().unwrap()), connected_at: Some("2026-08-24T12:34:56Z".parse().unwrap()),
online: true, online: true,
version: Some("1.2.3".to_string()), version: Some("1.2.3".to_string()),
bundle_type: Some("debian".to_string()),
dpi_hop_v4: Some(5), dpi_hop_v4: Some(5),
dpi_hop_v6: None, dpi_hop_v6: None,
}, },
@@ -183,6 +187,7 @@ mod tests {
connected_at: Some("2026-08-23T12:34:56Z".parse().unwrap()), connected_at: Some("2026-08-23T12:34:56Z".parse().unwrap()),
online: false, online: false,
version: None, version: None,
bundle_type: None,
dpi_hop_v4: None, dpi_hop_v4: None,
dpi_hop_v6: None, dpi_hop_v6: None,
}, },
+5 -1
View File
@@ -66,6 +66,7 @@ type ProbeStatuses = Arc<rocket::tokio::sync::RwLock<HashMap<String, ProbeStatus
pub struct ProbeStatusSnapshot { pub struct ProbeStatusSnapshot {
pub online: bool, pub online: bool,
pub version: String, pub version: String,
pub bundle_type: Option<String>,
pub dpi_hop_v4: Option<u8>, pub dpi_hop_v4: Option<u8>,
pub dpi_hop_v6: Option<u8>, pub dpi_hop_v6: Option<u8>,
} }
@@ -377,6 +378,7 @@ async fn dispatch_probe_status(probe_statuses: &ProbeStatuses, topic: &str, payl
ProbeStatusSnapshot { ProbeStatusSnapshot {
online: status.online, online: status.online,
version: status.version.to_string(), version: status.version.to_string(),
bundle_type: status.bundle_type.map(str::to_string),
dpi_hop_v4: status.dpi_hop_v4, dpi_hop_v4: status.dpi_hop_v4,
dpi_hop_v6: status.dpi_hop_v6, dpi_hop_v6: status.dpi_hop_v6,
}, },
@@ -462,7 +464,7 @@ mod tests {
dispatch_probe_status( dispatch_probe_status(
&statuses, &statuses,
"probe/status/v1/42", "probe/status/v1/42",
br#"{"online":false,"probe_id":"42","version":"1.2.3","dpi_hop_v4":4,"dpi_hop_v6":6}"#, br#"{"online":false,"probe_id":"42","version":"1.2.3","bundle_type":"openwrt","dpi_hop_v4":4,"dpi_hop_v6":6}"#,
) )
.await; .await;
@@ -471,6 +473,7 @@ mod tests {
Some(&ProbeStatusSnapshot { Some(&ProbeStatusSnapshot {
online: false, online: false,
version: "1.2.3".to_string(), version: "1.2.3".to_string(),
bundle_type: Some("openwrt".to_string()),
dpi_hop_v4: Some(4), dpi_hop_v4: Some(4),
dpi_hop_v6: Some(6), dpi_hop_v6: Some(6),
}) })
@@ -484,6 +487,7 @@ mod tests {
ProbeStatusSnapshot { ProbeStatusSnapshot {
online: true, online: true,
version: "1.2.3".to_string(), version: "1.2.3".to_string(),
bundle_type: None,
dpi_hop_v4: None, dpi_hop_v4: None,
dpi_hop_v6: None, dpi_hop_v6: None,
}, },