package denominator.route53;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import denominator.model.ResourceRecordSet;
import denominator.route53.Route53.ActionOnResourceRecordSet;
import feign.RequestTemplate;
import feign.codec.Encoder;
import static denominator.common.Preconditions.checkNotNull;
import static denominator.common.Util.join;
import static java.lang.String.format;
class EncodeChanges implements Encoder {
static String apply(ResourceRecordSet<?> rrs) {
StringBuilder builder = new StringBuilder().append("<ResourceRecordSet>");
builder.append("<Name>").append(rrs.name()).append("</Name>");
builder.append("<Type>").append(rrs.type()).append("</Type>");
if (rrs.qualifier() != null) {
builder.append("<SetIdentifier>")//
.append(rrs.qualifier())//
.append("</SetIdentifier>");
}
// note lowercase as this is a supported profile
if (rrs.weighted() != null) {
builder.append("<Weight>").append(rrs.weighted().weight()).append("</Weight>");
}
if (rrs.records().size() == 1 && rrs.records().get(0).containsKey("HostedZoneId")) {
builder.append("<AliasTarget>");
Map<String, Object> aliasTarget = rrs.records().get(0);
for (String attribute : new String[]{"HostedZoneId", "DNSName"}) {
builder.append('<').append(attribute).append('>');
builder.append(
checkNotNull(aliasTarget.get(attribute), "missing %s in alias target %s", attribute,
rrs));
builder.append("</").append(attribute).append('>');
}
// not valid until health checks are supported.
builder.append("<EvaluateTargetHealth>false</EvaluateTargetHealth>");
builder.append("</AliasTarget>");
} else {
// default ttl from the amazon console is 300
builder.append("<TTL>").append(rrs.ttl() == null ? 300 : rrs.ttl()).append("</TTL>");
builder.append("<ResourceRecords>");
for (Map<String, Object> data : rrs.records()) {
String textFormat = join(' ', data.values().toArray());
if ("SPF".equals(rrs.type()) || "TXT".equals(rrs.type())) {
textFormat = format("\"%s\"", textFormat);
}
builder.append("<ResourceRecord>").append("<Value>").append(textFormat).append("</Value>")
.append("</ResourceRecord>");
}
builder.append("</ResourceRecords>");
}
return builder.append("</ResourceRecordSet>").toString();
}
@Override
public void encode(Object object, Type bodyType, RequestTemplate template) {
List<ActionOnResourceRecordSet> actions = (List<ActionOnResourceRecordSet>) object;
StringBuilder b = new StringBuilder();
b.append(
"<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2012-12-12/\"><ChangeBatch>");
b.append("<Changes>");
for (ActionOnResourceRecordSet change : actions) {
b.append("<Change>").append("<Action>").append(change.action).append("</Action>")
.append(apply(change.rrs))
.append("</Change>");
}
b.append("</Changes>");
b.append("</ChangeBatch></ChangeResourceRecordSetsRequest>");
template.body(b.toString());
}
}