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: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ zip = { version = "9", default-features = false, features = ["deflate"], optiona

# Datadog API client — pinned to a git rev
# Use default-features = false; feature sets are activated per-target via features above
datadog-api-client = { git = "https://github.com/DataDog/datadog-api-client-rust", rev = "a0148e35b714615060937e8ebde2711fe9906aae", optional = true, default-features = false }
datadog-api-client = { git = "https://github.com/DataDog/datadog-api-client-rust", rev = "53de0d8e0e38c302a88e09e78ae4b81c8cf885e1", optional = true, default-features = false }

# HTTP middleware (version-matched to DD client; compiles on all targets)
reqwest-middleware = "0.5"
Expand Down
26 changes: 1 addition & 25 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,30 +418,6 @@ static UNSTABLE_OPS: &[&str] = &[
"v2.star_model_lab_project",
"v2.unpin_model_lab_run",
"v2.unstar_model_lab_project",
// Databricks Integration (5)
"v2.create_databricks_integration_account",
"v2.delete_databricks_integration_account",
"v2.get_databricks_integration_account",
"v2.list_databricks_integration_accounts",
"v2.update_databricks_integration_account",
// Elastic Cloud Integration (5)
"v2.create_elastic_cloud_integration_account",
"v2.delete_elastic_cloud_integration_account",
"v2.get_elastic_cloud_integration_account",
"v2.list_elastic_cloud_integration_accounts",
"v2.update_elastic_cloud_integration_account",
// Snowflake Integration (5)
"v2.create_snowflake_integration_account",
"v2.delete_snowflake_integration_account",
"v2.get_snowflake_integration_account",
"v2.list_snowflake_integration_accounts",
"v2.update_snowflake_integration_account",
// Twilio Integration (5)
"v2.create_twilio_integration_account",
"v2.delete_twilio_integration_account",
"v2.get_twilio_integration_account",
"v2.list_twilio_integration_accounts",
"v2.update_twilio_integration_account",
];

#[cfg(test)]
Expand Down Expand Up @@ -563,7 +539,7 @@ mod tests {

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

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

// pup CI denies clippy warnings, and the spec's size, not the generator, drives these two:
// operations with many params make long handler signatures and large command variants.
#![allow(clippy::too_many_arguments, clippy::large_enum_variant)]

pub mod authn_mappings;
pub mod domain_allowlist;
pub mod downtime;
pub mod security;
pub mod writes;

use anyhow::Result;
Expand Down
208 changes: 208 additions & 0 deletions src/generated/security/historical_jobs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// Code generated by openapi-transformer. DO NOT EDIT.

use anyhow::Result;
use datadog_api_client::datadogV2::api_security_monitoring::{
ListHistoricalJobsOptionalParams, SecurityMonitoringAPI,
};
use datadog_api_client::datadogV2::model::ConvertJobResultsToSignalsRequest;

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

#[derive(clap::Subcommand)]
pub enum Command {
/// Cancel a historical job
///
/// Cancel a historical job.
Cancel {
/// The ID of the job.
job_id: String,
},
/// Convert a job result to a signal
///
/// Convert a job result to a signal.
Convert {
#[arg(long = "file")]
file: String,
},
/// Delete an existing job
///
/// Delete an existing job.
Delete {
/// The ID of the job.
job_id: String,
},
/// Get a job's details
///
/// Get a job's details.
Get {
/// The ID of the job.
job_id: String,
},
/// List historical jobs
///
/// List historical jobs.
List {
/// Number of items to return per page. The maximum allowed value is 100.
#[arg(long = "page-size")]
page_size: Option<i64>,
/// Specific page number to return.
#[arg(long = "page-number")]
page_number: Option<i64>,
/// The order of the jobs in results.
#[arg(long = "sort")]
sort: Option<String>,
/// Query used to filter items from the fetched list.
#[arg(long = "filter-query")]
filter_query: Option<String>,
},
}

pub async fn run(cfg: &Config, command: Command) -> Result<()> {
match command {
Command::Cancel { job_id } => cancel(cfg, job_id).await,
Command::Convert { file } => convert(cfg, &file).await,
Command::Delete { job_id } => delete(cfg, job_id).await,
Command::Get { job_id } => get(cfg, job_id).await,
Command::List {
page_size,
page_number,
sort,
filter_query,
} => list(cfg, page_size, page_number, sort, filter_query).await,
}
}

/// Cancel a historical job
///
/// Cancel a historical job.
pub async fn cancel(cfg: &Config, job_id: String) -> Result<()> {
let resource_label = job_id.to_string();
let api = crate::make_api!(SecurityMonitoringAPI, cfg);
api.cancel_historical_job(job_id)
.await
.map_err(|e| anyhow::anyhow!("failed to cancel_historical_job: {:?}", e))?;
formatter::output_no_content(
cfg,
"security historical-jobs cancel",
Some(&resource_label),
)
}

/// Convert a job result to a signal
///
/// Convert a job result to a signal.
pub async fn convert(cfg: &Config, file: &str) -> Result<()> {
let body: ConvertJobResultsToSignalsRequest = util::read_json_file(file)?;
let api = crate::make_api!(SecurityMonitoringAPI, cfg);
api.convert_job_result_to_signal(body)
.await
.map_err(|e| anyhow::anyhow!("failed to convert_job_result_to_signal: {:?}", e))?;
formatter::output_no_content(cfg, "security historical-jobs convert", None)
}

/// Delete an existing job
///
/// Delete an existing job.
pub async fn delete(cfg: &Config, job_id: String) -> Result<()> {
let resource_label = job_id.to_string();
let api = crate::make_api!(SecurityMonitoringAPI, cfg);
api.delete_historical_job(job_id)
.await
.map_err(|e| anyhow::anyhow!("failed to delete_historical_job: {:?}", e))?;
formatter::output_no_content(
cfg,
"security historical-jobs delete",
Some(&resource_label),
)
}

/// Get a job's details
///
/// Get a job's details.
pub async fn get(cfg: &Config, job_id: String) -> Result<()> {
let api = crate::make_api!(SecurityMonitoringAPI, cfg);
let resp = api
.get_historical_job(job_id)
.await
.map_err(|e| anyhow::anyhow!("failed to get_historical_job: {:?}", e))?;
formatter::output(cfg, &resp)
}

/// List historical jobs
///
/// List historical jobs.
pub async fn list(
cfg: &Config,
page_size: Option<i64>,
page_number: Option<i64>,
sort: Option<String>,
filter_query: Option<String>,
) -> Result<()> {
let api = crate::make_api!(SecurityMonitoringAPI, cfg);
let mut params = ListHistoricalJobsOptionalParams::default();
if let Some(v) = page_size {
params = params.page_size(v);
}
if let Some(v) = page_number {
params = params.page_number(v);
}
if let Some(v) = sort {
params = params.sort(v);
}
if let Some(v) = filter_query {
params = params.filter_query(v);
}
let resp = api
.list_historical_jobs(params)
.await
.map_err(|e| anyhow::anyhow!("failed to list_historical_jobs: {:?}", e))?;
let count = resp.data.as_ref().map_or(0, |d| d.len());
let truncated = page_size.is_some_and(|l| count >= l as usize);
let next_action = if truncated {
page_size.map(|l| {
format!(
"Results may be truncated at {l}. Use --page-size={} or narrow the filters",
l + 1
)
})
} else {
None
};
let meta = formatter::Metadata {
count: Some(count),
truncated,
command: Some("security historical-jobs list".to_string()),
next_action,
..Default::default()
};
formatter::output_with_meta(cfg, &resp, &meta)
}

#[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": {"createdAt": "2024-01-01T00:00:00+00:00", "createdByHandle": "example-handle", "createdByName": "Example Name", "jobName": "Example Job", "jobStatus": "COMPLETED", "modifiedAt": "2024-01-01T00:00:00+00:00", "signalOutput": false}, "id": "abc-123", "type": "historicalDetectionsJob"}}"##).await;
let result = super::get(&cfg, "test".to_string()).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": {"createdAt": "2024-01-01T00:00:00+00:00", "createdByHandle": "example-handle", "createdByName": "Example Name", "jobName": "Example Job", "jobStatus": "COMPLETED"}, "id": "abc-123", "type": "historicalDetectionsJob"}], "meta": {"totalCount": 1}}"##).await;
let result = super::list(&cfg, None, None, None, None).await;
assert!(result.is_ok(), "list failed: {:?}", result.err());
cleanup_env();
}
}
Loading
Loading