From 38ab8f2531bbe4b11b4be80d40d8fd04eb3b0dd8 Mon Sep 17 00:00:00 2001 From: Valerij Fredriksen Date: Wed, 5 Oct 2022 14:32:34 +0200 Subject: Add ipAddress to RoutingPolicy --- .../controller/deployment/InternalStepRunner.java | 14 +++-- .../persistence/RoutingPolicySerializer.java | 7 ++- .../hosted/controller/routing/RoutingPolicies.java | 45 +++++++++++------ .../hosted/controller/routing/RoutingPolicy.java | 19 +++++-- .../controller/deployment/DeploymentContext.java | 3 +- .../controller/integration/ConfigServerMock.java | 1 + .../persistence/RoutingPolicySerializerTest.java | 16 ++++-- .../controller/routing/RoutingPoliciesTest.java | 59 +++++++++++++++++----- 8 files changed, 122 insertions(+), 42 deletions(-) (limited to 'controller-server') diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java index 965f1b09819..4d7b84be65e 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.deployment; import ai.vespa.http.DomainName; +import com.google.common.net.InetAddresses; import com.yahoo.component.Version; import com.yahoo.config.application.api.DeploymentSpec; import com.yahoo.config.application.api.Notifications; @@ -510,18 +511,25 @@ public class InternalStepRunner implements StepRunner { if (context.routingMethod() == RoutingMethod.exclusive) { RoutingPolicy policy = context.routingPolicy(ClusterSpec.Id.from(endpoint.name())) .orElseThrow(() -> new IllegalStateException(endpoint + " has no matching policy")); + if (policy.ipAddress().isPresent()) { + if (ipAddress.equals(policy.ipAddress().map(InetAddresses::forString))) continue; + logger.log(INFO, "IP address of '" + endpointName + "' (" + + ipAddress.map(InetAddresses::toAddrString).get() + ") and load balancer " + + "' (" + policy.ipAddress().orElseThrow() + ") are not equal"); + return false; + } var cNameValue = controller.jobController().cloud().resolveCname(endpointName); - if ( ! cNameValue.map(policy.canonicalName()::equals).orElse(false)) { + if ( ! cNameValue.map(policy.canonicalName().get()::equals).orElse(false)) { logger.log(INFO, "CNAME '" + endpointName + "' points at " + cNameValue.map(name -> "'" + name + "'").orElse("nothing") + " but should point at load balancer '" + policy.canonicalName() + "'"); return false; } - var loadBalancerAddress = controller.jobController().cloud().resolveHostName(policy.canonicalName()); + var loadBalancerAddress = controller.jobController().cloud().resolveHostName(policy.canonicalName().get()); if ( ! loadBalancerAddress.equals(ipAddress)) { logger.log(INFO, "IP address of CNAME '" + endpointName + "' (" + ipAddress.get() + ") and load balancer '" + - policy.canonicalName() + "' (" + loadBalancerAddress.orElse(null) + ") are not equal"); + policy.canonicalName().get() + "' (" + loadBalancerAddress.orElse(null) + ") are not equal"); return false; } } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RoutingPolicySerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RoutingPolicySerializer.java index 72c16ae0110..4d759056dfc 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RoutingPolicySerializer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/RoutingPolicySerializer.java @@ -40,6 +40,7 @@ public class RoutingPolicySerializer { private static final String routingPoliciesField = "routingPolicies"; private static final String clusterField = "cluster"; private static final String canonicalNameField = "canonicalName"; + private static final String ipAddressField = "ipAddress"; private static final String zoneField = "zone"; private static final String dnsZoneField = "dnsZone"; private static final String instanceEndpointsField = "rotations"; @@ -58,7 +59,8 @@ public class RoutingPolicySerializer { var policyObject = policyArray.addObject(); policyObject.setString(clusterField, policy.id().cluster().value()); policyObject.setString(zoneField, policy.id().zone().value()); - policyObject.setString(canonicalNameField, policy.canonicalName().value()); + policy.canonicalName().map(DomainName::value).ifPresent(name -> policyObject.setString(canonicalNameField, name)); + policy.ipAddress().ifPresent(ipAddress -> policyObject.setString(ipAddressField, ipAddress)); policy.dnsZone().ifPresent(dnsZone -> policyObject.setString(dnsZoneField, dnsZone)); var instanceEndpointsArray = policyObject.setArray(instanceEndpointsField); policy.instanceEndpoints().forEach(endpointId -> instanceEndpointsArray.addString(endpointId.id())); @@ -83,7 +85,8 @@ public class RoutingPolicySerializer { ClusterSpec.Id.from(inspect.field(clusterField).asString()), ZoneId.from(inspect.field(zoneField).asString())); policies.add(new RoutingPolicy(id, - DomainName.of(inspect.field(canonicalNameField).asString()), + SlimeUtils.optionalString(inspect.field(canonicalNameField)).map(DomainName::of), + SlimeUtils.optionalString(inspect.field(ipAddressField)), SlimeUtils.optionalString(inspect.field(dnsZoneField)), instanceEndpoints, applicationEndpoints, diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java index 683b16c803c..f76d04c9e1d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java @@ -205,20 +205,24 @@ public class RoutingPolicies { for (var policy : policies) { if (policy.dnsZone().isEmpty()) continue; if (controller.zoneRegistry().routingMethod(policy.id().zone()) != RoutingMethod.exclusive) continue; - Endpoint regionEndpoint = policy.regionEndpointIn(controller.system(), RoutingMethod.exclusive); + Endpoint endpoint = policy.regionEndpointIn(controller.system(), RoutingMethod.exclusive); var zonePolicy = db.readZoneRoutingPolicy(policy.id().zone()); long weight = 1; if (isConfiguredOut(zonePolicy, policy, inactiveZones)) { weight = 0; // A record with 0 weight will not receive traffic. If all records within a group have 0 // weight, traffic is routed to all records with equal probability. } - var weightedTarget = new WeightedAliasTarget(policy.canonicalName(), policy.dnsZone().get(), - policy.id().zone(), weight); - endpoints.computeIfAbsent(regionEndpoint, (k) -> new RegionEndpoint(new LatencyAliasTarget(DomainName.of(regionEndpoint.dnsName()), - policy.dnsZone().get(), - policy.id().zone()))) - .zoneTargets() - .add(weightedTarget); + + RegionEndpoint regionEndpoint = endpoints.computeIfAbsent(endpoint, (k) -> new RegionEndpoint( + new LatencyAliasTarget(DomainName.of(endpoint.dnsName()), policy.dnsZone().get(), policy.id().zone()))); + + if (policy.canonicalName().isPresent()) { + var weightedTarget = new WeightedAliasTarget( + policy.canonicalName().get(), policy.dnsZone().get(), policy.id().zone(), weight); + regionEndpoint.zoneTargets().add(weightedTarget); + } else { + // TODO (freva): Add direct weighted record + } } return endpoints.values(); } @@ -250,8 +254,9 @@ public class RoutingPolicies { for (var target : endpoint.targets()) { if (!policy.appliesTo(target.deployment())) continue; if (policy.dnsZone().isEmpty()) continue; // Does not support ALIAS records + if (policy.canonicalName().isEmpty()) continue; // TODO (freva): Handle DIRECT records ZoneRoutingPolicy zonePolicy = db.readZoneRoutingPolicy(policy.id().zone()); - WeightedAliasTarget weightedAliasTarget = new WeightedAliasTarget(policy.canonicalName(), policy.dnsZone().get(), + WeightedAliasTarget weightedAliasTarget = new WeightedAliasTarget(policy.canonicalName().get(), policy.dnsZone().get(), target.deployment().zoneId(), target.weight()); Set activeTargets = targetsByEndpoint.computeIfAbsent(endpoint, (k) -> new LinkedHashSet<>()); Set inactiveTargets = inactiveTargetsByEndpoint.computeIfAbsent(endpoint, (k) -> new LinkedHashSet<>()); @@ -309,10 +314,10 @@ public class RoutingPolicies { private RoutingPolicyList storePoliciesOf(LoadBalancerAllocation allocation, RoutingPolicyList instancePolicies, @SuppressWarnings("unused") Mutex lock) { Map policies = new LinkedHashMap<>(instancePolicies.asMap()); for (LoadBalancer loadBalancer : allocation.loadBalancers) { - if (loadBalancer.hostname().isEmpty()) continue; + if (loadBalancer.hostname().isEmpty() && loadBalancer.ipAddress().isEmpty()) continue; var policyId = new RoutingPolicyId(loadBalancer.application(), loadBalancer.cluster(), allocation.deployment.zoneId()); var existingPolicy = policies.get(policyId); - var newPolicy = new RoutingPolicy(policyId, loadBalancer.hostname().get(), loadBalancer.dnsZone(), + var newPolicy = new RoutingPolicy(policyId, loadBalancer.hostname(), loadBalancer.ipAddress(), loadBalancer.dnsZone(), allocation.instanceEndpointsOf(loadBalancer), allocation.applicationEndpointsOf(loadBalancer), new RoutingPolicy.Status(isActive(loadBalancer), RoutingStatus.DEFAULT)); @@ -332,7 +337,9 @@ public class RoutingPolicies { private void updateZoneDnsOf(RoutingPolicy policy) { for (var endpoint : policy.zoneEndpointsIn(controller.system(), RoutingMethod.exclusive, controller.zoneRegistry())) { var name = RecordName.from(endpoint.dnsName()); - var record = new Record(Record.Type.CNAME, name, RecordData.fqdn(policy.canonicalName().value())); + var record = policy.canonicalName().isPresent() ? + new Record(Record.Type.CNAME, name, RecordData.fqdn(policy.canonicalName().get().value())) : + new Record(Record.Type.A, name, RecordData.from(policy.ipAddress().orElseThrow())); nameServiceForwarderIn(policy.id().zone()).createRecord(record, Priority.normal); } } @@ -393,10 +400,16 @@ public class RoutingPolicies { for (var policy : policies) { if (!policy.appliesTo(allocation.deployment)) continue; NameServiceForwarder forwarder = nameServiceForwarderIn(policy.id().zone()); - endpoints.forEach(endpoint -> forwarder.removeRecords(Record.Type.ALIAS, - RecordName.from(endpoint.dnsName()), - RecordData.fqdn(policy.canonicalName().value()), - Priority.normal)); + for (Endpoint endpoint : endpoints) { + if (policy.canonicalName().isPresent()) { + forwarder.removeRecords(Record.Type.ALIAS, + RecordName.from(endpoint.dnsName()), + RecordData.fqdn(policy.canonicalName().get().value()), + Priority.normal); + } else { + // TODO (freva): Remove DIRECT records + } + } } } } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java index 585cda65e66..04c32590a4c 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java @@ -24,21 +24,27 @@ import java.util.Set; * @author mpolden */ public record RoutingPolicy(RoutingPolicyId id, - DomainName canonicalName, + Optional canonicalName, + Optional ipAddress, Optional dnsZone, Set instanceEndpoints, Set applicationEndpoints, Status status) { /** DO NOT USE. Public for serialization purposes */ - public RoutingPolicy(RoutingPolicyId id, DomainName canonicalName, Optional dnsZone, + public RoutingPolicy(RoutingPolicyId id, Optional canonicalName, Optional ipAddress, Optional dnsZone, Set instanceEndpoints, Set applicationEndpoints, Status status) { this.id = Objects.requireNonNull(id, "id must be non-null"); this.canonicalName = Objects.requireNonNull(canonicalName, "canonicalName must be non-null"); + this.ipAddress = Objects.requireNonNull(ipAddress, "ipAddress must be non-null"); this.dnsZone = Objects.requireNonNull(dnsZone, "dnsZone must be non-null"); this.instanceEndpoints = ImmutableSortedSet.copyOf(Objects.requireNonNull(instanceEndpoints, "instanceEndpoints must be non-null")); this.applicationEndpoints = ImmutableSortedSet.copyOf(Objects.requireNonNull(applicationEndpoints, "applicationEndpoints must be non-null")); this.status = Objects.requireNonNull(status, "status must be non-null"); + + if (canonicalName.isEmpty() == ipAddress.isEmpty()) + throw new IllegalArgumentException("Exactly 1 of canonicalName=%s and ipAddress=%s must be set".formatted( + canonicalName.map(DomainName::value).orElse(""), ipAddress.orElse(""))); } /** The ID of this */ @@ -47,10 +53,15 @@ public record RoutingPolicy(RoutingPolicyId id, } /** The canonical name for the load balancer this applies to (rhs of a CNAME or ALIAS record) */ - public DomainName canonicalName() { + public Optional canonicalName() { return canonicalName; } + /** The IP address for the load balancer this applies to (rhs of an A or DIRECT record) */ + public Optional ipAddress() { + return ipAddress; + } + /** DNS zone for the load balancer this applies to, if any. Used when creating ALIAS records. */ public Optional dnsZone() { return dnsZone; @@ -79,7 +90,7 @@ public record RoutingPolicy(RoutingPolicyId id, /** Returns a copy of this with status set to given status */ public RoutingPolicy with(Status status) { - return new RoutingPolicy(id, canonicalName, dnsZone, instanceEndpoints, applicationEndpoints, status); + return new RoutingPolicy(id, canonicalName, ipAddress, dnsZone, instanceEndpoints, applicationEndpoints, status); } /** Returns the zone endpoints of this */ diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java index bd43a9dafbc..b38bdbb1eaf 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java @@ -271,7 +271,8 @@ public class DeploymentContext { var clusterId = "default-inactive"; var id = new RoutingPolicyId(instanceId, Id.from(clusterId), zone); var policies = new LinkedHashMap<>(tester.controller().routing().policies().read(instanceId).asMap()); - policies.put(id, new RoutingPolicy(id, HostName.of("lb-host"), + policies.put(id, new RoutingPolicy(id, Optional.of(HostName.of("lb-host")), + Optional.empty(), Optional.empty(), Set.of(EndpointId.of("default")), Set.of(), diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java index d7f83979054..5a8d6a45e43 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ConfigServerMock.java @@ -402,6 +402,7 @@ public class ConfigServerMock extends AbstractComponent implements ConfigServer id.applicationId(), cluster, Optional.of(HostName.of("lb-0--" + id.applicationId().toFullString() + "--" + id.zoneId().toString())), + Optional.empty(), LoadBalancer.State.active, Optional.of("dns-zone-1")))); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RoutingPolicySerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RoutingPolicySerializerTest.java index 3df459513d7..6285c5c4aac 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RoutingPolicySerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/RoutingPolicySerializerTest.java @@ -38,20 +38,29 @@ public class RoutingPolicySerializerTest { ClusterSpec.Id.from("my-cluster2"), ZoneId.from("prod", "us-north-2")); var policies = List.of(new RoutingPolicy(id1, - HostName.of("long-and-ugly-name"), + Optional.of(HostName.of("long-and-ugly-name")), + Optional.empty(), Optional.of("zone1"), instanceEndpoints, applicationEndpoints, new RoutingPolicy.Status(true, RoutingStatus.DEFAULT)), new RoutingPolicy(id2, - HostName.of("long-and-ugly-name-2"), + Optional.of(HostName.of("long-and-ugly-name-2")), + Optional.empty(), Optional.empty(), instanceEndpoints, Set.of(), new RoutingPolicy.Status(false, new RoutingStatus(RoutingStatus.Value.out, RoutingStatus.Agent.tenant, - Instant.ofEpochSecond(123))))); + Instant.ofEpochSecond(123)))), + new RoutingPolicy(id1, + Optional.empty(), + Optional.of("127.0.0.1"), + Optional.of("zone2"), + instanceEndpoints, + applicationEndpoints, + new RoutingPolicy.Status(true, RoutingStatus.DEFAULT))); var serialized = serializer.fromSlime(owner, serializer.toSlime(policies)); assertEquals(policies.size(), serialized.size()); for (Iterator it1 = policies.iterator(), it2 = serialized.iterator(); it1.hasNext(); ) { @@ -59,6 +68,7 @@ public class RoutingPolicySerializerTest { var actual = it2.next(); assertEquals(expected.id(), actual.id()); assertEquals(expected.canonicalName(), actual.canonicalName()); + assertEquals(expected.ipAddress(), actual.ipAddress()); assertEquals(expected.dnsZone(), actual.dnsZone()); assertEquals(expected.instanceEndpoints(), actual.instanceEndpoints()); assertEquals(expected.applicationEndpoints(), actual.applicationEndpoints()); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java index c5d74e0b01d..2761c736e11 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java @@ -1,6 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.routing; +import ai.vespa.http.DomainName; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; import com.yahoo.config.application.api.DeploymentSpec; @@ -350,6 +351,32 @@ public class RoutingPoliciesTest { .allMatch(List::isEmpty), "No rotations assigned"); } + @Test + void cross_cloud_policies() { + var tester = new RoutingPoliciesTester(SystemName.Public); + var context = tester.newDeploymentContext("tenant1", "app1", "default"); + var zone1 = ZoneId.from("prod", "aws-us-east-1c"); + var zone2 = ZoneId.from("prod", "gcp-us-south1-b"); + tester.provisionLoadBalancers(1, context.instanceId(), zone1, zone2); + + var applicationPackage = applicationPackageBuilder() + .region(zone1.region().value()) + .region(zone2.region().value()) + .endpoint("r0", "c0") + .trustDefaultCertificate() + .build(); + context.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.prod).deploy(); + + List expectedRecords = List.of("c0.app1.tenant1.aws-us-east-1c.z.vespa-app.cloud", + "c0.app1.tenant1.gcp-us-south1-b.z.vespa-app.cloud", + "c0.app1.tenant1.aws-us-east-1.w.vespa-app.cloud", + "r0.app1.tenant1.g.vespa-app.cloud"); + assertEquals(Set.copyOf(expectedRecords), tester.recordNames()); + + assertEquals(List.of("lb-0--tenant1.app1.default--prod.aws-us-east-1c."), tester.recordDataOf(Record.Type.CNAME, expectedRecords.get(0))); + assertEquals(List.of("10.0.0.0"), tester.recordDataOf(Record.Type.A, expectedRecords.get(1))); + } + @Test void global_routing_policies_in_public() { var tester = new RoutingPoliciesTester(SystemName.Public); @@ -359,8 +386,8 @@ public class RoutingPoliciesTest { ZoneId zone2 = prodZones.get(1); var applicationPackage = applicationPackageBuilder() - .region(zone1.region().value()) - .region(zone2.region().value()) + .region(zone1.region()) + .region(zone2.region()) .endpoint("default", "default") .trustDefaultCertificate() .build(); @@ -452,6 +479,7 @@ public class RoutingPoliciesTest { context.instanceId(), ClusterSpec.Id.from("c0"), Optional.of(newHostname), + Optional.empty(), LoadBalancer.State.active, Optional.of("dns-zone-1")); tester.controllerTester().configServer().putLoadBalancers(zone1, List.of(loadBalancer)); @@ -461,8 +489,8 @@ public class RoutingPoliciesTest { assertEquals(expectedRecords, tester.recordNames()); assertEquals(1, tester.policiesOf(context.instanceId()).size()); assertEquals(newHostname.value() + ".", - tester.cnameDataOf(expectedRecords.iterator().next()).get(0), - "CNAME points to current load blancer"); + tester.recordDataOf(Record.Type.CNAME, expectedRecords.iterator().next()).get(0), + "CNAME points to current load balancer"); } @Test @@ -836,20 +864,24 @@ public class RoutingPoliciesTest { private static List createLoadBalancers(ZoneId zone, ApplicationId application, boolean shared, int count) { List loadBalancers = new ArrayList<>(); for (int i = 0; i < count; i++) { - HostName lbHostname; - if (shared) { - lbHostname = HostName.of("shared-lb--" + zone.value()); + Optional lbHostname; + Optional ipAddress; + if (zone.region().value().startsWith("gcp-")) { + lbHostname = Optional.empty(); + ipAddress = Optional.of("10.0.0." + i); } else { - lbHostname = HostName.of("lb-" + i + "--" + application.toFullString() + - "--" + zone.value()); + String hostname = shared ? "shared-lb--" + zone.value() : "lb-" + i + "--" + application.toFullString() + "--" + zone.value(); + lbHostname = Optional.of(DomainName.of(hostname)); + ipAddress = Optional.empty(); } loadBalancers.add( new LoadBalancer("LB-" + i + "-Z-" + zone.value(), application, ClusterSpec.Id.from("c" + i), - Optional.of(lbHostname), + lbHostname, + ipAddress, LoadBalancer.State.active, - Optional.of("dns-zone-1"))); + Optional.of("dns-zone-1").filter(__ -> lbHostname.isPresent()))); } return loadBalancers; } @@ -858,6 +890,7 @@ public class RoutingPoliciesTest { var sharedRegion = RegionName.from("aws-us-east-1c"); return List.of(ZoneId.from(Environment.prod, sharedRegion), ZoneId.from(Environment.prod, RegionName.from("aws-eu-west-1a")), + ZoneId.from(Environment.prod, RegionName.from("gcp-us-south1-b")), ZoneId.from(Environment.staging, RegionName.from("us-east-3")), ZoneId.from(Environment.test, RegionName.from("us-east-1"))); } @@ -936,8 +969,8 @@ public class RoutingPoliciesTest { .collect(Collectors.toSet()); } - private List cnameDataOf(String name) { - return tester.controllerTester().nameService().findRecords(Record.Type.CNAME, RecordName.from(name)).stream() + private List recordDataOf(Record.Type type, String name) { + return tester.controllerTester().nameService().findRecords(type, RecordName.from(name)).stream() .map(Record::data) .map(RecordData::asString) .collect(Collectors.toList()); -- cgit v1.2.3