use redis_cloud::CloudClient;
use redis_cloud::cost_report::CostReportCreateRequest;
use redis_cloud::types::TaskStatus;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut args = std::env::args().skip(1);
let start = args
.next()
.ok_or("usage: cost_report START_DATE END_DATE (dates in YYYY-MM-DD)")?;
let end = args
.next()
.ok_or("usage: cost_report START_DATE END_DATE (dates in YYYY-MM-DD)")?;
let api_key = std::env::var("REDIS_CLOUD_API_KEY")?;
let api_secret = std::env::var("REDIS_CLOUD_API_SECRET")?;
let client = CloudClient::builder()
.api_key(api_key)
.api_secret(api_secret)
.build()?;
let request = CostReportCreateRequest::new(&start, &end);
let task = client.cost_reports().generate_cost_report(request).await?;
let task_id = task
.task_id
.clone()
.ok_or("server did not return a task_id")?;
println!("kicked off cost-report generation: task {task_id}");
println!("polling task...");
let report_id = loop {
tokio::time::sleep(Duration::from_secs(5)).await;
let state = client.tasks().get_task_by_id(task_id.clone()).await?;
println!(" status={:?} progress={:?}", state.status, state.progress);
match state.status {
Some(TaskStatus::ProcessingCompleted) => {
break state
.response
.as_ref()
.and_then(|r| r.resource.as_ref())
.and_then(|res| res.get("costReportId"))
.and_then(|v| v.as_str())
.map(str::to_string)
.ok_or("task completed but did not return a costReportId")?;
}
Some(TaskStatus::ProcessingError) => {
return Err(format!(
"task ended with status {:?}: {}",
state.status,
serde_json::to_string(&state.response)?
)
.into());
}
_ => {}
}
};
println!("downloading report {report_id}");
let bytes = client
.cost_reports()
.download_cost_report(&report_id)
.await?;
let out_path = format!("cost-report-{report_id}");
std::fs::write(&out_path, &bytes)?;
println!("wrote {} bytes to {out_path}", bytes.len());
Ok(())
}