diff options
author | Øyvind Grønnesby <oyving@verizonmedia.com> | 2021-02-03 11:07:10 +0100 |
---|---|---|
committer | Øyvind Grønnesby <oyving@verizonmedia.com> | 2021-02-03 11:07:10 +0100 |
commit | 3732b858e75a251bbc11417a49a7e9947f0b7bc9 (patch) | |
tree | 3e6a84f7e6aba300172dbf622a55d7b02bdc1514 /config-model | |
parent | 367a937a4169f5a39e8b1b94e014baf02eceb005 (diff) |
Improve the quota error messages
Diffstat (limited to 'config-model')
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())); } } |