1pub(crate) mod auth;
4pub(crate) mod dashboard;
5pub(crate) mod downtime;
6pub(crate) mod events;
7pub(crate) mod format;
8pub(crate) mod helpers;
9pub(crate) mod hosts;
10pub(crate) mod logs;
11pub(crate) mod metrics;
12pub(crate) mod monitor;
13pub(crate) mod slo;
14
15use anyhow::Result;
16use clap::{Parser, Subcommand};
17
18use crate::datadog::client::DatadogClient;
19
20#[derive(Parser)]
22pub struct DatadogCommand {
23 #[command(subcommand)]
25 pub command: DatadogSubcommands,
26}
27
28#[derive(Subcommand)]
30pub enum DatadogSubcommands {
31 Auth(auth::AuthCommand),
33 Dashboard(dashboard::DashboardCommand),
35 Downtime(downtime::DowntimeCommand),
37 Events(events::EventsCommand),
39 Hosts(hosts::HostsCommand),
41 Logs(logs::LogsCommand),
43 Metrics(metrics::MetricsCommand),
45 Monitor(monitor::MonitorCommand),
47 Slo(slo::SloCommand),
49}
50
51impl DatadogCommand {
52 pub async fn execute(self) -> Result<()> {
59 match self.command {
60 DatadogSubcommands::Auth(cmd) => cmd.execute().await,
61 data => {
62 let (client, _site) = helpers::create_client()?;
64 data.dispatch(&client).await
65 }
66 }
67 }
68}
69
70impl DatadogSubcommands {
71 async fn dispatch(self, client: &DatadogClient) -> Result<()> {
77 match self {
78 Self::Auth(_) => {
79 unreachable!("Auth is dispatched before client resolution")
80 }
81 Self::Dashboard(cmd) => cmd.execute(client).await,
82 Self::Downtime(cmd) => cmd.execute(client).await,
83 Self::Events(cmd) => cmd.execute(client).await,
84 Self::Hosts(cmd) => cmd.execute(client).await,
85 Self::Logs(cmd) => cmd.execute(client).await,
86 Self::Metrics(cmd) => cmd.execute(client).await,
87 Self::Monitor(cmd) => cmd.execute(client).await,
88 Self::Slo(cmd) => cmd.execute(client).await,
89 }
90 }
91}
92
93#[cfg(test)]
94#[allow(clippy::unwrap_used)]
95mod tests {
96 use super::*;
97 use crate::cli::datadog::format::OutputFormat;
98 use crate::datadog::client::DatadogClient;
99
100 fn dead_client() -> DatadogClient {
105 DatadogClient::new("http://127.0.0.1:1", "api", "app").unwrap()
106 }
107
108 #[test]
109 fn datadog_subcommands_auth_variant() {
110 let cmd = DatadogCommand {
111 command: DatadogSubcommands::Auth(auth::AuthCommand {
112 command: auth::AuthSubcommands::Status(auth::StatusCommand),
113 }),
114 };
115 assert!(matches!(cmd.command, DatadogSubcommands::Auth(_)));
116 }
117
118 #[test]
119 fn datadog_subcommands_metrics_variant() {
120 let cmd = DatadogCommand {
121 command: DatadogSubcommands::Metrics(metrics::MetricsCommand {
122 command: metrics::MetricsSubcommands::Query(metrics::query::QueryCommand {
123 query: "m".into(),
124 from: "1h".into(),
125 to: None,
126 output: OutputFormat::Table,
127 }),
128 }),
129 };
130 assert!(matches!(cmd.command, DatadogSubcommands::Metrics(_)));
131 }
132
133 #[tokio::test]
134 async fn dispatch_routes_metrics_query() {
135 let cmd = DatadogSubcommands::Metrics(metrics::MetricsCommand {
136 command: metrics::MetricsSubcommands::Query(metrics::query::QueryCommand {
137 query: "m".into(),
138 from: "1h".into(),
139 to: None,
140 output: OutputFormat::Table,
141 }),
142 });
143 assert!(cmd.dispatch(&dead_client()).await.is_err());
145 }
146
147 #[tokio::test]
148 async fn dispatch_routes_monitor_get() {
149 let cmd = DatadogSubcommands::Monitor(monitor::MonitorCommand {
150 command: monitor::MonitorSubcommands::Get(monitor::get::GetCommand {
151 id: 1,
152 output: OutputFormat::Table,
153 }),
154 });
155 assert!(cmd.dispatch(&dead_client()).await.is_err());
157 }
158
159 #[tokio::test]
160 async fn dispatch_routes_monitor_list() {
161 let cmd = DatadogSubcommands::Monitor(monitor::MonitorCommand {
162 command: monitor::MonitorSubcommands::List(monitor::list::ListCommand {
163 name: None,
164 tags: None,
165 monitor_tags: None,
166 limit: 5,
167 output: OutputFormat::Table,
168 }),
169 });
170 assert!(cmd.dispatch(&dead_client()).await.is_err());
172 }
173
174 #[tokio::test]
175 async fn dispatch_routes_monitor_search() {
176 let cmd = DatadogSubcommands::Monitor(monitor::MonitorCommand {
177 command: monitor::MonitorSubcommands::Search(monitor::search::SearchCommand {
178 query: "q".into(),
179 limit: 5,
180 output: OutputFormat::Table,
181 }),
182 });
183 assert!(cmd.dispatch(&dead_client()).await.is_err());
185 }
186
187 #[test]
188 fn datadog_subcommands_dashboard_variant() {
189 let cmd = DatadogCommand {
190 command: DatadogSubcommands::Dashboard(dashboard::DashboardCommand {
191 command: dashboard::DashboardSubcommands::List(dashboard::list::ListCommand {
192 filter_shared: false,
193 output: OutputFormat::Table,
194 }),
195 }),
196 };
197 assert!(matches!(cmd.command, DatadogSubcommands::Dashboard(_)));
198 }
199
200 #[tokio::test]
201 async fn dispatch_routes_dashboard_list() {
202 let cmd = DatadogSubcommands::Dashboard(dashboard::DashboardCommand {
203 command: dashboard::DashboardSubcommands::List(dashboard::list::ListCommand {
204 filter_shared: true,
205 output: OutputFormat::Table,
206 }),
207 });
208 assert!(cmd.dispatch(&dead_client()).await.is_err());
210 }
211
212 #[tokio::test]
213 async fn dispatch_routes_dashboard_get() {
214 let cmd = DatadogSubcommands::Dashboard(dashboard::DashboardCommand {
215 command: dashboard::DashboardSubcommands::Get(dashboard::get::GetCommand {
216 id: "abc".into(),
217 output: OutputFormat::Table,
218 }),
219 });
220 assert!(cmd.dispatch(&dead_client()).await.is_err());
222 }
223
224 #[test]
225 fn datadog_subcommands_logs_variant() {
226 let cmd = DatadogCommand {
227 command: DatadogSubcommands::Logs(logs::LogsCommand {
228 command: logs::LogsSubcommands::Search(logs::search::SearchCommand {
229 filter: "*".into(),
230 from: "15m".into(),
231 to: "now".into(),
232 limit: 10,
233 sort: logs::search::SortArg::TimestampDesc,
234 output: OutputFormat::Table,
235 }),
236 }),
237 };
238 assert!(matches!(cmd.command, DatadogSubcommands::Logs(_)));
239 }
240
241 #[tokio::test]
242 async fn dispatch_routes_logs_search() {
243 let cmd = DatadogSubcommands::Logs(logs::LogsCommand {
244 command: logs::LogsSubcommands::Search(logs::search::SearchCommand {
245 filter: "*".into(),
246 from: "15m".into(),
247 to: "now".into(),
248 limit: 10,
249 sort: logs::search::SortArg::TimestampDesc,
250 output: OutputFormat::Table,
251 }),
252 });
253 assert!(cmd.dispatch(&dead_client()).await.is_err());
255 }
256
257 #[test]
258 fn datadog_subcommands_events_variant() {
259 let cmd = DatadogCommand {
260 command: DatadogSubcommands::Events(events::EventsCommand {
261 command: events::EventsSubcommands::List(events::list::ListCommand {
262 filter: None,
263 from: "1h".into(),
264 to: "now".into(),
265 limit: 10,
266 sources: None,
267 tags: None,
268 output: OutputFormat::Table,
269 }),
270 }),
271 };
272 assert!(matches!(cmd.command, DatadogSubcommands::Events(_)));
273 }
274
275 #[tokio::test]
276 async fn dispatch_routes_events_list() {
277 let cmd = DatadogSubcommands::Events(events::EventsCommand {
278 command: events::EventsSubcommands::List(events::list::ListCommand {
279 filter: None,
280 from: "1h".into(),
281 to: "now".into(),
282 limit: 10,
283 sources: None,
284 tags: None,
285 output: OutputFormat::Table,
286 }),
287 });
288 assert!(cmd.dispatch(&dead_client()).await.is_err());
290 }
291
292 #[test]
293 fn datadog_subcommands_slo_variant() {
294 let cmd = DatadogCommand {
295 command: DatadogSubcommands::Slo(slo::SloCommand {
296 command: slo::SloSubcommands::List(slo::list::ListCommand {
297 tags: None,
298 query: None,
299 ids: None,
300 metrics_query: None,
301 limit: 5,
302 output: OutputFormat::Table,
303 }),
304 }),
305 };
306 assert!(matches!(cmd.command, DatadogSubcommands::Slo(_)));
307 }
308
309 #[tokio::test]
310 async fn dispatch_routes_slo_list() {
311 let cmd = DatadogSubcommands::Slo(slo::SloCommand {
312 command: slo::SloSubcommands::List(slo::list::ListCommand {
313 tags: None,
314 query: None,
315 ids: None,
316 metrics_query: None,
317 limit: 5,
318 output: OutputFormat::Table,
319 }),
320 });
321 assert!(cmd.dispatch(&dead_client()).await.is_err());
323 }
324
325 #[tokio::test]
326 async fn dispatch_routes_slo_get() {
327 let cmd = DatadogSubcommands::Slo(slo::SloCommand {
328 command: slo::SloSubcommands::Get(slo::get::GetCommand {
329 id: "abc".into(),
330 output: OutputFormat::Table,
331 }),
332 });
333 assert!(cmd.dispatch(&dead_client()).await.is_err());
335 }
336
337 #[test]
338 fn datadog_subcommands_hosts_variant() {
339 let cmd = DatadogCommand {
340 command: DatadogSubcommands::Hosts(hosts::HostsCommand {
341 command: hosts::HostsSubcommands::List(hosts::list::ListCommand {
342 filter: None,
343 from: None,
344 limit: 5,
345 output: OutputFormat::Table,
346 }),
347 }),
348 };
349 assert!(matches!(cmd.command, DatadogSubcommands::Hosts(_)));
350 }
351
352 #[tokio::test]
353 async fn dispatch_routes_hosts_list() {
354 let cmd = DatadogSubcommands::Hosts(hosts::HostsCommand {
355 command: hosts::HostsSubcommands::List(hosts::list::ListCommand {
356 filter: None,
357 from: None,
358 limit: 5,
359 output: OutputFormat::Table,
360 }),
361 });
362 assert!(cmd.dispatch(&dead_client()).await.is_err());
364 }
365
366 #[test]
367 fn datadog_subcommands_downtime_variant() {
368 let cmd = DatadogCommand {
369 command: DatadogSubcommands::Downtime(downtime::DowntimeCommand {
370 command: downtime::DowntimeSubcommands::List(downtime::list::ListCommand {
371 active_only: false,
372 output: OutputFormat::Table,
373 }),
374 }),
375 };
376 assert!(matches!(cmd.command, DatadogSubcommands::Downtime(_)));
377 }
378
379 #[tokio::test]
380 async fn dispatch_routes_downtime_list() {
381 let cmd = DatadogSubcommands::Downtime(downtime::DowntimeCommand {
382 command: downtime::DowntimeSubcommands::List(downtime::list::ListCommand {
383 active_only: true,
384 output: OutputFormat::Table,
385 }),
386 });
387 assert!(cmd.dispatch(&dead_client()).await.is_err());
389 }
390
391 #[tokio::test]
392 async fn dispatch_routes_metrics_catalog_list() {
393 let cmd = DatadogSubcommands::Metrics(metrics::MetricsCommand {
394 command: metrics::MetricsSubcommands::Catalog(metrics::catalog::CatalogCommand {
395 command: metrics::catalog::CatalogSubcommands::List(
396 metrics::catalog::list::ListCommand {
397 host: None,
398 from: None,
399 output: OutputFormat::Table,
400 },
401 ),
402 }),
403 });
404 assert!(cmd.dispatch(&dead_client()).await.is_err());
406 }
407}