diff options
author | Håkon Hallingstad <hakon@yahoo-inc.com> | 2017-03-01 12:57:47 +0100 |
---|---|---|
committer | Håkon Hallingstad <hakon@yahoo-inc.com> | 2017-03-01 12:57:47 +0100 |
commit | 111176dc2261676aa59962e795cbd332be8a74f1 (patch) | |
tree | 8f0291a11b6409676229682f7ff9c5ef408baf9b /node-repository | |
parent | f1179b5e605a528e561b9ef98b41422b0a603dee (diff) |
Support default flavor override per application
Diffstat (limited to 'node-repository')
5 files changed, 55 insertions, 6 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java index a163cf6db7f..031170aa488 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java @@ -225,6 +225,11 @@ public class NodeRepository extends AbstractComponent { .findFirst(); } + /** Get default flavor override for an application, if present. */ + public Optional<String> getDefaultFlavorOverride(ApplicationId applicationId) { + return zkClient.getDefaultFlavorForApplication(applicationId); + } + // ----------------- Node lifecycle ----------------------------------------------------------- /** Creates a new node object, without adding it to the node repo. If no IP address is given, it will be resolved */ diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java index 54292247115..31ad57a4a77 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDatabaseClient.java @@ -18,6 +18,7 @@ import com.yahoo.vespa.curator.transaction.CuratorTransaction; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.node.Status; +import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.Duration; import java.util.ArrayList; @@ -288,4 +289,15 @@ public class CuratorDatabaseClient { return curatorDatabase.lock(path, timeout); } + /** + * Returns a default flavor specific for an application, or empty if not available. + */ + public Optional<String> getDefaultFlavorForApplication(ApplicationId applicationId) { + Optional<byte[]> utf8DefaultFlavor = curatorDatabase.getData(defaultFlavorPath(applicationId)); + return utf8DefaultFlavor.map((flavor) -> new String(flavor, StandardCharsets.UTF_8)); + } + + private Path defaultFlavorPath(ApplicationId applicationId) { + return root.append("defaultFlavor").append(applicationId.serializedForm()); + } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java index f63d43edbda..fbff0115192 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java @@ -38,16 +38,19 @@ public class CapacityPolicies { } } - public Flavor decideFlavor(Capacity requestedCapacity, ClusterSpec cluster) { + public Flavor decideFlavor(Capacity requestedCapacity, ClusterSpec cluster, Optional<String> defaultFlavorOverride) { // for now, always use requested docker flavor when requested final Optional<String> requestedFlavor = requestedCapacity.flavor(); if (requestedFlavor.isPresent() && flavors.getFlavorOrThrow(requestedFlavor.get()).getType() == Flavor.Type.DOCKER_CONTAINER) return flavors.getFlavorOrThrow(requestedFlavor.get()); + String defaultFlavorName = defaultFlavorOverride.isPresent() ? + defaultFlavorOverride.get() : zone.defaultFlavor(cluster.type()); + switch(zone.environment()) { - case dev : case test : case staging : return flavors.getFlavorOrThrow(zone.defaultFlavor(cluster.type())); - default : return flavors.getFlavorOrThrow(requestedFlavor.orElse(zone.defaultFlavor(cluster.type()))); + case dev : case test : case staging : return flavors.getFlavorOrThrow(defaultFlavorName); + default : return flavors.getFlavorOrThrow(requestedFlavor.orElse(defaultFlavorName)); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index ac313cb7526..37fa903380d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -5,8 +5,10 @@ import com.google.inject.Inject; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; +import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.HostFilter; import com.yahoo.config.provision.HostSpec; +import com.yahoo.config.provision.NodeFlavors; import com.yahoo.config.provision.NodeType; import com.yahoo.config.provision.ProvisionLogger; import com.yahoo.config.provision.Provisioner; @@ -15,8 +17,6 @@ import com.yahoo.log.LogLevel; import com.yahoo.transaction.NestedTransaction; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeRepository; -import com.yahoo.config.provision.Flavor; -import com.yahoo.config.provision.NodeFlavors; import com.yahoo.vespa.hosted.provision.node.filter.ApplicationFilter; import com.yahoo.vespa.hosted.provision.node.filter.NodeHostFilter; @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -79,7 +80,8 @@ public class NodeRepositoryProvisioner implements Provisioner { if (zone.environment().isManuallyDeployed() && nodeCount < requestedCapacity.nodeCount()) logger.log(Level.INFO, "Requested " + requestedCapacity.nodeCount() + " nodes for " + cluster + ", downscaling to " + nodeCount + " nodes in " + zone.environment()); - Flavor flavor = capacityPolicies.decideFlavor(requestedCapacity, cluster); + Optional<String> defaultFlavorOverride = nodeRepository.getDefaultFlavorOverride(application); + Flavor flavor = capacityPolicies.decideFlavor(requestedCapacity, cluster, defaultFlavorOverride); effectiveGroups = wantedGroups > nodeCount ? nodeCount : wantedGroups; // cannot have more groups than nodes requestedNodes = NodeSpec.from(nodeCount, flavor); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTest.java index ce0a910c0d5..b4a0c7f072f 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTest.java @@ -1,9 +1,18 @@ package com.yahoo.vespa.hosted.provision; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.ApplicationName; +import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.NodeType; +import com.yahoo.config.provision.TenantName; +import com.yahoo.path.Path; import org.junit.Test; +import java.nio.charset.StandardCharsets; +import java.util.Optional; + import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** @@ -29,5 +38,23 @@ public class NodeRepositoryTest { assertEquals(2, tester.getNodes(NodeType.tenant).size()); } + + @Test + public void applicationDefaultFlavor() { + NodeRepositoryTester tester = new NodeRepositoryTester(); + + ApplicationId application = ApplicationId.from(TenantName.from("a"), ApplicationName.from("b"), InstanceName.from("c")); + + Path path = Path.fromString("/provision/v1/defaultFlavor").append(application.serializedForm()); + String flavor = "example-flavor"; + tester.curator().create(path); + tester.curator().set(path, flavor.getBytes(StandardCharsets.UTF_8)); + + assertEquals(Optional.of(flavor), tester.nodeRepository().getDefaultFlavorOverride(application)); + + ApplicationId applicationWithoutDefaultFlavor = + ApplicationId.from(TenantName.from("does"), ApplicationName.from("not"), InstanceName.from("exist")); + assertFalse(tester.nodeRepository().getDefaultFlavorOverride(applicationWithoutDefaultFlavor).isPresent()); + } } |