From 288205e302d9f6afa06b8602184e983d2080a5b6 Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Tue, 17 Oct 2023 21:17:55 -0400 Subject: CLI tool for updating Route53 DNS for an ASG. --- src/converge.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/converge.rs (limited to 'src/converge.rs') diff --git a/src/converge.rs b/src/converge.rs new file mode 100644 index 0000000..073e9e6 --- /dev/null +++ b/src/converge.rs @@ -0,0 +1,85 @@ +use std::fmt::Debug; + +use anyhow::anyhow; +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::result::Result; +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(dns_name, aws_context).await?; + let zone_id = zone + .id() + .ok_or(anyhow!("No ID for hosted zone for name: {}", dns_name))?; + + let (intended_records, actual_records) = try_join!( + instance_recordsets( + &asg_name, + dns_name, + dns_ttl, + &live_instance_ids, + aws_context + ), + zone_suffix_recordsets(dns_name, zone_id, aws_context), + )?; + + 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) +} -- cgit v1.2.3