diff options
author | Martin Polden <mpolden@mpolden.no> | 2020-06-25 11:01:58 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2020-06-25 11:08:23 +0200 |
commit | defdb6949e198ffa611cecc446a2966a7ca249a0 (patch) | |
tree | e7dcbd0c304c5e9045f28af8b88c5dfb7436f4fd /controller-api | |
parent | a979e89b4c4f96c2ddcbd03509b84cb6e0d6812c (diff) |
Add weighted alias type
Diffstat (limited to 'controller-api')
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) { + } + } + } + +} |