feat: use Alpine AOT images, static SQLite and Podman host metrics [CI]
ci/woodpecker/push/main-amd64-build Pipeline failed

This commit is contained in:
geruipu committed 2026-10-07 01:03:31 +08:00
1 parent 295aa1c5cb
commit 6985b0a9c4
37 files changed
+719 -309

No files matched your search

@@ -21,6 +21,7 @@ public sealed class HostSamplerTests
Assert.Equal((1000L, 5000L), HostSampler.ParseNetwork(Dev1));
Assert.Equal(3600L, HostSampler.ParseUptime("3600.55 7000.1\n"));
Assert.Null(HostSampler.ParseNetwork("nothing useful"));
Assert.Equal((1000L, 5000L), HostSampler.ParseNetwork(Dev1 + "podman0: 8888 1 0 0 0 0 0 0 9999 1 0 0 0 0 0 0\n"));
}
[Fact]
@@ -29,7 +30,7 @@ public sealed class HostSamplerTests
var time = new Microsoft.Extensions.Time.Testing.FakeTimeProvider();
string stat = Stat1;
string dev = Dev1;
var sampler = new HostSampler(time, path => path switch { "/proc/stat" => stat, "/proc/net/dev" => dev, "/proc/uptime" => "100.0 1.0", _ => null }, () => (1000, 250));
var sampler = new HostSampler(time, path => path switch { "/proc/stat" => stat, "/proc/net/dev" => dev, "/proc/uptime" => "100.0 1.0", _ => null }, () => (1000, 250), procRoot: "/proc", sysRoot: "/sys");
HostSnapshot first = sampler.Sample();
Assert.Null(first.CpuPercent); // 第一次没有基线
Assert.Null(first.NetRxBps);
@@ -45,6 +46,54 @@ public sealed class HostSamplerTests
Assert.Equal(2000, second.NetTxBps);
Assert.Equal(3000, second.NetRxTotal);
}
[Fact]
public void Sample_UsesMountedHostProcAndSys_InsteadOfContainerPaths()
{
var reads = new List<string>();
var sampler = new HostSampler(TimeProvider.System, path =>
{
reads.Add(path);
return path switch
{
"/host/proc/stat" => Stat1,
"/host/proc/meminfo" => "MemTotal: 8192 kB\nMemAvailable: 6144 kB\n",
"/host/proc/net/dev" => Dev1,
"/host/proc/uptime" => "3600.0 7000.0",
"/host/sys/class/net/eth0/speed" => "10000\n",
_ => throw new InvalidOperationException("unexpected container path: " + path),
};
}, () => (1000, 250), procRoot: "/host/proc", sysRoot: "/host/sys");
HostSnapshot snapshot = sampler.Sample();
Assert.Equal(8L * 1024 * 1024, snapshot.MemTotal);
Assert.Equal(1000, snapshot.NetRxTotal);
Assert.Equal(10000, snapshot.NetLinkMbps);
Assert.Equal(3600, snapshot.UptimeSeconds);
Assert.DoesNotContain(reads, path => path.StartsWith("/proc/", StringComparison.Ordinal));
Assert.DoesNotContain(reads, path => path.Contains("docker0", StringComparison.Ordinal) || path.Contains("/lo/", StringComparison.Ordinal));
}
[Theory]
[InlineData(null)]
[InlineData("-1")]
[InlineData("0")]
[InlineData("not supported")]
public void Sample_DoesNotInventLinkSpeedOrContainerDisk_WhenHostDataIsUnavailable(string? speed)
{
var sampler = new HostSampler(TimeProvider.System,
path => path.EndsWith("net/dev", StringComparison.Ordinal) ? Dev1 : path.EndsWith("/speed", StringComparison.Ordinal) ? speed : null,
procRoot: "/host/proc", sysRoot: "/host/sys", diskRoot: Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")));
HostSnapshot snapshot = sampler.Sample();
Assert.Null(snapshot.NetLinkMbps);
Assert.Null(snapshot.DiskTotal);
Assert.Null(snapshot.DiskUsed);
if (OperatingSystem.IsLinux())
{
Assert.Null(snapshot.UptimeSeconds);
}
}
}
[Collection("backend")]
@@ -61,6 +110,7 @@ public sealed class HostStatusTests
{
CpuPercent = cpu, MemUsed = 2L << 30, MemTotal = 8L << 30, DiskUsed = 10L << 30, DiskTotal = 40L << 30,
NetRxTotal = 600L << 30, NetTxTotal = 180L << 30, NetRxBps = 2500, NetTxBps = 4800, UptimeSeconds = 3_000_000,
NetLinkMbps = 1000,
};
[Fact]
@@ -81,6 +131,7 @@ public sealed class HostStatusTests
JsonNode item = list["items"]!.AsArray().Single(i => i!["agent_id"]!.GetValue<string>() == id)!;
Assert.False(item["stale"]!.GetValue<bool>());
Assert.Equal(40L << 30, item["host"]!["disk_total"]!.GetValue<long>());
Assert.Equal(1000, item["host"]!["net_link_mbps"]!.GetValue<long>());
// 展示页能拿到的只有汇总数字:整份响应里没有型号、主机名、地址之类的字段
string text = list.ToJsonString();