From 28136f1bc4ba533d68170de22f5f0bf0a012c029 Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Thu, 4 Apr 2019 14:49:35 +0200 Subject: Redirect legacy DNS names to current name Guarded by feature flag, per application. --- controller-server/pom.xml | 7 ++ .../hosted/controller/ApplicationController.java | 45 ++++++++----- .../yahoo/vespa/hosted/controller/Controller.java | 19 ++++-- .../controller/application/GlobalDnsName.java | 2 +- .../vespa/hosted/controller/ControllerTest.java | 75 ++++++++++++++-------- .../vespa/hosted/controller/ControllerTester.java | 17 +++-- .../restapi/ControllerContainerTest.java | 1 + .../src/main/java/com/yahoo/vespa/flags/Flags.java | 6 ++ 8 files changed, 117 insertions(+), 55 deletions(-) diff --git a/controller-server/pom.xml b/controller-server/pom.xml index c4cb66de3ec..f22142db727 100644 --- a/controller-server/pom.xml +++ b/controller-server/pom.xml @@ -100,6 +100,13 @@ provided + + com.yahoo.vespa + flags + ${project.version} + provided + + diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java index 71d39f97988..b6993fbc421 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java @@ -13,6 +13,9 @@ import com.yahoo.vespa.athenz.api.AthenzDomain; import com.yahoo.vespa.athenz.api.AthenzPrincipal; import com.yahoo.vespa.athenz.api.AthenzUser; import com.yahoo.vespa.curator.Lock; +import com.yahoo.vespa.flags.BooleanFlag; +import com.yahoo.vespa.flags.FetchVector; +import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.hosted.controller.api.ActivateResult; import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions; import com.yahoo.vespa.hosted.controller.api.application.v4.model.EndpointStatus; @@ -42,6 +45,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneId; import com.yahoo.vespa.hosted.controller.application.ApplicationPackage; import com.yahoo.vespa.hosted.controller.application.Deployment; import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics; +import com.yahoo.vespa.hosted.controller.application.GlobalDnsName; import com.yahoo.vespa.hosted.controller.application.JobList; import com.yahoo.vespa.hosted.controller.application.JobStatus; import com.yahoo.vespa.hosted.controller.application.JobStatus.JobRun; @@ -112,6 +116,7 @@ public class ApplicationController { private final ConfigServer configServer; private final RoutingGenerator routingGenerator; private final Clock clock; + private final BooleanFlag redirectLegacyDnsFlag; private final DeploymentTrigger deploymentTrigger; @@ -127,6 +132,7 @@ public class ApplicationController { this.configServer = configServer; this.routingGenerator = routingGenerator; this.clock = clock; + this.redirectLegacyDnsFlag = Flags.REDIRECT_LEGACY_DNS_NAMES.bindTo(controller.flagSource()); this.artifactRepository = artifactRepository; this.applicationStore = applicationStore; @@ -432,9 +438,18 @@ public class ApplicationController { application = application.with(rotation.id()); store(application); // store assigned rotation even if deployment fails - registerRotationInDns(rotation, application.get().globalDnsName(controller.system()).get().dnsName()); - registerRotationInDns(rotation, application.get().globalDnsName(controller.system()).get().secureDnsName()); - registerRotationInDns(rotation, application.get().globalDnsName(controller.system()).get().oathDnsName()); + GlobalDnsName dnsName = application.get().globalDnsName(controller.system()) + .orElseThrow(() -> new IllegalStateException("Expected rotation to be assigned")); + boolean redirectLegacyDns = redirectLegacyDnsFlag.with(FetchVector.Dimension.APPLICATION_ID, application.get().id().serializedForm()) + .value(); + registerCname(dnsName.oathDnsName(), rotation.name()); + if (redirectLegacyDns) { + registerCname(dnsName.dnsName(), dnsName.oathDnsName()); + registerCname(dnsName.secureDnsName(), dnsName.oathDnsName()); + } else { + registerCname(dnsName.dnsName(), rotation.name()); + registerCname(dnsName.secureDnsName(), rotation.name()); + } } } return application; @@ -494,24 +509,22 @@ public class ApplicationController { options.deployCurrentVersion); } - /** Register a DNS name for rotation */ - private void registerRotationInDns(Rotation rotation, String dnsName) { + /** Register a CNAME record in DNS */ + private void registerCname(String name, String targetName) { try { - - RecordData rotationName = RecordData.fqdn(rotation.name()); - List records = nameService.findRecords(Record.Type.CNAME, RecordName.from(dnsName)); + RecordData data = RecordData.fqdn(targetName); + List records = nameService.findRecords(Record.Type.CNAME, RecordName.from(name)); records.forEach(record -> { - // Ensure that the existing record points to the correct rotation - if ( ! record.data().equals(rotationName)) { - nameService.updateRecord(record, rotationName); - log.info("Updated mapping for record '" + record + "': '" + dnsName - + "' -> '" + rotation.name() + "'"); + // Ensure that the existing record points to the correct target + if ( ! record.data().equals(data)) { + log.info("Updating mapping for record '" + record + "': '" + name + + "' -> '" + data.asString() + "'"); + nameService.updateRecord(record, data); } }); - if (records.isEmpty()) { - Record record = nameService.createCname(RecordName.from(dnsName), rotationName); - log.info("Registered mapping as record '" + record + "'"); + Record record = nameService.createCname(RecordName.from(name), data); + log.info("Registered mapping as record '" + record + "'"); } } catch (RuntimeException e) { log.log(Level.WARNING, "Failed to register CNAME", e); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java index 6e59c384485..7754286ba9e 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java @@ -9,8 +9,7 @@ import com.yahoo.config.provision.CloudName; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.SystemName; import com.yahoo.vespa.curator.Lock; -import com.yahoo.vespa.hosted.controller.api.identifiers.Property; -import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId; +import com.yahoo.vespa.flags.FlagSource; import com.yahoo.vespa.hosted.controller.api.integration.BuildService; import com.yahoo.vespa.hosted.controller.api.integration.MetricsService; import com.yahoo.vespa.hosted.controller.api.integration.RunDataStore; @@ -76,6 +75,7 @@ public class Controller extends AbstractComponent { private final Chef chef; private final Mailer mailer; private final AuditLogger auditLogger; + private final FlagSource flagSource; /** * Creates a controller @@ -88,11 +88,11 @@ public class Controller extends AbstractComponent { NameService nameService, RoutingGenerator routingGenerator, Chef chef, AccessControl accessControl, ArtifactRepository artifactRepository, ApplicationStore applicationStore, TesterCloud testerCloud, - BuildService buildService, RunDataStore runDataStore, Mailer mailer) { + BuildService buildService, RunDataStore runDataStore, Mailer mailer, FlagSource flagSource) { this(curator, rotationsConfig, gitHub, zoneRegistry, configServer, metricsService, nameService, routingGenerator, chef, Clock.systemUTC(), accessControl, artifactRepository, applicationStore, testerCloud, - buildService, runDataStore, com.yahoo.net.HostName::getLocalhost, mailer); + buildService, runDataStore, com.yahoo.net.HostName::getLocalhost, mailer, flagSource); } public Controller(CuratorDb curator, RotationsConfig rotationsConfig, GitHub gitHub, @@ -102,7 +102,7 @@ public class Controller extends AbstractComponent { AccessControl accessControl, ArtifactRepository artifactRepository, ApplicationStore applicationStore, TesterCloud testerCloud, BuildService buildService, RunDataStore runDataStore, Supplier hostnameSupplier, - Mailer mailer) { + Mailer mailer, FlagSource flagSource) { this.hostnameSupplier = Objects.requireNonNull(hostnameSupplier, "HostnameSupplier cannot be null"); this.curator = Objects.requireNonNull(curator, "Curator cannot be null"); @@ -113,6 +113,7 @@ public class Controller extends AbstractComponent { this.chef = Objects.requireNonNull(chef, "Chef cannot be null"); this.clock = Objects.requireNonNull(clock, "Clock cannot be null"); this.mailer = Objects.requireNonNull(mailer, "Mailer cannot be null"); + this.flagSource = Objects.requireNonNull(flagSource, "FlagSource cannot be null"); jobController = new JobController(this, runDataStore, Objects.requireNonNull(testerCloud)); applicationController = new ApplicationController(this, curator, accessControl, @@ -123,7 +124,8 @@ public class Controller extends AbstractComponent { Objects.requireNonNull(applicationStore, "ApplicationStore cannot be null"), Objects.requireNonNull(routingGenerator, "RoutingGenerator cannot be null"), Objects.requireNonNull(buildService, "BuildService cannot be null"), - clock); + clock + ); tenantController = new TenantController(this, curator, accessControl); auditLogger = new AuditLogger(curator, clock); @@ -146,6 +148,11 @@ public class Controller extends AbstractComponent { return mailer; } + /** Provides access to the feature flags of this */ + public FlagSource flagSource() { + return flagSource; + } + public Clock clock() { return clock; } public ZoneRegistry zoneRegistry() { return zoneRegistry; } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/GlobalDnsName.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/GlobalDnsName.java index 0254bf2fd38..ae638beed5c 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/GlobalDnsName.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/GlobalDnsName.java @@ -9,7 +9,7 @@ import java.net.URI; import java.util.Objects; /** - * Represents an application's global rotation. + * Represents names for an application's global rotation. * * @author mpolden */ diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java index 1f00d99350a..bc42b672da4 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java @@ -12,13 +12,14 @@ import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.flags.Flags; +import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions; import com.yahoo.vespa.hosted.controller.api.application.v4.model.EndpointStatus; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion; import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision; import com.yahoo.vespa.hosted.controller.api.integration.dns.Record; -import com.yahoo.vespa.hosted.controller.api.integration.dns.RecordName; import com.yahoo.vespa.hosted.controller.api.integration.routing.RoutingEndpoint; import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneId; import com.yahoo.vespa.hosted.controller.application.ApplicationPackage; @@ -281,40 +282,60 @@ public class ControllerTest { .region("us-central-1") // Two deployments should result in each DNS alias being registered once .build(); - Function> findCname = (name) -> tester.controllerTester().nameService() - .findRecords(Record.Type.CNAME, - RecordName.from(name)) - .stream() - .findFirst(); - tester.deployCompletely(application, applicationPackage); assertEquals(3, tester.controllerTester().nameService().records().size()); - Optional record = findCname.apply("app1--tenant1.global.vespa.yahooapis.com"); + Optional record = tester.controllerTester().findCname("app1--tenant1.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); assertEquals("app1--tenant1.global.vespa.yahooapis.com", record.get().name().asString()); assertEquals("rotation-fqdn-01.", record.get().data().asString()); - record = findCname.apply("app1--tenant1.global.vespa.oath.cloud"); + record = tester.controllerTester().findCname("app1--tenant1.global.vespa.oath.cloud"); assertTrue(record.isPresent()); assertEquals("app1--tenant1.global.vespa.oath.cloud", record.get().name().asString()); assertEquals("rotation-fqdn-01.", record.get().data().asString()); - record = findCname.apply("app1.tenant1.global.vespa.yahooapis.com"); + record = tester.controllerTester().findCname("app1.tenant1.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); assertEquals("app1.tenant1.global.vespa.yahooapis.com", record.get().name().asString()); assertEquals("rotation-fqdn-01.", record.get().data().asString()); } @Test - public void testUpdatesExistingDnsAlias() { + public void testRedirectLegacyDnsNames() { // TODO: Remove together with Flags.REDIRECT_LEGACY_DNS_NAMES DeploymentTester tester = new DeploymentTester(); + Application application = tester.createApplication("app1", "tenant1", 1, 1L); + ApplicationPackage applicationPackage = new ApplicationPackageBuilder() + .environment(Environment.prod) + .globalServiceId("foo") + .region("us-west-1") + .region("us-central-1") + .build(); + + ((InMemoryFlagSource) tester.controller().flagSource()).withBooleanFlag(Flags.REDIRECT_LEGACY_DNS_NAMES.id(), true); + + tester.deployCompletely(application, applicationPackage); + assertEquals(3, tester.controllerTester().nameService().records().size()); + + Optional record = tester.controllerTester().findCname("app1--tenant1.global.vespa.yahooapis.com"); + assertTrue(record.isPresent()); + assertEquals("app1--tenant1.global.vespa.yahooapis.com", record.get().name().asString()); + assertEquals("app1--tenant1.global.vespa.oath.cloud.", record.get().data().asString()); - Function> findCname = (name) -> tester.controllerTester().nameService() - .findRecords(Record.Type.CNAME, - RecordName.from(name)) - .stream() - .findFirst(); + record = tester.controllerTester().findCname("app1--tenant1.global.vespa.oath.cloud"); + assertTrue(record.isPresent()); + assertEquals("app1--tenant1.global.vespa.oath.cloud", record.get().name().asString()); + assertEquals("rotation-fqdn-01.", record.get().data().asString()); + + record = tester.controllerTester().findCname("app1.tenant1.global.vespa.yahooapis.com"); + assertTrue(record.isPresent()); + assertEquals("app1.tenant1.global.vespa.yahooapis.com", record.get().name().asString()); + assertEquals("app1--tenant1.global.vespa.oath.cloud.", record.get().data().asString()); + } + + @Test + public void testUpdatesExistingDnsAlias() { + DeploymentTester tester = new DeploymentTester(); // Application 1 is deployed and deleted { @@ -329,12 +350,12 @@ public class ControllerTest { tester.deployCompletely(app1, applicationPackage); assertEquals(3, tester.controllerTester().nameService().records().size()); - Optional record = findCname.apply("app1--tenant1.global.vespa.yahooapis.com"); + Optional record = tester.controllerTester().findCname("app1--tenant1.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); assertEquals("app1--tenant1.global.vespa.yahooapis.com", record.get().name().asString()); assertEquals("rotation-fqdn-01.", record.get().data().asString()); - record = findCname.apply("app1.tenant1.global.vespa.yahooapis.com"); + record = tester.controllerTester().findCname("app1.tenant1.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); assertEquals("app1.tenant1.global.vespa.yahooapis.com", record.get().name().asString()); assertEquals("rotation-fqdn-01.", record.get().data().asString()); @@ -356,13 +377,13 @@ public class ControllerTest { } // Records remain - record = findCname.apply("app1--tenant1.global.vespa.yahooapis.com"); + record = tester.controllerTester().findCname("app1--tenant1.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); - record = findCname.apply("app1--tenant1.global.vespa.oath.cloud"); + record = tester.controllerTester().findCname("app1--tenant1.global.vespa.oath.cloud"); assertTrue(record.isPresent()); - record = findCname.apply("app1.tenant1.global.vespa.yahooapis.com"); + record = tester.controllerTester().findCname("app1.tenant1.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); } @@ -378,17 +399,17 @@ public class ControllerTest { tester.deployCompletely(app2, applicationPackage); assertEquals(6, tester.controllerTester().nameService().records().size()); - Optional record = findCname.apply("app2--tenant2.global.vespa.yahooapis.com"); + Optional record = tester.controllerTester().findCname("app2--tenant2.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); assertEquals("app2--tenant2.global.vespa.yahooapis.com", record.get().name().asString()); assertEquals("rotation-fqdn-01.", record.get().data().asString()); - record = findCname.apply("app2--tenant2.global.vespa.oath.cloud"); + record = tester.controllerTester().findCname("app2--tenant2.global.vespa.oath.cloud"); assertTrue(record.isPresent()); assertEquals("app2--tenant2.global.vespa.oath.cloud", record.get().name().asString()); assertEquals("rotation-fqdn-01.", record.get().data().asString()); - record = findCname.apply("app2.tenant2.global.vespa.yahooapis.com"); + record = tester.controllerTester().findCname("app2.tenant2.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); assertEquals("app2.tenant2.global.vespa.yahooapis.com", record.get().name().asString()); assertEquals("rotation-fqdn-01.", record.get().data().asString()); @@ -411,15 +432,15 @@ public class ControllerTest { // Existing DNS records are updated to point to the newly assigned rotation assertEquals(6, tester.controllerTester().nameService().records().size()); - Optional record = findCname.apply("app1--tenant1.global.vespa.yahooapis.com"); + Optional record = tester.controllerTester().findCname("app1--tenant1.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); assertEquals("rotation-fqdn-02.", record.get().data().asString()); - record = findCname.apply("app1--tenant1.global.vespa.oath.cloud"); + record = tester.controllerTester().findCname("app1--tenant1.global.vespa.oath.cloud"); assertTrue(record.isPresent()); assertEquals("rotation-fqdn-02.", record.get().data().asString()); - record = findCname.apply("app1.tenant1.global.vespa.yahooapis.com"); + record = tester.controllerTester().findCname("app1.tenant1.global.vespa.yahooapis.com"); assertTrue(record.isPresent()); assertEquals("rotation-fqdn-02.", record.get().data().asString()); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java index d7845e4bfa1..c18e9c46f07 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java @@ -13,6 +13,7 @@ import com.yahoo.vespa.athenz.api.AthenzUser; import com.yahoo.vespa.athenz.api.OktaAccessToken; import com.yahoo.vespa.curator.Lock; import com.yahoo.vespa.curator.mock.MockCurator; +import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions; import com.yahoo.vespa.hosted.controller.api.identifiers.Property; import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId; @@ -22,14 +23,15 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationS import com.yahoo.vespa.hosted.controller.api.integration.deployment.ArtifactRepository; import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; import com.yahoo.vespa.hosted.controller.api.integration.dns.MemoryNameService; -import com.yahoo.vespa.hosted.controller.api.integration.entity.MemoryEntityService; +import com.yahoo.vespa.hosted.controller.api.integration.dns.Record; +import com.yahoo.vespa.hosted.controller.api.integration.dns.RecordName; import com.yahoo.vespa.hosted.controller.api.integration.github.GitHubMock; import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact; import com.yahoo.vespa.hosted.controller.api.integration.organization.MockContactRetriever; import com.yahoo.vespa.hosted.controller.api.integration.organization.MockIssueHandler; -import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer; import com.yahoo.vespa.hosted.controller.api.integration.routing.RoutingGenerator; import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockBuildService; +import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer; import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockRunDataStore; import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockTesterCloud; import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneId; @@ -43,11 +45,11 @@ import com.yahoo.vespa.hosted.controller.integration.ConfigServerMock; import com.yahoo.vespa.hosted.controller.integration.MetricsServiceMock; import com.yahoo.vespa.hosted.controller.integration.RoutingGeneratorMock; import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock; -import com.yahoo.vespa.hosted.controller.security.AthenzCredentials; -import com.yahoo.vespa.hosted.controller.security.AthenzTenantSpec; import com.yahoo.vespa.hosted.controller.persistence.ApplicationSerializer; import com.yahoo.vespa.hosted.controller.persistence.CuratorDb; import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb; +import com.yahoo.vespa.hosted.controller.security.AthenzCredentials; +import com.yahoo.vespa.hosted.controller.security.AthenzTenantSpec; import com.yahoo.vespa.hosted.controller.security.Credentials; import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.Tenant; @@ -188,6 +190,10 @@ public final class ControllerTester { return contactRetriever; } + public Optional findCname(String name) { + return nameService.findRecords(Record.Type.CNAME, RecordName.from(name)).stream().findFirst(); + } + /** Create a new controller instance. Useful to verify that controller state is rebuilt from persistence */ public final void createNewController() { controller = createController(curator, rotationsConfig, configServer, clock, gitHub, zoneRegistry, athenzDb, @@ -345,7 +351,8 @@ public final class ControllerTester { buildService, new MockRunDataStore(), () -> "test-controller", - new MockMailer()); + new MockMailer(), + new InMemoryFlagSource()); // Calculate initial versions controller.updateVersionStatus(VersionStatus.compute(controller)); return controller; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java index 331a6ba9ac8..3c5466f22be 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java @@ -63,6 +63,7 @@ public class ControllerContainerTest { " http://localhost\n" + " \n" + " \n" + + " \n" + " \n" + " \n" + " \n" + diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java index c4c3021d607..e9e886f73e9 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java @@ -137,6 +137,12 @@ public class Flags { "Takes effect at redeployment", APPLICATION_ID); + public static final UnboundBooleanFlag REDIRECT_LEGACY_DNS_NAMES = defineFeatureFlag( + "redirect-legacy-dns", false, + "Redirect legacy DNS names to the main DNS name", + "Takes effect on deployment through controller", + APPLICATION_ID); + /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static UnboundBooleanFlag defineFeatureFlag(String flagId, boolean defaultValue, String description, String modificationEffect, FetchVector.Dimension... dimensions) { -- cgit v1.2.3