io.kodokojo.service.aws.Route53DnsManager.java Source code

Java tutorial

Introduction

Here is the source code for io.kodokojo.service.aws.Route53DnsManager.java

Source

/**
 * Kodo Kojo - Software factory done right
 * Copyright  2016 Kodo Kojo (infos@kodokojo.io)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package io.kodokojo.service.aws;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.auth.EnvironmentVariableCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.route53.AmazonRoute53Client;
import com.amazonaws.services.route53.model.*;
import io.kodokojo.service.dns.DnsEntry;
import io.kodokojo.service.dns.DnsManager;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;

public class Route53DnsManager implements DnsManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(Route53DnsManager.class);

    private final String domainName;

    private final AmazonRoute53Client client;

    public Route53DnsManager(String domainName, Region region) {
        if (isBlank(domainName)) {
            throw new IllegalArgumentException("domainName must be defined.");
        }
        this.domainName = domainName.endsWith(".") ? domainName : domainName + ".";

        AWSCredentials credentials = new DefaultAWSCredentialsProviderChain().getCredentials();
        client = new AmazonRoute53Client(credentials);
        client.setRegion(region == null ? Region.getRegion(Regions.EU_WEST_1) : region);
    }

    @Override
    public boolean createOrUpdateDnsEntry(DnsEntry dnsEntry) {
        if (dnsEntry == null) {
            throw new IllegalArgumentException("dnsEntry must be defined.");
        }
        createOrUpdateDnsEntries(Collections.singleton(dnsEntry));
        return true;
    }

    @Override
    public void createOrUpdateDnsEntries(Set<DnsEntry> dnsEntries) {
        if (dnsEntries == null) {
            throw new IllegalArgumentException("dnsEntries must be defined.");
        }

        HostedZone hostedZone = getHostedZone();
        List<Change> changes = new ArrayList<>();
        if (hostedZone != null) {
            for (DnsEntry dnsEntry : dnsEntries) {
                if (!containEntry(dnsEntry, true)) {
                    List<ResourceRecord> resourceRecords = new ArrayList<>();

                    ResourceRecord resourceRecord = new ResourceRecord();
                    String value = dnsEntry.getValue();
                    resourceRecord.setValue(
                            (dnsEntry.getType().equals(DnsEntry.Type.CNAME) ? valideDnsName(value) : value));
                    resourceRecords.add(resourceRecord);

                    ResourceRecordSet resourceRecordSet = new ResourceRecordSet();
                    resourceRecordSet.setName(valideDnsName(dnsEntry.getName()));
                    resourceRecordSet.setType(RRType.valueOf(dnsEntry.getType().toString()));
                    resourceRecordSet.setTTL(300L);

                    resourceRecordSet.setResourceRecords(resourceRecords);

                    Change change = new Change();
                    change.setAction(dnsEntryExist(dnsEntry) ? ChangeAction.UPSERT : ChangeAction.CREATE);
                    change.setResourceRecordSet(resourceRecordSet);
                    changes.add(change);
                }
            }
            if (CollectionUtils.isNotEmpty(changes)) {
                ChangeResourceRecordSetsRequest request = new ChangeResourceRecordSetsRequest();
                ChangeBatch changeBatch = new ChangeBatch();
                changeBatch.setChanges(changes);
                request.setChangeBatch(changeBatch);
                request.setHostedZoneId(getHostedZoneID(hostedZone));
                //ChangeResourceRecordSetsResult result =
                try {
                    client.changeResourceRecordSets(request);
                } catch (PriorRequestNotCompleteException e) {
                    LOGGER.error("Unable to create or update follwing entry in Route53 {}.",
                            StringUtils.join(dnsEntries, ","));
                }
            }
        }

    }

    @Override
    public boolean dnsEntryExist(DnsEntry dnsEntry) {
        return containEntry(dnsEntry, false);
    }

    private boolean containEntry(DnsEntry dnsEntry, boolean stric) {
        if (dnsEntry == null) {
            throw new IllegalArgumentException("dnsEntry must be defined.");
        }
        HostedZone hostedZone = getHostedZone();
        boolean found = false;
        if (hostedZone != null) {
            Iterator<ResourceRecordSet> iterator = getResourceRecordSet(hostedZone).iterator();
            String dnsEntryName = valideDnsName(dnsEntry.getName());
            while (!found && iterator.hasNext()) {
                ResourceRecordSet recordSet = iterator.next();
                found = recordSet.getName().equals(dnsEntryName)
                        && DnsEntry.Type.valueOf(recordSet.getType()).equals(dnsEntry.getType());
                if (found && stric) {
                    Iterator<ResourceRecord> recordIterator = recordSet.getResourceRecords().iterator();
                    boolean sameValue = false;
                    while (!sameValue && recordIterator.hasNext()) {
                        ResourceRecord record = recordIterator.next();
                        sameValue = dnsEntry.getValue().equals(record.getValue());
                    }
                    found = sameValue;
                }
            }
        }
        return found;
    }

    @Override
    public List<DnsEntry> getDnsEntries(String name) {
        String dnsName = null;
        if (isNotBlank(name)) {
            dnsName = valideDnsName(name);
        }
        HostedZone hostedZone = getHostedZone();
        List<DnsEntry> res = new ArrayList<>();
        if (hostedZone != null) {
            List<ResourceRecordSet> resourceRecordSet = getResourceRecordSet(hostedZone);
            for (ResourceRecordSet recordSet : resourceRecordSet) {
                if ((isNotBlank(dnsName) && recordSet.getName().equals(dnsName)) || isBlank(dnsName)) {
                    DnsEntry dnsEntry = convertDnsEnrty(recordSet);
                    res.add(dnsEntry);
                }
            }
        }
        return res;
    }

    private HostedZone getHostedZone() {
        ListHostedZonesByNameRequest listHostedZonesByNameRequest = new ListHostedZonesByNameRequest();
        listHostedZonesByNameRequest.setDNSName(domainName);
        ListHostedZonesByNameResult result = client.listHostedZonesByName(listHostedZonesByNameRequest);

        Iterator<HostedZone> iterator = result.getHostedZones().iterator();
        HostedZone hostedZone = null;
        while (hostedZone == null && iterator.hasNext()) {
            HostedZone currentZone = iterator.next();
            hostedZone = currentZone.getName().equals(domainName) ? currentZone : null;
        }
        return hostedZone;
    }

    private List<ResourceRecordSet> getResourceRecordSet(HostedZone hostedZone) {
        ListResourceRecordSetsRequest listResourceRecordSetsRequest = new ListResourceRecordSetsRequest();
        listResourceRecordSetsRequest.setHostedZoneId(getHostedZoneID(hostedZone));
        ListResourceRecordSetsResult recordSetsResult = client
                .listResourceRecordSets(listResourceRecordSetsRequest);
        return recordSetsResult.getResourceRecordSets();
    }

    private static String valideDnsName(String name) {
        return name.endsWith(".") ? name : name + ".";
    }

    private static String getHostedZoneID(HostedZone hostedZone) {
        return hostedZone.getId().substring("/hostedzone/".length());
    }

    private static DnsEntry convertDnsEnrty(ResourceRecordSet resourceRecordSet) {
        String dnsName = resourceRecordSet.getName();
        DnsEntry.Type dnsType = DnsEntry.Type.valueOf(resourceRecordSet.getType());
        String value = resourceRecordSet.getResourceRecords().get(0).getValue();
        return new DnsEntry(dnsName, dnsType, value);
    }
}