diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2023-10-17 21:17:55 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2023-10-17 22:32:21 -0400 |
| commit | 288205e302d9f6afa06b8602184e983d2080a5b6 (patch) | |
| tree | dfb307e8f3cb82d280e5a0392f11318194e09ef1 /src/converge.rs | |
CLI tool for updating Route53 DNS for an ASG.
Diffstat (limited to 'src/converge.rs')
| -rw-r--r-- | src/converge.rs | 85 |
1 files changed, 85 insertions, 0 deletions
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<T> { + pub zone_id: String, + pub remove: T, + pub insert: T, +} + +async fn changes<C>( + aws_context: &C, + auto_scaling_group: &AutoScalingGroup, + dns_name: &Name, + dns_ttl: i64, +) -> Result<Changes<impl IntoIterator<Item = ResourceRecordSet> + 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<C>( + aws_context: &C, + name: &str, + dns_name: &Name, + dns_ttl: i64, +) -> Result<Changes<impl IntoIterator<Item = ResourceRecordSet> + 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) +} |
