aboutsummaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorØyvind Grønnesby <oyving@verizonmedia.com>2021-02-03 12:33:15 +0100
committerGitHub <noreply@github.com>2021-02-03 12:33:15 +0100
commite4e9ac3e2d0ecab4f506be232d1f838bcec5b4db (patch)
treeee7939d64567e0eee0842cee9ae9c413496729df /config-model
parentc9d9ba5e0944832c4a91976f5140b85e26608a65 (diff)
parent3732b858e75a251bbc11417a49a7e9947f0b7bc9 (diff)
Merge pull request #16362 from vespa-engine/ogronnesby/improve-quota-errors
Improve the quota error messages
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java27
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java17
2 files changed, 38 insertions, 6 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java
index 2bb12654fc4..3a9ff32eea3 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/QuotaValidator.java
@@ -11,6 +11,7 @@ import java.math.BigDecimal;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.logging.Logger;
import java.util.stream.Collectors;
/**
@@ -19,6 +20,8 @@ import java.util.stream.Collectors;
* @author ogronnesby
*/
public class QuotaValidator extends Validator {
+ private static final Logger log = Logger.getLogger(QuotaValidator.class.getName());
+
@Override
public void validate(VespaModel model, DeployState deployState) {
var quota = deployState.getProperties().quota();
@@ -33,9 +36,13 @@ public class QuotaValidator extends Validator {
.mapToDouble(clusterCapacity -> clusterCapacity.nodeResources().cost() * clusterCapacity.nodes())
.sum();
- if (budget.doubleValue() < spend) {
- throwBudgetExceeded(spend, budget, systemName);
+ if (Math.abs(spend) < 0.01) {
+ log.warning("Deploying application " + model.applicationPackage().getApplicationId() + " with zero budget use. This is suspicious, but not blocked");
+ return;
}
+
+ throwIfBudgetNegative(spend, budget, systemName);
+ throwIfBudgetExceeded(spend, budget, systemName);
}
/** Check that all clusters in the application do not exceed the quota max cluster size. */
@@ -57,8 +64,20 @@ public class QuotaValidator extends Validator {
}
}
- private void throwBudgetExceeded(double spend, BigDecimal budget, SystemName systemName) {
- var message = String.format(Locale.US, "Hourly spend for maximum specified resources ($%.2f) exceeds budget from quota ($%.2f)!", spend, budget);
+ private void throwIfBudgetNegative(double spend, BigDecimal budget, SystemName systemName) {
+ if (budget.doubleValue() < 0) {
+ throwBudgetException("Please free up some quota! This deployment's quota use is ($%.2f) and reserved quota is below zero! ($%.2f)", spend, budget, systemName);
+ }
+ }
+
+ private void throwIfBudgetExceeded(double spend, BigDecimal budget, SystemName systemName) {
+ if (budget.doubleValue() < spend) {
+ throwBudgetException("Please free up some quota! This deployment's quota use ($%.2f) exceeds reserved quota ($%.2f)!", spend, budget, systemName);
+ }
+ }
+
+ private void throwBudgetException(String formatMessage, double spend, BigDecimal budget, SystemName systemName) {
+ var message = String.format(Locale.US, formatMessage, spend, budget);
var messageWithSystem = (systemName.equals(SystemName.Public) ? "" : systemName.value() + ": ") + message;
throw new IllegalArgumentException(messageWithSystem);
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java
index d3c41754c8d..d9f9b602fea 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/QuotaValidatorTest.java
@@ -47,7 +47,7 @@ public class QuotaValidatorTest {
tester.deploy(null, getServices("testCluster", 10), Environment.prod, null);
fail();
} catch (RuntimeException e) {
- assertEquals("Hourly spend for maximum specified resources ($-.--) exceeds budget from quota ($-.--)!",
+ assertEquals("Please free up some quota! This deployment's quota use ($-.--) exceeds reserved quota ($-.--)!",
ValidationTester.censorNumbers(e.getMessage()));
}
}
@@ -59,7 +59,20 @@ public class QuotaValidatorTest {
tester.deploy(null, getServices("testCluster", 10), Environment.prod, null);
fail();
} catch (RuntimeException e) {
- assertEquals("publiccd: Hourly spend for maximum specified resources ($-.--) exceeds budget from quota ($-.--)!",
+ assertEquals("publiccd: Please free up some quota! This deployment's quota use ($-.--) exceeds reserved quota ($-.--)!",
+ ValidationTester.censorNumbers(e.getMessage()));
+ }
+ }
+
+ @Test
+ public void test_deploy_with_negative_budget() {
+ var quota = Quota.unlimited().withBudget(BigDecimal.valueOf(-1));
+ var tester = new ValidationTester(10, false, new TestProperties().setHostedVespa(true).setQuota(quota).setZone(publicZone));
+ try {
+ tester.deploy(null, getServices("testCluster", 10), Environment.prod, null);
+ fail();
+ } catch (RuntimeException e) {
+ assertEquals("Please free up some quota! This deployment's quota use is ($-.--) and reserved quota is below zero! ($--.--)",
ValidationTester.censorNumbers(e.getMessage()));
}
}