From 559eb831701e77a8c88944c4f1dcc52f2e906a8e Mon Sep 17 00:00:00 2001 From: Øyvind Grønnesby Date: Fri, 14 Jun 2019 15:56:34 +0200 Subject: Get ContainerEndpoints into DeployState --- .../main/java/com/yahoo/config/model/deploy/DeployState.java | 11 +++++++++++ .../main/java/com/yahoo/vespa/model/VespaModelFactory.java | 1 + 2 files changed, 12 insertions(+) (limited to 'config-model') diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java index c19865fafc9..44fe45dc160 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java @@ -11,6 +11,7 @@ import com.yahoo.config.application.api.FileRegistry; import com.yahoo.config.application.api.UnparsedConfigDefinition; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.config.model.api.ConfigDefinitionRepo; +import com.yahoo.config.model.api.ContainerEndpoint; import com.yahoo.config.model.api.HostProvisioner; import com.yahoo.config.model.api.Model; import com.yahoo.config.model.api.ModelContext; @@ -67,6 +68,7 @@ public class DeployState implements ConfigDefinitionStore { private final ModelContext.Properties properties; private final Version vespaVersion; private final Set rotations; + private final Set endpoints; private final Zone zone; private final QueryProfiles queryProfiles; private final SemanticRules semanticRules; @@ -96,6 +98,7 @@ public class DeployState implements ConfigDefinitionStore { Optional configDefinitionRepo, java.util.Optional previousModel, Set rotations, + Set endpoints, Collection modelImporters, Zone zone, QueryProfiles queryProfiles, @@ -115,6 +118,7 @@ public class DeployState implements ConfigDefinitionStore { this.permanentApplicationPackage = permanentApplicationPackage; this.configDefinitionRepo = configDefinitionRepo; this.rotations = rotations; + this.endpoints = endpoints; this.zone = zone; this.queryProfiles = queryProfiles; // TODO: Remove this by seeing how pagetemplates are propagated this.semanticRules = semanticRules; // TODO: Remove this by seeing how pagetemplates are propagated @@ -260,6 +264,7 @@ public class DeployState implements ConfigDefinitionStore { private Optional configDefinitionRepo = Optional.empty(); private Optional previousModel = Optional.empty(); private Set rotations = new HashSet<>(); + private Set endpoints = Set.of(); private Collection modelImporters = Collections.emptyList(); private Zone zone = Zone.defaultZone(); private Instant now = Instant.now(); @@ -315,6 +320,11 @@ public class DeployState implements ConfigDefinitionStore { return this; } + public Builder endpoints(Set endpoints) { + this.endpoints = endpoints; + return this; + } + public Builder modelImporters(Collection modelImporters) { this.modelImporters = modelImporters; return this; @@ -356,6 +366,7 @@ public class DeployState implements ConfigDefinitionStore { configDefinitionRepo, previousModel, rotations, + endpoints, modelImporters, zone, queryProfiles, diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java index af6400023cc..f69330eb196 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java @@ -139,6 +139,7 @@ public class VespaModelFactory implements ModelFactory { .vespaVersion(version()) .modelHostProvisioner(createHostProvisioner(modelContext)) .rotations(modelContext.properties().rotations()) + .endpoints(modelContext.properties().endpoints()) .modelImporters(modelImporters) .zone(zone) .now(clock.instant()) -- cgit v1.2.3 From 1a205c24bd278e0975907dbb7a5de2e8089577e9 Mon Sep 17 00:00:00 2001 From: Øyvind Grønnesby Date: Tue, 18 Jun 2019 09:38:50 +0200 Subject: Add ContainerEndpoint info to LbServices --- .../com/yahoo/config/model/deploy/DeployState.java | 6 +- .../yahoo/config/model/deploy/TestProperties.java | 4 + .../model/container/xml/ContainerModelBuilder.java | 29 +++++-- .../server/model/LbServicesProducerTest.java | 96 +++++++++++++++++----- 4 files changed, 108 insertions(+), 27 deletions(-) (limited to 'config-model') diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java index 44fe45dc160..21a8297910f 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java @@ -118,7 +118,7 @@ public class DeployState implements ConfigDefinitionStore { this.permanentApplicationPackage = permanentApplicationPackage; this.configDefinitionRepo = configDefinitionRepo; this.rotations = rotations; - this.endpoints = endpoints; + this.endpoints = Set.copyOf(endpoints); this.zone = zone; this.queryProfiles = queryProfiles; // TODO: Remove this by seeing how pagetemplates are propagated this.semanticRules = semanticRules; // TODO: Remove this by seeing how pagetemplates are propagated @@ -238,6 +238,10 @@ public class DeployState implements ConfigDefinitionStore { return this.rotations; // todo: consider returning a copy or immutable view } + public Set getEndpoints() { + return endpoints; + } + /** Returns the zone in which this is currently running */ public Zone zone() { return zone; } diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java index 4b35af53154..650bd06beda 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java @@ -3,6 +3,7 @@ package com.yahoo.config.model.deploy; import com.google.common.collect.ImmutableList; import com.yahoo.config.model.api.ConfigServerSpec; +import com.yahoo.config.model.api.ContainerEndpoint; import com.yahoo.config.model.api.ModelContext; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.HostName; @@ -31,6 +32,7 @@ public class TestProperties implements ModelContext.Properties { private boolean hostedVespa = false; private Zone zone; private Set rotations; + private Set endpoints; private boolean isBootstrap = false; private boolean isFirstTimeDeployment = false; private boolean useDedicatedNodeForLogserver = false; @@ -49,6 +51,8 @@ public class TestProperties implements ModelContext.Properties { @Override public boolean hostedVespa() { return hostedVespa; } @Override public Zone zone() { return zone; } @Override public Set rotations() { return rotations; } + @Override public Set endpoints() { return endpoints; } + @Override public boolean isBootstrap() { return isBootstrap; } @Override public boolean isFirstTimeDeployment() { return isFirstTimeDeployment; } @Override public boolean useAdaptiveDispatch() { return useAdaptiveDispatch; } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java index 642f882f3ed..f68ddecad9d 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java @@ -9,6 +9,7 @@ import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.application.api.DeploymentSpec; import com.yahoo.config.model.ConfigModelContext; import com.yahoo.config.model.api.ConfigServerSpec; +import com.yahoo.config.model.api.ContainerEndpoint; import com.yahoo.config.model.application.provider.IncludeDirs; import com.yahoo.config.model.builder.xml.ConfigModelBuilder; import com.yahoo.config.model.builder.xml.ConfigModelId; @@ -72,6 +73,7 @@ import org.w3c.dom.Node; import java.net.URI; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -212,13 +214,13 @@ public class ContainerModelBuilder extends ConfigModelBuilder { context.getDeployState().getProperties().athenzDnsSuffix(), context.getDeployState().zone(), deploymentSpec); - addRotationProperties(cluster, context.getDeployState().zone(), context.getDeployState().getRotations(), deploymentSpec); + addRotationProperties(cluster, context.getDeployState().zone(), context.getDeployState().getRotations(), context.getDeployState().getEndpoints(), deploymentSpec); }); } - private void addRotationProperties(ApplicationContainerCluster cluster, Zone zone, Set rotations, DeploymentSpec spec) { + private void addRotationProperties(ApplicationContainerCluster cluster, Zone zone, Set rotations, Set endpoints, DeploymentSpec spec) { cluster.getContainers().forEach(container -> { - setRotations(container, rotations, spec.globalServiceId(), cluster.getName()); + setRotations(container, rotations, endpoints, spec.globalServiceId(), cluster.getName()); container.setProp("activeRotation", Boolean.toString(zoneHasActiveRotation(zone, spec))); }); } @@ -229,13 +231,30 @@ public class ContainerModelBuilder extends ConfigModelBuilder { declaredZone.active()); } - private void setRotations(Container container, Set rotations, Optional globalServiceId, String containerClusterName) { + private void setRotations(Container container, + Set rotations, + Set endpoints, + Optional globalServiceId, + String containerClusterName) { + final Set rotationsProperty = new HashSet<>(); + // Add the legacy rotations to the list of available rotations. Using the same test + // as was used before to mirror the old business logic for global-service-id. if ( ! rotations.isEmpty() && globalServiceId.isPresent()) { if (containerClusterName.equals(globalServiceId.get())) { - container.setProp("rotations", rotations.stream().map(Rotation::getId).collect(Collectors.joining(","))); + rotations.stream().map(Rotation::getId).forEach(rotationsProperty::add); } } + + // For ContainerEndpoints this is more straight-forward, just add all that are present + endpoints.stream() + .filter(endpoint -> endpoint.clusterId().equals(containerClusterName)) + .flatMap(endpoint -> endpoint.names().stream()) + .forEach(rotationsProperty::add); + + // Build the comma delimited list of endpoints this container should be known as. + // Confusingly called 'rotations' for legacy reasons. + container.setProp("rotations", String.join(",", rotationsProperty)); } private void addRoutingAliases(ApplicationContainerCluster cluster, Element spec, Environment environment) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java index 395c1ecb80b..1287bce4963 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java @@ -5,6 +5,7 @@ import com.yahoo.cloud.config.LbServicesConfig; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.model.NullConfigModelRegistry; import com.yahoo.config.model.api.ApplicationInfo; +import com.yahoo.config.model.api.ContainerEndpoint; import com.yahoo.config.model.api.Model; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.deploy.TestProperties; @@ -20,11 +21,14 @@ import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.model.VespaModel; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import org.xml.sax.SAXException; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -33,20 +37,32 @@ import java.util.Random; import java.util.Set; import static com.yahoo.config.model.api.container.ContainerServiceType.QRSERVER; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; /** * @author Ulf Lilleengen */ +@RunWith(Parameterized.class) public class LbServicesProducerTest { private static final String rotation1 = "rotation-1"; private static final String rotation2 = "rotation-2"; private static final String rotationString = rotation1 + "," + rotation2; private static final Set rotations = Collections.singleton(new Rotation(rotationString)); + private static final Set endpoints = Set.of( + new ContainerEndpoint("mydisc", List.of("rotation-1", "rotation-2")) + ); private final InMemoryFlagSource flagSource = new InMemoryFlagSource(); + private final boolean useGlobalServiceId; + + @Parameterized.Parameters + public static Object[] useGlobalServiceId() { + return new Object[] { true, false }; + } + + public LbServicesProducerTest(boolean useGlobalServiceId) { + this.useGlobalServiceId = useGlobalServiceId; + } @Test public void testDeterministicGetConfig() throws IOException, SAXException { @@ -127,16 +143,36 @@ public class LbServicesProducerTest { .rotations(rotations) .properties(new TestProperties().setHostedVespa(true))); RegionName regionName = RegionName.from("us-east-1"); - LbServicesConfig conf = getLbServicesConfig(new Zone(Environment.prod, regionName), testModel); - final LbServicesConfig.Tenants.Applications.Hosts.Services services = conf.tenants("foo").applications("foo:prod:" + regionName.value() + ":default").hosts("foo.foo.yahoo.com").services(QRSERVER.serviceName); - assertThat(services.servicealiases().size(), is(1)); - assertThat(services.endpointaliases().size(), is(4)); - assertThat(services.servicealiases(0), is("service1")); - assertThat(services.endpointaliases(0), is("foo1.bar1.com")); - assertThat(services.endpointaliases(1), is("foo2.bar2.com")); - assertThat(services.endpointaliases(2), is(rotation1)); - assertThat(services.endpointaliases(3), is(rotation2)); + var services = getLbServicesConfig(new Zone(Environment.prod, regionName), testModel) + .tenants("foo") + .applications("foo:prod:" + regionName.value() + ":default") + .hosts("foo.foo.yahoo.com") + .services(QRSERVER.serviceName); + + if (useGlobalServiceId) { + assertThat(services.servicealiases(), contains("service1")); + assertThat("Missing rotations in list: " + services.endpointaliases(), services.endpointaliases(), containsInAnyOrder("foo1.bar1.com", "foo2.bar2.com", rotation1, rotation2)); + } + } + + @Test + public void testConfigAliasesWithEndpoints() throws IOException, SAXException { + Map> testModel = createTestModel(new DeployState.Builder() + .endpoints(endpoints) + .properties(new TestProperties().setHostedVespa(true))); + RegionName regionName = RegionName.from("us-east-1"); + + var services = getLbServicesConfig(new Zone(Environment.prod, regionName), testModel) + .tenants("foo") + .applications("foo:prod:" + regionName.value() + ":default") + .hosts("foo.foo.yahoo.com") + .services(QRSERVER.serviceName); + + if (! useGlobalServiceId) { + assertThat(services.servicealiases(), contains("service1")); + assertThat("Missing endpoints in list: " + services.endpointaliases(), services.endpointaliases(), containsInAnyOrder("foo1.bar1.com", "foo2.bar2.com", rotation1, rotation2)); + } } private Map> randomizeApplications(Map> testModel, int seed) { @@ -195,14 +231,32 @@ public class LbServicesProducerTest { " " + "" + ""; - String deploymentInfo ="" + - "" + - " " + - " " + - " us-east-1" + - " us-east-2" + - " " + - ""; + + String deploymentInfo; + + if (useGlobalServiceId) { + deploymentInfo ="" + + "" + + " " + + " " + + " us-east-1" + + " us-east-2" + + " " + + ""; + } else { + deploymentInfo ="" + + "" + + " " + + " " + + " us-east-1" + + " us-east-2" + + " " + + " " + + " " + + " " + + ""; + } + return new MockApplicationPackage.Builder().withHosts(hosts).withServices(services).withDeploymentSpec(deploymentInfo).build(); } -- cgit v1.2.3 From 7a0bde0a0edd6026ae4e74156cd987e213c33e99 Mon Sep 17 00:00:00 2001 From: Øyvind Grønnesby Date: Tue, 18 Jun 2019 17:10:03 +0200 Subject: Fix NPE in unit tests due to uninitialized endpoints in TestProperties --- .../src/main/java/com/yahoo/config/model/deploy/TestProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'config-model') diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java index 650bd06beda..fa2fbb95689 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java @@ -32,7 +32,7 @@ public class TestProperties implements ModelContext.Properties { private boolean hostedVespa = false; private Zone zone; private Set rotations; - private Set endpoints; + private Set endpoints = Collections.emptySet(); private boolean isBootstrap = false; private boolean isFirstTimeDeployment = false; private boolean useDedicatedNodeForLogserver = false; -- cgit v1.2.3 From d581622b38817f63d2625e689388ab83b225f0da Mon Sep 17 00:00:00 2001 From: Øyvind Grønnesby Date: Wed, 19 Jun 2019 15:30:07 +0200 Subject: Make a proper set to see that rotations properties are set on containers --- .../container/xml/ContainerModelBuilderTest.java | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'config-model') diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java index c7816c23119..f787453dfb6 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java @@ -6,6 +6,7 @@ import com.yahoo.component.ComponentId; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.model.NullConfigModelRegistry; +import com.yahoo.config.model.api.ContainerEndpoint; import com.yahoo.config.model.builder.xml.test.DomBuilderTest; import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.deploy.TestProperties; @@ -33,6 +34,7 @@ import com.yahoo.vespa.model.AbstractService; import com.yahoo.vespa.model.VespaModel; import com.yahoo.vespa.model.container.Container; import com.yahoo.vespa.model.container.ContainerCluster; +import com.yahoo.vespa.model.container.ContainerModel; import com.yahoo.vespa.model.container.SecretStore; import com.yahoo.vespa.model.container.component.Component; import com.yahoo.vespa.model.content.utils.ContentClusterUtils; @@ -45,8 +47,11 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.logging.Level; +import java.util.stream.Collectors; +import static com.yahoo.config.model.test.TestUtil.joinLines; import static com.yahoo.test.LinePatternMatcher.containsLineWithPattern; import static com.yahoo.vespa.defaults.Defaults.getDefaults; import static org.hamcrest.CoreMatchers.is; @@ -610,6 +615,48 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { assertNull(getContainerCluster("default").getContainers().get(0).getServicePropertyString("endpointaliases")); } + @Test + public void endpoints_are_added_to_containers() throws IOException, SAXException { + final var servicesXml = joinLines("", + "", + " ", + " ", + " ", + "" + ); + + final var deploymentXml = joinLines("", + "", + " ", + "" + ); + + final var applicationPackage = new MockApplicationPackage.Builder() + .withServices(servicesXml) + .withDeploymentSpec(deploymentXml) + .build(); + + final var deployState = new DeployState.Builder() + .applicationPackage(applicationPackage) + .zone(new Zone(Environment.prod, RegionName.from("us-east-1"))) + .endpoints(Set.of(new ContainerEndpoint("comics-search", List.of("nalle", "balle")))) + .properties(new TestProperties().setHostedVespa(true)) + .build(); + + final var model = new VespaModel(new NullConfigModelRegistry(), deployState); + final var containers = model.getContainerClusters().values().stream() + .flatMap(cluster -> cluster.getContainers().stream()) + .collect(Collectors.toList()); + + assertFalse("Missing container objects based on configuration", containers.isEmpty()); + + containers.forEach(container -> { + final var rotations = container.getServicePropertyString("rotations").split(","); + final var rotationsSet = Set.of(rotations); + assertEquals(Set.of("balle", "nalle"), rotationsSet); + }); + } + @Test public void singlenode_servicespec_is_used_with_hosted_vespa() throws IOException, SAXException { String servicesXml = ""; -- cgit v1.2.3