Skip to main content

kanade_shared/
subject.rs

1pub const COMMANDS_ALL: &str = "commands.all";
2
3pub fn commands_group(name: &str) -> String {
4    format!("commands.group.{name}")
5}
6
7pub fn commands_pc(pc_id: &str) -> String {
8    format!("commands.pc.{pc_id}")
9}
10
11// `commands_exec` (subject `commands.exec.<job_id>`) was removed in
12// v0.22.1. The STREAM_EXEC stream now catches the existing
13// `commands.{all,group.X,pc.Y}` subjects directly, so the dedicated
14// per-exec subject isn't needed any more. See
15// `kanade-agent::command_replay` for how reconnecting agents catch
16// up on missed messages.
17
18pub fn results(request_id: &str) -> String {
19    format!("results.{request_id}")
20}
21
22pub fn heartbeat(pc_id: &str) -> String {
23    format!("heartbeat.{pc_id}")
24}
25
26pub fn kill(job_id: &str) -> String {
27    format!("kill.{job_id}")
28}
29
30pub fn inventory(pc_id: &str, category: &str) -> String {
31    format!("inventory.{pc_id}.{category}")
32}
33
34pub const INVENTORY_HW: &str = "hw";
35pub const INVENTORY_SW: &str = "sw";
36pub const INVENTORY_NET: &str = "net";
37
38/// `logs.fetch.<pc_id>` — request/reply: operator (or backend) sends
39/// a `LogsRequest`; the addressed agent replies with the tail of its
40/// local log file. On-demand only, no stream.
41pub fn logs_fetch(pc_id: &str) -> String {
42    format!("logs.fetch.{pc_id}")
43}
44
45// v0.14: subject::inventory_request was retired alongside the
46// hardcoded inventory loop. On-demand collection now goes through
47// the normal exec path (`kanade exec configs/jobs/inventory-
48// hw.yaml`) — Command + ExecResult + the inventory-fact projector
49// give operators the same effect with no extra subject.
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn commands_all_constant() {
57        assert_eq!(COMMANDS_ALL, "commands.all");
58    }
59
60    #[test]
61    fn commands_group_formats_name() {
62        assert_eq!(commands_group("canary"), "commands.group.canary");
63        assert_eq!(commands_group("wave1"), "commands.group.wave1");
64    }
65
66    #[test]
67    fn commands_pc_formats_id() {
68        assert_eq!(commands_pc("minipc"), "commands.pc.minipc");
69        assert_eq!(commands_pc("PC1234"), "commands.pc.PC1234");
70    }
71
72    #[test]
73    fn results_formats_request_id() {
74        assert_eq!(results("req-1"), "results.req-1");
75    }
76
77    #[test]
78    fn heartbeat_formats_pc_id() {
79        assert_eq!(heartbeat("minipc"), "heartbeat.minipc");
80    }
81
82    #[test]
83    fn kill_formats_job_id() {
84        assert_eq!(kill("testjob1"), "kill.testjob1");
85    }
86
87    #[test]
88    fn logs_fetch_formats_pc_id() {
89        assert_eq!(logs_fetch("minipc"), "logs.fetch.minipc");
90    }
91
92    #[test]
93    fn inventory_formats_pc_id_and_category() {
94        assert_eq!(inventory("minipc", "hw"), "inventory.minipc.hw");
95        assert_eq!(inventory("minipc", INVENTORY_HW), "inventory.minipc.hw");
96        assert_eq!(inventory("minipc", INVENTORY_SW), "inventory.minipc.sw");
97        assert_eq!(inventory("minipc", INVENTORY_NET), "inventory.minipc.net");
98    }
99}