diff options
author | Øyvind Grønnesby <oyving@verizonmedia.com> | 2020-10-12 14:10:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-12 14:10:08 +0200 |
commit | d1059fed419e8c8b0b033966cfabbf4568bbcca6 (patch) | |
tree | d6a23bdc41a7e8038e2eab1147e0402385f31a47 | |
parent | 9e74c7bfd20b32283fd9c078d3604bb44bacc02c (diff) | |
parent | e8f8420eab675350e61260578bd10228645c51f1 (diff) |
Merge pull request #14654 from vespa-engine/ogronnesby/quota-decimal-controller
Quota as BigDecimals in the controller
5 files changed, 71 insertions, 28 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java index 5db89ccc656..19dfe0d9dcc 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java @@ -33,7 +33,7 @@ public class MockBillingController implements BillingController { @Override public Optional<Quota> getQuota(TenantName tenant, Environment environment) { - return Optional.of(new Quota(5)); + return Optional.of(Quota.unlimited().withMaxClusterSize(5)); } @Override diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Quota.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Quota.java index 4e1efc1b6d9..511d7bf1d09 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Quota.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Quota.java @@ -1,57 +1,60 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.api.integration.billing; +import java.math.BigDecimal; import java.util.Objects; import java.util.Optional; +import java.util.OptionalInt; /** - * Quota information transmitted to the configserver on deploy. + * Quota information transmitted to the configserver on deploy. All limits are represented + * with an Optional type where the empty optional means unlimited resource use. * * @author andreer * @author ogronnesby */ public class Quota { - private static final Quota UNLIMITED = new Quota(Optional.empty(), Optional.empty()); - private static final Quota ZERO = new Quota(0, 0); + private static final Quota UNLIMITED = new Quota(OptionalInt.empty(), Optional.empty()); + private static final Quota ZERO = new Quota(OptionalInt.of(0), Optional.of(BigDecimal.ZERO)); - private final Optional<Integer> maxClusterSize; - private final Optional<Integer> budget; // in USD/hr, as calculated by NodeResources + private final OptionalInt maxClusterSize; + private final Optional<BigDecimal> budget; // in USD/hr, as calculated by NodeResources - public Quota(int maxClusterSize) { - this(Optional.of(maxClusterSize), Optional.empty()); - } - - public Quota(int maxClusterSize, int dollarsPerHour) { - this(Optional.of(maxClusterSize), Optional.of(dollarsPerHour)); - } - - public Quota(Optional<Integer> maxClusterSize, Optional<Integer> budget) { + private Quota(OptionalInt maxClusterSize, Optional<BigDecimal> budget) { this.maxClusterSize = Objects.requireNonNull(maxClusterSize); this.budget = Objects.requireNonNull(budget); } - public Optional<Integer> maxClusterSize() { - return maxClusterSize; + public Quota withMaxClusterSize(int clusterSize) { + return new Quota(OptionalInt.of(clusterSize), budget); } - public Optional<Integer> budget() { - return budget; + /** Construct a Quota that allows zero resource usage */ + public static Quota zero() { + return ZERO; } - public Quota withMaxClusterSize(int clusterSize) { - return new Quota(Optional.of(clusterSize), budget); + /** Construct a Quota that allows unlimited resource usage */ + public static Quota unlimited() { + return UNLIMITED; + } + + public Quota withBudget(BigDecimal budget) { + return new Quota(maxClusterSize, Optional.ofNullable(budget)); } public Quota withBudget(int budget) { - return new Quota(maxClusterSize, Optional.of(budget)); + return withBudget(BigDecimal.valueOf(budget)); } - public static Quota zero() { - return ZERO; + /** Maximum number of nodes in a cluster in a Vespa deployment */ + public OptionalInt maxClusterSize() { + return maxClusterSize; } - public static Quota unlimited() { - return UNLIMITED; + /** Maximum $/hour run-rate for the Vespa deployment */ + public Optional<BigDecimal> budget() { + return budget; } @Override diff --git a/flags/src/main/java/com/yahoo/vespa/flags/BigDecimalFlag.java b/flags/src/main/java/com/yahoo/vespa/flags/BigDecimalFlag.java new file mode 100644 index 00000000000..f5273719275 --- /dev/null +++ b/flags/src/main/java/com/yahoo/vespa/flags/BigDecimalFlag.java @@ -0,0 +1,15 @@ +// Copyright 2020 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.flags; + +import java.math.BigDecimal; + +/** + * @author ogronnesby + */ +public class BigDecimalFlag extends FlagImpl<BigDecimal, BigDecimalFlag> { + public BigDecimalFlag(FlagId id, BigDecimal defaultValue, FetchVector fetchVector, FlagSerializer<BigDecimal> serializer, FlagSource source) { + super(id, defaultValue, fetchVector, serializer, source, BigDecimalFlag::new); + } + + public BigDecimal value() { return boxedValue(); } +} 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 c7e171e4e06..448e493408a 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java @@ -5,6 +5,7 @@ import com.yahoo.component.Vtag; import com.yahoo.vespa.defaults.Defaults; import com.yahoo.vespa.flags.custom.HostCapacity; +import java.math.BigDecimal; import java.util.List; import java.util.Optional; import java.util.TreeMap; @@ -302,8 +303,8 @@ public class Flags { APPLICATION_ID ); - public static final UnboundIntFlag TENANT_BUDGET_QUOTA = defineIntFlag( - "tenant-budget-quota", 5, + public static final UnboundBigDecimalFlag TENANT_BUDGET_QUOTA = defineBigDecimalFlag( + "tenant-budget-quota", new BigDecimal("5.00"), "The budget in $/hr a tenant is allowed spend per instance, as calculated by NodeResources", "Only takes effect on next deployment, if set to a value other than the default for flag!", APPLICATION_ID @@ -405,6 +406,12 @@ public class Flags { } /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ + public static UnboundBigDecimalFlag defineBigDecimalFlag(String flagId, BigDecimal defaultValue, String description, + String modificationEffect, FetchVector.Dimension... dimensions) { + return define(UnboundBigDecimalFlag::new, flagId, defaultValue, description, modificationEffect, dimensions); + } + + /** WARNING: public for testing: All flags should be defined in {@link Flags}. */ public static <T> UnboundJacksonFlag<T> defineJacksonFlag(String flagId, T defaultValue, Class<T> jacksonClass, String description, String modificationEffect, FetchVector.Dimension... dimensions) { return define((id2, defaultValue2, vector2) -> new UnboundJacksonFlag<>(id2, defaultValue2, vector2, jacksonClass), diff --git a/flags/src/main/java/com/yahoo/vespa/flags/UnboundBigDecimalFlag.java b/flags/src/main/java/com/yahoo/vespa/flags/UnboundBigDecimalFlag.java new file mode 100644 index 00000000000..0b26046c777 --- /dev/null +++ b/flags/src/main/java/com/yahoo/vespa/flags/UnboundBigDecimalFlag.java @@ -0,0 +1,18 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.flags; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.DecimalNode; + +import java.math.BigDecimal; + +/** + * @author ogronnesby + */ +public class UnboundBigDecimalFlag extends UnboundFlagImpl<BigDecimal, BigDecimalFlag, UnboundBigDecimalFlag> { + public UnboundBigDecimalFlag(FlagId id, BigDecimal defaultValue, FetchVector defaultFetchVector) { + super(id, defaultValue, defaultFetchVector, + new SimpleFlagSerializer<>(DecimalNode::valueOf, JsonNode::isBigDecimal, JsonNode::decimalValue), + UnboundBigDecimalFlag::new, BigDecimalFlag::new); + } +} |