summaryrefslogtreecommitdiffstats
path: root/controller-api
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2020-06-25 11:01:58 +0200
committerMartin Polden <mpolden@mpolden.no>2020-06-25 11:08:23 +0200
commitdefdb6949e198ffa611cecc446a2966a7ca249a0 (patch)
treee7dcbd0c304c5e9045f28af8b88c5dfb7436f4fd /controller-api
parenta979e89b4c4f96c2ddcbd03509b84cb6e0d6812c (diff)
Add weighted alias type
Diffstat (limited to 'controller-api')
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTarget.java7
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/WeightedAliasTarget.java64
-rw-r--r--controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTargetTest.java39
3 files changed, 109 insertions, 1 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 a5436bc3fc1..41723dbdea6 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
@@ -57,7 +57,12 @@ public abstract class AliasTarget {
/** Unpack target from given record data */
public static AliasTarget unpack(RecordData data) {
- return LatencyAliasTarget.unpack(data);
+ String[] parts = data.asString().split("/");
+ switch (parts[0]) {
+ case "latency": return LatencyAliasTarget.unpack(data);
+ case "weighted": return WeightedAliasTarget.unpack(data);
+ }
+ throw new IllegalArgumentException("Unknown alias type '" + parts[0] + "'");
}
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/WeightedAliasTarget.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/WeightedAliasTarget.java
new file mode 100644
index 00000000000..9d741cb2dbc
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/WeightedAliasTarget.java
@@ -0,0 +1,64 @@
+// 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} where is requests are answered based on the weight assigned to the
+ * record, as a proportion of the total weight for all records having the same DNS name.
+ *
+ * The portion of received traffic is calculated as follows: (record weight / sum of the weights of all records).
+ *
+ * @author mpolden
+ */
+public class WeightedAliasTarget extends AliasTarget {
+
+ private final long weight;
+
+ public WeightedAliasTarget(HostName name, String dnsZone, ZoneId zone, long weight) {
+ super(name, dnsZone, zone.value());
+ this.weight = weight;
+ }
+
+ /** The weight of this target */
+ public long weight() {
+ return weight;
+ }
+
+ @Override
+ public RecordData pack() {
+ return RecordData.from("weighted/" + name().value() + "/" + dnsZone() + "/" + id() + "/" + weight);
+ }
+
+ @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;
+ WeightedAliasTarget that = (WeightedAliasTarget) o;
+ return weight == that.weight;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), weight);
+ }
+
+ /** Unpack weighted alias from given record data */
+ public static WeightedAliasTarget unpack(RecordData data) {
+ var parts = data.asString().split("/");
+ if (parts.length != 5) {
+ throw new IllegalArgumentException("Expected data to be on format type/name/DNS-zone/zone-id/weight, " +
+ "but got " + data.asString());
+ }
+ if (!"weighted".equals(parts[0])) {
+ throw new IllegalArgumentException("Unexpected type '" + parts[0] + "'");
+ }
+ return new WeightedAliasTarget(HostName.from(parts[1]), parts[2], ZoneId.from(parts[3]),
+ Long.parseLong(parts[4]));
+ }
+
+}
diff --git a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTargetTest.java b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTargetTest.java
new file mode 100644
index 00000000000..7169222fe26
--- /dev/null
+++ b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/dns/AliasTargetTest.java
@@ -0,0 +1,39 @@
+// 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 org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author mpolden
+ */
+public class AliasTargetTest {
+
+ @Test
+ public void packing() {
+ List<AliasTarget> tests = List.of(
+ new LatencyAliasTarget(HostName.from("foo.example.com"), "dns-zone-1", ZoneId.from("prod.us-north-1")),
+ new WeightedAliasTarget(HostName.from("bar.example.com"), "dns-zone-2", ZoneId.from("prod.us-north-2"), 50)
+ );
+ for (var target : tests) {
+ AliasTarget unpacked = AliasTarget.unpack(target.pack());
+ assertEquals(target, unpacked);
+ }
+
+ List<RecordData> invalidData = List.of(RecordData.from(""), RecordData.from("foobar"));
+ for (var data : invalidData) {
+ try {
+ AliasTarget.unpack(data);
+ fail("Expected exception");
+ } catch (IllegalArgumentException ignored) {
+ }
+ }
+ }
+
+}