nomad_client_rs/extensions/
mod.rs1use serde::{Deserialize, Serialize};
2
3use crate::models::alloc_file_info::AllocFileInfo;
4use crate::models::event::{Event, EventPayload};
5use crate::models::{TaskEvent, TaskState};
6
7impl AllocFileInfo {
8 pub fn is_empty(&self) -> bool {
9 self.size.map_or(false, |value| value <= 1)
10 }
11}
12
13impl Event {
14 pub fn get_alloc_id(&self) -> Option<String> {
15 if let Some(payload) = &self.payload {
16 match payload {
17 EventPayload::Allocation(allocation) => {
18 allocation.job_id.as_ref().map(|job_id| job_id.to_string())
19 }
20 _ => None,
21 };
22 }
23
24 None
25 }
26}
27
28impl TaskState {
29 pub fn last_exit_code(&self) -> Option<i32> {
30 match &self.events {
31 Some(events) => {
32 for event in events.iter().rev() {
33 match event.exit_code() {
34 Some(exit_code) => return Some(exit_code),
35 None => continue,
36 }
37 }
38 }
39 None => return None,
40 }
41
42 None
43 }
44
45 pub fn first_exit_code(&self) -> Option<i32> {
46 match &self.events {
47 Some(events) => {
48 for event in events {
49 match event.exit_code() {
50 Some(exit_code) => return Some(exit_code),
51 None => continue,
52 }
53 }
54 }
55 None => return None,
56 }
57
58 None
59 }
60}
61
62#[derive(Clone, Debug, Default, Deserialize, Serialize)]
63pub enum TaskStates {
64 #[default]
65 None,
66 #[serde(rename = "pending")]
67 Pending,
68 #[serde(rename = "running")]
69 Running,
70 #[serde(rename = "dead")]
71 Dead,
72}
73
74impl TaskEvent {
75 pub fn exit_code(&self) -> Option<i32> {
76 if let Some(Ok(exit_code)) = self
77 .details
78 .as_ref()?
79 .get("exit_code")
80 .map(|s| s.parse::<i32>())
81 {
82 return Some(exit_code);
83 }
84 None
85 }
86
87 pub fn driver_message(&self) -> Option<String> {
88 self.details
89 .as_ref()?
90 .get("driver_message")
91 .map(|s| s.into())
92 }
93
94 pub fn restart_reason(&self) -> Option<String> {
95 self.details
96 .as_ref()?
97 .get("restart_reason")
98 .map(|s| s.into())
99 }
100
101 pub fn kill_reason(&self) -> Option<String> {
102 self.details.as_ref()?.get("kill_reason").map(|s| s.into())
103 }
104
105 pub fn has_error(&self) -> bool {
106 if let Some(details) = &self.details {
107 for key in error_keys() {
108 if details.contains_key(key) {
109 return true;
110 }
111 }
112 }
113
114 false
115 }
116
117 pub fn error(&self, error_key: &str) -> Option<String> {
118 self.details.as_ref()?.get(error_key).map(|s| s.into())
119 }
120
121 pub fn all_errors(&self) -> Option<Vec<(&str, String)>> {
122 let mut errors: Vec<(&str, String)> = Vec::new();
123
124 for key in error_keys() {
125 match self.details.as_ref()?.get(key) {
126 Some(error) => errors.push((key, error.into())),
127 None => continue,
128 }
129 }
130
131 if errors.is_empty() {
132 None
133 } else {
134 Some(errors)
135 }
136 }
137}
138
139pub fn error_keys() -> Vec<&'static str> {
140 vec![
141 "validation_error",
142 "kill_error",
143 "setup_error",
144 "driver_error",
145 "download_error",
146 "vault_renewal_error",
147 ]
148}