Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/auth/callback.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Code generated by openapi-transformer. DO NOT EDIT.

#[cfg(not(target_arch = "wasm32"))]
use anyhow::bail;
use anyhow::Result;
Expand Down
2 changes: 2 additions & 0 deletions src/auth/dcr.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Code generated by openapi-transformer. DO NOT EDIT.

#[cfg(not(target_arch = "wasm32"))]
use anyhow::{bail, Context, Result};
#[cfg(not(target_arch = "wasm32"))]
Expand Down
2 changes: 2 additions & 0 deletions src/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Code generated by openapi-transformer. DO NOT EDIT.

pub mod callback;
pub mod dcr;
pub mod pkce;
Expand Down
2 changes: 2 additions & 0 deletions src/auth/pkce.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Code generated by openapi-transformer. DO NOT EDIT.

#[cfg(not(target_arch = "wasm32"))]
use anyhow::Result;
#[cfg(not(target_arch = "wasm32"))]
Expand Down
2 changes: 2 additions & 0 deletions src/auth/storage.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Code generated by openapi-transformer. DO NOT EDIT.

use anyhow::{Context, Result};
use std::path::PathBuf;

Expand Down
4 changes: 3 additions & 1 deletion src/auth/types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Code generated by openapi-transformer. DO NOT EDIT.

use chrono::Utc;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -260,7 +262,7 @@ pub fn default_scopes() -> Vec<&'static str> {
"synthetics_read",
"synthetics_write",
"synthetics_private_location_read",
// Tag Rules
// Tag Policies
"telemetry_rules_create",
"telemetry_rules_read",
// Teams
Expand Down
42 changes: 11 additions & 31 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Code generated by openapi-transformer. DO NOT EDIT.

use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};

#[cfg(not(target_arch = "wasm32"))]
Expand Down Expand Up @@ -31,24 +33,6 @@ impl Middleware for BearerAuthMiddleware {
}
}

#[cfg(not(target_arch = "wasm32"))]
struct RateLimitCaptureMiddleware;

#[cfg(not(target_arch = "wasm32"))]
#[async_trait]
impl Middleware for RateLimitCaptureMiddleware {
async fn handle(
&self,
req: reqwest_middleware::reqwest::Request,
extensions: &mut Extensions,
next: Next<'_>,
) -> reqwest_middleware::Result<reqwest_middleware::reqwest::Response> {
let resp = next.run(req, extensions).await?;
crate::rate_limit::store_last(crate::rate_limit::extract_from_headers(resp.headers()));
Ok(resp)
}
}

