use std::fmt::Debug; use anyhow::Result; use aws_sdk_route53::types::{Change, ChangeAction, ChangeBatch}; // Needed until try_collect is stable, see use itertools::Itertools; use crate::route53::{ResourceRecordSet, Route53}; #[derive(Debug)] pub struct Transaction { pub zone_id: String, pub changes: Changes, } #[derive(Debug)] pub struct Changes { pub remove: T, pub insert: T, } pub enum ApplyMode { DryRun, Apply, } impl ApplyMode { pub async fn apply(&self, aws_context: &C, transaction: Transaction) -> Result<()> where C: Route53, R: IntoIterator + Debug, { match self { ApplyMode::DryRun => dry_run(transaction).await, ApplyMode::Apply => apply(aws_context, transaction).await, } } } async fn dry_run(transaction: Transaction) -> Result<()> where R: IntoIterator + Debug, { println!("ZONE: {}", transaction.zone_id); println!("REMOVE: {:#?}", transaction.changes.remove); println!("INSERT: {:#?}", transaction.changes.insert); Ok(()) } async fn apply(aws_context: &C, transaction: Transaction) -> Result<()> where C: Route53, R: IntoIterator, { let Changes { remove: remove_records, insert: insert_records, } = transaction.changes; let remove_records = remove_records.into_iter().map(|record| { Change::builder() .action(ChangeAction::Delete) // <-- .resource_record_set(record.into()) .build() }); let insert_records = insert_records.into_iter().map(|record| { Change::builder() .action(ChangeAction::Create) // <-- .resource_record_set(record.into()) .build() }); let change_records: Vec<_> = remove_records.chain(insert_records).try_collect()?; if !change_records.is_empty() { let change_batch = ChangeBatch::builder() .set_changes(Some(change_records)) .build()?; aws_context .route53() .change_resource_record_sets() .hosted_zone_id(transaction.zone_id) .change_batch(change_batch) .send() .await?; } Ok(()) }