use std::fmt::Debug; use anyhow::Result; use aws_sdk_autoscaling::types::AutoScalingGroup; use aws_sdk_route53::types::ResourceRecordSet; use futures::try_join; use trust_dns_proto::rr::Name; use crate::autoscaling::{asg_by_name, AutoScaling}; use crate::dns::AutoScalingGroupConfig; use crate::ec2::{instance_recordsets, Ec2}; use crate::hashable::Hashable; use crate::route53::{zone_for_domain, zone_suffix_recordsets, Route53}; #[derive(Debug)] pub struct Changes { pub zone_id: String, pub remove: T, pub insert: T, } async fn changes( aws_context: &C, auto_scaling_group: &AutoScalingGroup, dns_name: &Name, dns_ttl: i64, ) -> Result + Debug>> where C: Ec2 + Route53, { let AutoScalingGroupConfig { name: asg_name, live_instance_ids, } = AutoScalingGroupConfig::try_from(auto_scaling_group)?; let zone = zone_for_domain(aws_context, dns_name).await?; let zone_id = zone.id(); let (intended_records, actual_records) = try_join!( instance_recordsets( aws_context, &asg_name, dns_name, dns_ttl, &live_instance_ids, ), zone_suffix_recordsets(aws_context, zone_id, dns_name), )?; let remove_records = actual_records.difference(&intended_records); let insert_records = intended_records.difference(&actual_records); let remove_records = remove_records.map(Hashable::as_ref); let insert_records = insert_records.map(Hashable::as_ref); let remove_records = remove_records.map(ToOwned::to_owned); let insert_records = insert_records.map(ToOwned::to_owned); let remove_records: Vec<_> = remove_records.collect(); let insert_records: Vec<_> = insert_records.collect(); Ok(Changes { zone_id: zone_id.into(), remove: remove_records, insert: insert_records, }) } pub async fn named_asg_changes( aws_context: &C, name: &str, dns_name: &Name, dns_ttl: i64, ) -> Result + Debug>> where C: AutoScaling + Ec2 + Route53, { let auto_scaling_group = asg_by_name(aws_context, name).await?; let changes = changes(aws_context, &auto_scaling_group, dns_name, dns_ttl).await?; Ok(changes) }