/* * Copyright 2015 Philip Cronje * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package net.za.slyfox.dyn53.route53; import com.amazonaws.services.route53.AmazonRoute53; import com.amazonaws.services.route53.model.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Named; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.util.Objects; import java.util.function.Consumer; /** * Implements a {@link Consumer} that updates an Amazon Route 53 resource record set with the value of an * {@link InetAddress}. */ final class Route53Updater implements Consumer<InetAddress> { private final Logger logger = LoggerFactory.getLogger(getClass()); private final String hostedZoneId; private final String resourceRecordSetName; private final Long resourceRecordSetTtl; private final AmazonRoute53 route53; /** * Initializes this {@code Route53Updater} with configuration values, and injects dependencies. * * @param hostedZoneId the identifier of the hosted zone to update, as given by Route 53 * @param resourceRecordSetName the name of the resource record set in the hosted zone to update * @param route53 the Amazon Route 53 client interface to use when making requests against the service * @throws NullPointerException if a required parameter is {@code null} */ @Inject Route53Updater(@Named("hostedZoneId") String hostedZoneId, @Named("resourceRecordSetName") String resourceRecordSetName, @Named("resourceRecordSetTtl") Long resourceRecordSetTtl, AmazonRoute53 route53) { this.hostedZoneId = Objects.requireNonNull(hostedZoneId); this.resourceRecordSetName = Objects.requireNonNull(resourceRecordSetName); this.resourceRecordSetTtl = Objects.requireNonNull(resourceRecordSetTtl); this.route53 = Objects.requireNonNull(route53); } /** * Updates the configured resource record set with the value of an IP address. * * @param inetAddress the address to update the resource record set with */ @Override public void accept(InetAddress inetAddress) { final String address = inetAddress.getHostAddress(); logger.info("Updating resource record set {} in hosted zone {} to {}", resourceRecordSetName, hostedZoneId, address); final ResourceRecordSet resourceRecordSet = new ResourceRecordSet(resourceRecordSetName, getResourceRecordType(inetAddress)) .withResourceRecords(new ResourceRecord(address)) .withTTL(resourceRecordSetTtl); final Change change = new Change(ChangeAction.UPSERT, resourceRecordSet); final ChangeBatch changeBatch = new ChangeBatch().withChanges(change).withComment("Dyn53 update"); final ChangeResourceRecordSetsRequest request = new ChangeResourceRecordSetsRequest() .withHostedZoneId(hostedZoneId) .withChangeBatch(changeBatch); if(logger.isDebugEnabled()) { logger.debug("Requesting change: {}", change); } final ChangeResourceRecordSetsResult result = route53.changeResourceRecordSets(request); if(logger.isInfoEnabled()) { logger.info("Result of change request {}: {}", result.getChangeInfo().getId(), result.getChangeInfo().getStatus()); } } /** * Maps the given {@link InetAddress} to a {@link RRType} enumeration value. * * @param address the address to map * @return the {@code RRType} enumeration value corresponding to the type of address given * @throws IllegalArgumentException if {@code address} cannot be mapped to a value in the {@code RRType} enumeration */ private static RRType getResourceRecordType(InetAddress address) { if(address instanceof Inet4Address) { return RRType.A; } else if(address instanceof Inet6Address) { return RRType.AAAA; } else { throw new IllegalArgumentException("Unsupported address type " + address.getClass()); } } }