summaryrefslogtreecommitdiffstats
path: root/controller-api
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2020-06-24 13:35:32 +0200
committerMartin Polden <mpolden@mpolden.no>2020-06-24 14:41:35 +0200
commit0c3080ce98166a121d94775d2da9fdc63b737be8 (patch)
tree8ae1747586597ad5d727baa0d6d40ef057fa9fb6 /controller-api
parentc2b57fddcbc9beb3b866d579c6cd68a68590651e (diff)
Support multiple types of alias targets
Diffstat (limited to 'controller-api')
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTarget.java58
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/LatencyAliasTarget.java60
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java8
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java11
4 files changed, 94 insertions, 43 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTarget.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTarget.java
index b92eb80df80..a5436bc3fc1 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTarget.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTarget.java
@@ -1,73 +1,63 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration.dns;
import com.yahoo.config.provision.HostName;
-import com.yahoo.config.provision.zone.ZoneId;
import java.util.Objects;
/**
- * Represents the target of an ALIAS record.
+ * The target of an {@link Record.Type#ALIAS} record. Contains record fields unique to aliases.
*
* @author mpolden
*/
-public class AliasTarget {
+public abstract class AliasTarget {
private final HostName name;
private final String dnsZone;
- private final ZoneId zone;
+ private final String id;
- public AliasTarget(HostName name, String dnsZone, ZoneId zone) {
+ public AliasTarget(HostName name, String dnsZone, String id) {
this.name = Objects.requireNonNull(name, "name must be non-null");
this.dnsZone = Objects.requireNonNull(dnsZone, "dnsZone must be non-null");
- this.zone = Objects.requireNonNull(zone, "zone must be non-null");
+ this.id = Objects.requireNonNull(id, "id must be non-null");
}
- /** DNS name of this */
- public HostName name() {
- return name;
+ /** A unique identifier of this record within the ALIAS record group */
+ public String id() {
+ return id;
}
- /** DNS zone of this */
- public String dnsZone() {
- return dnsZone;
+ /** DNS name this points to */
+ public final HostName name() {
+ return name;
}
- /** The zone where this exists */
- public ZoneId zone() {
- return zone;
+ /** The DNS zone this belongs to */
+ public final String dnsZone() {
+ return dnsZone;
}
/** Returns the fields in this encoded as record data */
- public RecordData asData() {
- return RecordData.from(name.value() + "/" + dnsZone + "/" + zone.value());
- }
+ public abstract RecordData pack();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- AliasTarget that = (AliasTarget) o;
- return name.equals(that.name);
+ AliasTarget alias = (AliasTarget) o;
+ return name.equals(alias.name) &&
+ dnsZone.equals(alias.dnsZone) &&
+ id.equals(alias.id);
}
@Override
public int hashCode() {
- return Objects.hash(name);
- }
-
- @Override
- public String toString() {
- return String.format("rotation target %s [zone: %s] in %s", name, dnsZone, zone);
+ return Objects.hash(name, dnsZone, id);
}
- public static AliasTarget from(RecordData data) {
- var parts = data.asString().split("/");
- if (parts.length != 3) {
- throw new IllegalArgumentException("Expected data to be on format [hostname]/[DNS zone]/[zone], but got " +
- data.asString());
- }
- return new AliasTarget(HostName.from(parts[0]), parts[1], ZoneId.from(parts[2]));
+ /** Unpack target from given record data */
+ public static AliasTarget unpack(RecordData data) {
+ return LatencyAliasTarget.unpack(data);
}
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/LatencyAliasTarget.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/LatencyAliasTarget.java
new file mode 100644
index 00000000000..7bd43ff1dcb
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/LatencyAliasTarget.java
@@ -0,0 +1,60 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.api.integration.dns;
+
+import com.yahoo.config.provision.HostName;
+import com.yahoo.config.provision.zone.ZoneId;
+
+import java.util.Objects;
+
+/**
+ * An implementation of {@link AliasTarget} that uses latency-based routing.
+ *
+ * @author mpolden
+ */
+public class LatencyAliasTarget extends AliasTarget {
+
+ private final ZoneId zone;
+
+ public LatencyAliasTarget(HostName name, String dnsZone, ZoneId zone) {
+ super(name, dnsZone, zone.value());
+ this.zone = Objects.requireNonNull(zone);
+ }
+
+ /** The zone this record points to */
+ public ZoneId zone() {
+ return zone;
+ }
+
+ @Override
+ public RecordData pack() {
+ return RecordData.from("latency/" + name().value() + "/" + dnsZone() + "/" + id());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+ LatencyAliasTarget that = (LatencyAliasTarget) o;
+ return zone.equals(that.zone);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), zone);
+ }
+
+ /** Unpack latency alias from given record data */
+ public static LatencyAliasTarget unpack(RecordData data) {
+ var parts = data.asString().split("/");
+ if (parts.length != 4) {
+ throw new IllegalArgumentException("Expected data to be on format type/name/DNS-zone/zone-id, but got " +
+ data.asString());
+ }
+ if (!"latency".equals(parts[0])) {
+ throw new IllegalArgumentException("Unexpected type '" + parts[0] + "'");
+ }
+ return new LatencyAliasTarget(HostName.from(parts[1]), parts[2], ZoneId.from(parts[3]));
+ }
+
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java
index 59324079e6f..e8688b17347 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration.dns;
@@ -43,7 +43,7 @@ public class MemoryNameService implements NameService {
public List<Record> createAlias(RecordName name, Set<AliasTarget> targets) {
var records = targets.stream()
.sorted((a, b) -> Comparator.comparing(AliasTarget::name).compare(a, b))
- .map(target -> new Record(Record.Type.ALIAS, name, target.asData()))
+ .map(d -> new Record(Record.Type.ALIAS, name, d.pack()))
.collect(Collectors.toList());
// Satisfy idempotency contract of interface
records.stream()
@@ -80,7 +80,7 @@ public class MemoryNameService implements NameService {
if (record.type() == type) {
if (type == Record.Type.ALIAS) {
// Unpack ALIAS record and compare FQDN of data part
- return RecordData.fqdn(AliasTarget.from(record.data()).name().value())
+ return RecordData.fqdn(AliasTarget.unpack(record.data()).name().value())
.equals(data);
}
return record.data().equals(data);
@@ -111,7 +111,7 @@ public class MemoryNameService implements NameService {
}
/**
- * Returns whether record r1 and r2 can co-exist in a name service. This attempts to enforce the same constraints as
+ * Returns whether record r1 and r2 are in conflict. This attempts to enforce the same constraints a
* most real name services.
*/
private static boolean conflicts(Record r1, Record r2) {
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java
index 903ea250935..9f2fd887482 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/NameService.java
@@ -1,4 +1,4 @@
-// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration.dns;
import java.util.List;
@@ -21,18 +21,19 @@ public interface NameService {
Record createCname(RecordName name, RecordData canonicalName);
/**
- * Create a non-standard ALIAS record pointing to given targets. Implementations of this can be expected to be
+ * Create a non-standard ALIAS record pointing to given targets. Implementations of this are expected to be
* idempotent
*
- * @param targets Targets that should be resolved by this alias. pointing to given targets.
- * @return The created records. One for each target.
+ * @param targets Targets that should be resolved by this name.
+ * @return The created records. One per target.
*/
List<Record> createAlias(RecordName name, Set<AliasTarget> targets);
/**
* Create a new TXT record containing the provided data.
* @param name Name of the created record
- * @param txtRecords TXT data values for the record, each consisting of one or more space-separated <em>double-quoted</em> strings: "string1" "string2"
+ * @param txtRecords TXT data values for the record, each consisting of one or more space-separated double-quoted
+ * strings: "string1" "string2"
* @return The created records
*/
List<Record> createTxtRecords(RecordName name, List<RecordData> txtRecords);