1use serde::{Deserialize, Serialize};
3use serde_json::{Map, Value, json};
4
5use super::{Fleet, FleetPage, Item};
6use crate::{Scope, http::Method, pagination::paginated, request::endpoint};
7
8#[derive(Clone, Debug, Deserialize, Serialize)]
9#[non_exhaustive]
10pub struct Agent {
11 pub id: String,
12 #[serde(default)]
13 pub policy_id: Option<String>,
14 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub policy_revision: Option<u64>,
18 #[serde(default)]
19 pub active: Option<bool>,
20 #[serde(default)]
21 pub status: Option<String>,
22 #[serde(default)]
23 pub local_metadata: Value,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub last_checkin: Option<String>,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub tags: Option<Vec<String>>,
28 #[serde(flatten)]
29 pub extra: Map<String, Value>,
30}
31
32#[derive(Clone, Debug, Serialize)]
34#[serde(untagged)]
35pub enum AgentSelection {
36 Ids(Vec<String>),
37 Query(String),
38}
39
40#[derive(Clone, Debug, Deserialize, Serialize)]
43#[serde(untagged)]
44#[non_exhaustive]
45pub enum BulkActionResult {
46 Action {
47 #[serde(rename = "actionId")]
48 action_id: String,
49 },
50 DryRun { count: u64 },
52}
53
54#[derive(Clone, Copy, Debug, Serialize)]
55#[non_exhaustive]
56pub enum DiagnosticMetric {
57 #[serde(rename = "CPU")]
58 Cpu,
59}
60
61impl<'a> Fleet<'a> {
62 pub fn find_agents(&self) -> FindAgents<'a> {
63 FindAgents(
64 self.0
65 .request(Method::GET, Scope::Space, &["api", "fleet", "agents"]),
66 )
67 }
68
69 pub fn get_agent(&self, id: &str) -> GetAgent<'a> {
70 GetAgent(
71 self.0
72 .request(Method::GET, Scope::Space, &["api", "fleet", "agents", id]),
73 )
74 }
75
76 pub fn agent_status(&self) -> AgentStatus<'a> {
78 AgentStatus(
79 self.0
80 .request(Method::GET, Scope::Space, &["api", "fleet", "agent_status"]),
81 )
82 }
83
84 pub fn reassign_agent(&self, id: &str, policy_id: &str) -> ReassignAgent<'a> {
85 ReassignAgent(
86 self.0
87 .request(
88 Method::POST,
89 Scope::Space,
90 &["api", "fleet", "agents", id, "reassign"],
91 )
92 .nonempty("policy_id", policy_id)
93 .field("policy_id", policy_id),
94 )
95 }
96
97 pub fn unenroll_agent(&self, id: &str) -> UnenrollAgent<'a> {
98 UnenrollAgent(
99 self.0
100 .request(
101 Method::POST,
102 Scope::Space,
103 &["api", "fleet", "agents", id, "unenroll"],
104 )
105 .json(&json!({})),
106 )
107 }
108
109 pub fn upgrade_agent(&self, id: &str, version: &str) -> UpgradeAgent<'a> {
112 UpgradeAgent(
113 self.0
114 .request(
115 Method::POST,
116 Scope::Space,
117 &["api", "fleet", "agents", id, "upgrade"],
118 )
119 .nonempty("version", version)
120 .field("version", version),
121 )
122 }
123
124 pub fn request_agent_diagnostics(&self, id: &str) -> RequestAgentDiagnostics<'a> {
127 RequestAgentDiagnostics(
128 self.0
129 .request(
130 Method::POST,
131 Scope::Space,
132 &["api", "fleet", "agents", id, "request_diagnostics"],
133 )
134 .json(&json!({})),
135 )
136 }
137
138 pub fn bulk_reassign_agents(
139 &self,
140 agents: AgentSelection,
141 policy_id: &str,
142 ) -> BulkReassignAgents<'a> {
143 BulkReassignAgents(
144 self.0
145 .request(
146 Method::POST,
147 Scope::Space,
148 &["api", "fleet", "agents", "bulk_reassign"],
149 )
150 .field("agents", agents)
151 .nonempty("policy_id", policy_id)
152 .field("policy_id", policy_id),
153 )
154 }
155
156 pub fn bulk_unenroll_agents(&self, agents: AgentSelection) -> BulkUnenrollAgents<'a> {
157 BulkUnenrollAgents(
158 self.0
159 .request(
160 Method::POST,
161 Scope::Space,
162 &["api", "fleet", "agents", "bulk_unenroll"],
163 )
164 .field("agents", agents),
165 )
166 }
167
168 pub fn bulk_update_agent_tags(&self, agents: AgentSelection) -> BulkUpdateAgentTags<'a> {
169 BulkUpdateAgentTags(
170 self.0
171 .request(
172 Method::POST,
173 Scope::Space,
174 &["api", "fleet", "agents", "bulk_update_agent_tags"],
175 )
176 .field("agents", agents),
177 )
178 }
179
180 pub fn bulk_upgrade_agents(
181 &self,
182 agents: AgentSelection,
183 version: &str,
184 ) -> BulkUpgradeAgents<'a> {
185 BulkUpgradeAgents(
186 self.0
187 .request(
188 Method::POST,
189 Scope::Space,
190 &["api", "fleet", "agents", "bulk_upgrade"],
191 )
192 .field("agents", agents)
193 .nonempty("version", version)
194 .field("version", version),
195 )
196 }
197
198 pub fn bulk_request_agent_diagnostics(
199 &self,
200 agents: AgentSelection,
201 ) -> BulkRequestAgentDiagnostics<'a> {
202 BulkRequestAgentDiagnostics(
203 self.0
204 .request(
205 Method::POST,
206 Scope::Space,
207 &["api", "fleet", "agents", "bulk_request_diagnostics"],
208 )
209 .field("agents", agents),
210 )
211 }
212}
213
214macro_rules! bulk_setters {
215 ($($name:ident),*) => {$(
216 impl $name<'_> {
217 pub fn dry_run(self, dry_run: bool) -> Self {
219 Self(self.0.field("dryRun", dry_run))
220 }
221
222 pub fn batch_size(self, size: u32) -> Self {
224 Self(self.0.field("batchSize", size))
225 }
226 }
227 )*};
228}
229
230macro_rules! include_inactive_setter {
231 ($($name:ident),*) => {$(
232 impl $name<'_> {
233 pub fn include_inactive(self, include: bool) -> Self {
235 Self(self.0.field("includeInactive", include))
236 }
237 }
238 )*};
239}
240
241macro_rules! upgrade_setters {
242 ($($name:ident),*) => {$(
243 impl $name<'_> {
244 pub fn force(self, force: bool) -> Self {
246 Self(self.0.field("force", force))
247 }
248
249 pub fn source_uri(self, uri: &str) -> Self {
251 Self(self.0.field("source_uri", uri))
252 }
253
254 pub fn skip_rate_limit_check(self, skip: bool) -> Self {
255 Self(self.0.field("skipRateLimitCheck", skip))
256 }
257 }
258 )*};
259}
260
261macro_rules! diagnostics_setters {
262 ($($name:ident),*) => {$(
263 impl $name<'_> {
264 pub fn additional_metrics(self, metrics: Vec<DiagnosticMetric>) -> Self {
265 Self(self.0.field("additional_metrics", metrics))
266 }
267 }
268 )*};
269}
270
271endpoint! {
272 FindAgents => FleetPage<Agent>
274}
275
276impl FindAgents<'_> {
277 pub fn show_inactive(self, show: bool) -> Self {
278 Self(self.0.param("showInactive", show))
279 }
280}
281
282endpoint! {
283 GetAgent => Item<Agent>
285}
286
287endpoint! {
288 AgentStatus => Value
290}
291
292impl AgentStatus<'_> {
293 pub fn policy_id(self, id: &str) -> Self {
294 Self(self.0.param("policyId", id))
295 }
296
297 pub fn kuery(self, kuery: &str) -> Self {
298 Self(self.0.param("kuery", kuery))
299 }
300}
301
302endpoint! {
303 ReassignAgent => Value
305}
306
307endpoint! {
308 UnenrollAgent => Value
310}
311
312impl UnenrollAgent<'_> {
313 pub fn force(self, force: bool) -> Self {
315 Self(self.0.field("force", force))
316 }
317
318 pub fn revoke(self, revoke: bool) -> Self {
320 Self(self.0.field("revoke", revoke))
321 }
322}
323
324endpoint! {
325 UpgradeAgent => Value
327}
328
329endpoint! {
330 RequestAgentDiagnostics => BulkActionResult
332}
333
334endpoint! {
335 BulkReassignAgents => BulkActionResult
337}
338
339endpoint! {
340 BulkUnenrollAgents => BulkActionResult
342}
343
344impl BulkUnenrollAgents<'_> {
345 pub fn force(self, force: bool) -> Self {
347 Self(self.0.field("force", force))
348 }
349
350 pub fn revoke(self, revoke: bool) -> Self {
352 Self(self.0.field("revoke", revoke))
353 }
354}
355
356endpoint! {
357 BulkUpdateAgentTags => BulkActionResult
359}
360
361impl BulkUpdateAgentTags<'_> {
362 pub fn add_tags<I: IntoIterator<Item = S>, S: Into<String>>(self, tags: I) -> Self {
363 let tags: Vec<String> = tags.into_iter().map(Into::into).collect();
364 Self(self.0.field("tagsToAdd", tags))
365 }
366
367 pub fn remove_tags<I: IntoIterator<Item = S>, S: Into<String>>(self, tags: I) -> Self {
368 let tags: Vec<String> = tags.into_iter().map(Into::into).collect();
369 Self(self.0.field("tagsToRemove", tags))
370 }
371}
372
373endpoint! {
374 BulkUpgradeAgents => BulkActionResult
376}
377
378impl BulkUpgradeAgents<'_> {
379 pub fn start_time(self, time: &str) -> Self {
381 Self(self.0.field("start_time", time))
382 }
383
384 pub fn rollout_duration_seconds(self, seconds: u64) -> Self {
386 Self(self.0.field("rollout_duration_seconds", seconds))
387 }
388}
389
390endpoint! {
391 BulkRequestAgentDiagnostics => BulkActionResult
393}
394
395page_setters!(FindAgents);
396sort_setters!(FindAgents);
397bulk_setters!(
398 BulkReassignAgents,
399 BulkUnenrollAgents,
400 BulkUpdateAgentTags,
401 BulkUpgradeAgents,
402 BulkRequestAgentDiagnostics
403);
404include_inactive_setter!(
405 BulkReassignAgents,
406 BulkUnenrollAgents,
407 BulkUpdateAgentTags,
408 BulkUpgradeAgents
409);
410upgrade_setters!(UpgradeAgent, BulkUpgradeAgents);
411diagnostics_setters!(RequestAgentDiagnostics, BulkRequestAgentDiagnostics);
412paginated!(FindAgents => FleetPage<Agent>);