diff options
author | Martin Polden <mpolden@mpolden.no> | 2020-06-24 13:35:32 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2020-06-24 14:41:35 +0200 |
commit | 0c3080ce98166a121d94775d2da9fdc63b737be8 (patch) | |
tree | 8ae1747586597ad5d727baa0d6d40ef057fa9fb6 /controller-api | |
parent | c2b57fddcbc9beb3b866d579c6cd68a68590651e (diff) |
Support multiple types of alias targets
Diffstat (limited to 'controller-api')
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); |