talos_api_rs/resources/
dmesg.rs1use crate::api::generated::machine::DmesgRequest as ProtoDmesgRequest;
8
9#[derive(Debug, Clone, Default)]
11pub struct DmesgRequest {
12 pub follow: bool,
14 pub tail: bool,
16}
17
18impl DmesgRequest {
19 #[must_use]
21 pub fn new() -> Self {
22 Self::default()
23 }
24
25 #[must_use]
27 pub fn follow() -> Self {
28 Self {
29 follow: true,
30 tail: false,
31 }
32 }
33
34 #[must_use]
36 pub fn tail() -> Self {
37 Self {
38 follow: false,
39 tail: true,
40 }
41 }
42
43 #[must_use]
45 pub fn builder() -> DmesgRequestBuilder {
46 DmesgRequestBuilder::default()
47 }
48}
49
50impl From<DmesgRequest> for ProtoDmesgRequest {
51 fn from(req: DmesgRequest) -> Self {
52 Self {
53 follow: req.follow,
54 tail: req.tail,
55 }
56 }
57}
58
59#[derive(Debug, Clone, Default)]
61pub struct DmesgRequestBuilder {
62 follow: bool,
63 tail: bool,
64}
65
66impl DmesgRequestBuilder {
67 #[must_use]
69 pub fn follow(mut self, follow: bool) -> Self {
70 self.follow = follow;
71 self
72 }
73
74 #[must_use]
76 pub fn tail(mut self, tail: bool) -> Self {
77 self.tail = tail;
78 self
79 }
80
81 #[must_use]
83 pub fn build(self) -> DmesgRequest {
84 DmesgRequest {
85 follow: self.follow,
86 tail: self.tail,
87 }
88 }
89}
90
91#[derive(Debug, Clone)]
93pub struct DmesgResponse {
94 data: Vec<u8>,
96 pub node: Option<String>,
98}
99
100impl DmesgResponse {
101 #[must_use]
103 pub fn new(data: Vec<u8>, node: Option<String>) -> Self {
104 Self { data, node }
105 }
106
107 #[must_use]
109 pub fn as_bytes(&self) -> &[u8] {
110 &self.data
111 }
112
113 pub fn as_str(&self) -> Result<&str, std::str::Utf8Error> {
115 std::str::from_utf8(&self.data)
116 }
117
118 #[must_use]
120 pub fn as_string_lossy(&self) -> std::borrow::Cow<'_, str> {
121 String::from_utf8_lossy(&self.data)
122 }
123
124 #[must_use]
126 pub fn len(&self) -> usize {
127 self.data.len()
128 }
129
130 #[must_use]
132 pub fn is_empty(&self) -> bool {
133 self.data.is_empty()
134 }
135
136 #[must_use]
138 pub fn lines(&self) -> Vec<&str> {
139 self.as_str()
140 .map(|s| s.lines().collect())
141 .unwrap_or_default()
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_dmesg_request_new() {
151 let req = DmesgRequest::new();
152 assert!(!req.follow);
153 assert!(!req.tail);
154 }
155
156 #[test]
157 fn test_dmesg_request_follow() {
158 let req = DmesgRequest::follow();
159 assert!(req.follow);
160 assert!(!req.tail);
161 }
162
163 #[test]
164 fn test_dmesg_request_tail() {
165 let req = DmesgRequest::tail();
166 assert!(!req.follow);
167 assert!(req.tail);
168 }
169
170 #[test]
171 fn test_dmesg_request_builder() {
172 let req = DmesgRequest::builder().follow(true).tail(true).build();
173 assert!(req.follow);
174 assert!(req.tail);
175 }
176
177 #[test]
178 fn test_proto_conversion() {
179 let req = DmesgRequest::builder().follow(true).tail(false).build();
180 let proto: ProtoDmesgRequest = req.into();
181 assert!(proto.follow);
182 assert!(!proto.tail);
183 }
184
185 #[test]
186 fn test_dmesg_response() {
187 let data = b"[ 0.000000] Linux version 5.15.0\n[ 0.000001] Command line: talos.platform=metal".to_vec();
188 let response = DmesgResponse::new(data.clone(), Some("node1".to_string()));
189
190 assert_eq!(response.len(), data.len());
191 assert!(!response.is_empty());
192 assert!(response.as_str().is_ok());
193 assert_eq!(response.lines().len(), 2);
194 assert!(response.lines()[0].contains("Linux version"));
195 }
196}