// The `datadog-api-client` SDK's `Configuration.user_agent` is `pub(crate)`
// with no setter, so the only way to override it from outside the crate is
// via middleware that mutates the header after the SDK builds the request.
Expand Down Expand Up @@ -148,9 +132,7 @@ pub fn make_dd_client(cfg: &Config, send_bearer: bool) -> Option<ClientWithMiddl
let reqwest_client = reqwest_middleware::reqwest::Client::builder()
.build()
.expect("failed to build reqwest client");
let mut builder = ClientBuilder::new(reqwest_client)
.with(UserAgentMiddleware)
.with(RateLimitCaptureMiddleware);
let mut builder = ClientBuilder::new(reqwest_client).with(UserAgentMiddleware);
if send_bearer {
if let Some(token) = cfg.access_token.as_ref() {
builder = builder.with(BearerAuthMiddleware {
Expand Down Expand Up @@ -390,15 +372,13 @@ static UNSTABLE_OPS: &[&str] = &[
"v2.trigger_investigation",
// Cloud Cost Management — Anomalies (1)
"v2.list_cost_anomalies",
// Tag Rules (6)
"v2.create_tag_rule",
"v2.delete_tag_rule",
"v2.get_tag_rule",
"v2.get_tag_rule_score",
"v2.list_tag_rules",
"v2.update_tag_rule",
// RUM Session Replay (1)
"v2.get_segments",
// Tag Policies (6)
"v2.create_tag_policy",
"v2.delete_tag_policy",
"v2.get_tag_policy",
"v2.get_tag_policy_score",
"v2.list_tag_policies",
"v2.update_tag_policy",
// Model Lab (16)
"v2.delete_model_lab_run",
"v2.get_model_lab_artifact_content",
Expand Down Expand Up @@ -538,7 +518,7 @@ mod tests {

#[test]
fn test_unstable_ops_count() {
assert_eq!(UNSTABLE_OPS.len(), 187);
assert_eq!(UNSTABLE_OPS.len(), 186);
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Code generated by openapi-transformer. DO NOT EDIT.

use anyhow::{bail, Result};
#[cfg(not(feature = "browser"))]
use serde::Deserialize;
Expand Down
273 changes: 273 additions & 0 deletions src/downtimes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
// Code generated by openapi-transformer. DO NOT EDIT.

use anyhow::Result;
use datadog_api_client::datadogV2::api_downtimes::{
DowntimesAPI, GetDowntimeOptionalParams, ListDowntimesOptionalParams,
ListMonitorDowntimesOptionalParams,
};
use datadog_api_client::datadogV2::model::{DowntimeCreateRequest, DowntimeUpdateRequest};

use crate::config::Config;
use crate::formatter;
use crate::util;

#[derive(clap::Subcommand)]
pub enum Command {
/// Cancel a downtime
///
/// Cancel a downtime.
///
/// **Note**: Downtimes canceled through the API are no longer active, but are retained for approximately two days before being permanently removed. The downtime may still appear in search results until it is permanently removed.
Cancel {
/// ID of the downtime to cancel.
downtime_id: String,
},
/// Schedule a downtime
///
/// Schedule a downtime.
Create {
#[arg(long)]
file: String,
},
/// Get a downtime
///
/// Get downtime detail by `downtime_id`.
Get {
/// ID of the downtime to fetch.
downtime_id: String,
/// Comma-separated list of resource paths for related resources to include in the response. Supported resource
/// paths are `created_by` and `monitor`.
#[arg(long)]
include: Option<String>,
},
/// Get all downtimes
///
/// Get all scheduled downtimes.
List {
/// Only return downtimes that are active when the request is made.
#[arg(long)]
current_only: Option<bool>,
/// Comma-separated list of resource paths for related resources to include in the response. Supported resource
/// paths are `created_by` and `monitor`.
#[arg(long)]
include: Option<String>,
/// Specific offset to use as the beginning of the returned page.
#[arg(long)]
page_offset: Option<i64>,
/// Maximum number of downtimes in the response.
#[arg(long)]
page_limit: Option<i64>,
},
/// Get active downtimes for a monitor
///
/// Get all active downtimes for the specified monitor.
ListMonitor {
/// The id of the monitor.
monitor_id: i64,
/// Specific offset to use as the beginning of the returned page.
#[arg(long)]
page_offset: Option<i64>,
/// Maximum number of downtimes in the response.
#[arg(long)]
page_limit: Option<i64>,
},
/// Update a downtime
///
/// Update a downtime by `downtime_id`.
Update {
/// ID of the downtime to update.
downtime_id: String,
#[arg(long)]
file: String,
},
}

pub async fn run(cfg: &Config, command: Command) -> Result<()> {
match command {
Command::Cancel { downtime_id } => cancel(cfg, downtime_id).await,
Command::Create { file } => create(cfg, &file).await,
Command::Get {
downtime_id,
include,
} => get(cfg, downtime_id, include).await,
Command::List {
current_only,
include,
page_offset,
page_limit,
} => list(cfg, current_only, include, page_offset, page_limit).await,
Command::ListMonitor {
monitor_id,
page_offset,
page_limit,
} => list_monitor(cfg, monitor_id, page_offset, page_limit).await,
Command::Update { downtime_id, file } => update(cfg, downtime_id, &file).await,
}
}

/// Cancel a downtime
///
/// Cancel a downtime.
///
/// **Note**: Downtimes canceled through the API are no longer active, but are retained for approximately two days before being permanently removed. The downtime may still appear in search results until it is permanently removed.
pub async fn cancel(cfg: &Config, downtime_id: String) -> Result<()> {
let api = crate::make_api!(DowntimesAPI, cfg);
api.cancel_downtime(downtime_id)
.await
.map_err(|e| anyhow::anyhow!("failed to cancel_downtime: {:?}", e))?;
println!("downtimes cancel: ok");
Ok(())
}

/// Schedule a downtime
///
/// Schedule a downtime.
pub async fn create(cfg: &Config, file: &str) -> Result<()> {
let body: DowntimeCreateRequest = util::read_json_file(file)?;
let api = crate::make_api!(DowntimesAPI, cfg);
let resp = api
.create_downtime(body)
.await
.map_err(|e| anyhow::anyhow!("failed to create_downtime: {:?}", e))?;
formatter::output(cfg, &resp)
}

/// Get a downtime
///
/// Get downtime detail by `downtime_id`.
pub async fn get(cfg: &Config, downtime_id: String, include: Option<String>) -> Result<()> {
let api = crate::make_api!(DowntimesAPI, cfg);
let mut params = GetDowntimeOptionalParams::default();
if let Some(v) = include {
params = params.include(v);
}
let resp = api
.get_downtime(downtime_id, params)
.await
.map_err(|e| anyhow::anyhow!("failed to get_downtime: {:?}", e))?;
formatter::output(cfg, &resp)
}

/// Get all downtimes
///
/// Get all scheduled downtimes.
pub async fn list(
cfg: &Config,
current_only: Option<bool>,
include: Option<String>,
page_offset: Option<i64>,
page_limit: Option<i64>,
) -> Result<()> {
let api = crate::make_api!(DowntimesAPI, cfg);
let mut params = ListDowntimesOptionalParams::default();
if let Some(v) = current_only {
params = params.current_only(v);
}
if let Some(v) = include {
params = params.include(v);
}
if let Some(v) = page_offset {
params = params.page_offset(v);
}
if let Some(v) = page_limit {
params = params.page_limit(v);
}
let resp = api
.list_downtimes(params)
.await
.map_err(|e| anyhow::anyhow!("failed to list_downtimes: {:?}", e))?;
let count = resp.data.as_ref().map_or(0, |d| d.len());
let truncated = false;
let next_action: Option<String> = None;
let meta = formatter::Metadata {
count: Some(count),
truncated,
command: Some("downtimes list".to_string()),
next_action,
};
formatter::format_and_print(&resp, &cfg.output_format, cfg.agent_mode, Some(&meta))
}

/// Get active downtimes for a monitor
///
/// Get all active downtimes for the specified monitor.
pub async fn list_monitor(
cfg: &Config,
monitor_id: i64,
page_offset: Option<i64>,
page_limit: Option<i64>,
) -> Result<()> {
let api = crate::make_api!(DowntimesAPI, cfg);
let mut params = ListMonitorDowntimesOptionalParams::default();
if let Some(v) = page_offset {
params = params.page_offset(v);
}
if let Some(v) = page_limit {
params = params.page_limit(v);
}
let resp = api
.list_monitor_downtimes(monitor_id, params)
.await
.map_err(|e| anyhow::anyhow!("failed to list_monitor_downtimes: {:?}", e))?;
let count = resp.data.as_ref().map_or(0, |d| d.len());
let truncated = false;
let next_action: Option<String> = None;
let meta = formatter::Metadata {
count: Some(count),
truncated,
command: Some("downtimes list_monitor".to_string()),
next_action,
};
formatter::format_and_print(&resp, &cfg.output_format, cfg.agent_mode, Some(&meta))
}

/// Update a downtime
///
/// Update a downtime by `downtime_id`.
pub async fn update(cfg: &Config, downtime_id: String, file: &str) -> Result<()> {
let body: DowntimeUpdateRequest = util::read_json_file(file)?;
let api = crate::make_api!(DowntimesAPI, cfg);
let resp = api
.update_downtime(downtime_id, body)
.await
.map_err(|e| anyhow::anyhow!("failed to update_downtime: {:?}", e))?;
formatter::output(cfg, &resp)
}

#[cfg(test)]
mod tests {
use crate::test_support::*;

#[tokio::test]
async fn test_get_ok() {
let _lock = lock_env().await;
let mut server = mockito::Server::new_async().await;
let cfg = test_config(&server.url());
let _mock = mock_any(&mut server, "GET", r##"{"data": {"attributes": {"created": "2024-01-01T00:00:00+00:00", "display_timezone": "America/New_York", "message": "Message about the downtime", "modified": "2024-01-01T00:00:00+00:00", "monitor_identifier": {"monitor_tags": ["*"]}, "mute_first_recovery_notification": false, "notify_end_states": ["alert", "warn"], "notify_end_types": ["canceled", "expired"], "scope": "env:(staging OR prod) AND datacenter:us-east-1", "status": "active"}, "id": "00000000-0000-1234-0000-000000000000", "type": "downtime"}}"##).await;
let result = super::get(&cfg, "test".to_string(), None).await;
assert!(result.is_ok(), "get failed: {:?}", result.err());
cleanup_env();
}

#[tokio::test]
async fn test_list_ok() {
let _lock = lock_env().await;
let mut server = mockito::Server::new_async().await;
let cfg = test_config(&server.url());
let _mock = mock_any(&mut server, "GET", r##"{"data": [{"attributes": {"created": "2024-01-01T00:00:00+00:00", "display_timezone": "America/New_York", "message": "Message about the downtime", "modified": "2024-01-01T00:00:00+00:00", "monitor_identifier": {"monitor_tags": ["*"]}, "mute_first_recovery_notification": false, "notify_end_states": ["alert", "warn"], "notify_end_types": ["canceled", "expired"], "scope": "env:(staging OR prod) AND datacenter:us-east-1", "status": "active"}, "id": "00000000-0000-1234-0000-000000000000", "type": "downtime"}], "meta": {"page": {"total_filtered_count": 1}}}"##).await;
let result = super::list(&cfg, None, None, None, None).await;
assert!(result.is_ok(), "list failed: {:?}", result.err());
cleanup_env();
}

#[tokio::test]
async fn test_list_monitor_ok() {
let _lock = lock_env().await;
let mut server = mockito::Server::new_async().await;
let cfg = test_config(&server.url());
let _mock = mock_any(&mut server, "GET", r##"{"data": [{"attributes": {"end": "2024-01-01T01:00:00+00:00", "groups": ["service:postgres"], "scope": "env:(staging OR prod) AND datacenter:us-east-1", "start": "2024-01-01T00:00:00+00:00"}, "id": "00000000-0000-1234-0000-000000000000", "type": "downtime_match"}], "meta": {"page": {"total_filtered_count": 1}}}"##).await;
let result = super::list_monitor(&cfg, 1, None, None).await;
assert!(result.is_ok(), "list_monitor failed: {:?}", result.err());
cleanup_env();
}
}
Loading
Loading