diff options
Diffstat (limited to 'controller-server')
10 files changed, 51 insertions, 14 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java index 8765884e23c..d482dedfdaa 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java @@ -113,7 +113,7 @@ public class CloudTrialExpirer extends ControllerMaintainer { private void setPlanNone(List<Tenant> tenants) { tenants.forEach(tenant -> { - controller().serviceRegistry().billingController().setPlan(tenant.name(), PlanId.from("none"), false); + controller().serviceRegistry().billingController().setPlan(tenant.name(), PlanId.from("none"), false, false); }); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java index d0b3b9f4c7f..1463cce595d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainer.java @@ -44,7 +44,7 @@ import java.util.stream.Stream; public class VcmrMaintainer extends ControllerMaintainer { private static final Logger LOG = Logger.getLogger(VcmrMaintainer.class.getName()); - private static final Duration ALLOWED_RETIREMENT_TIME = Duration.ofHours(60); + private static final int DAYS_TO_RETIRE = 2; private static final Duration ALLOWED_POSTPONEMENT_TIME = Duration.ofDays(7); private final CuratorDb curator; @@ -240,8 +240,7 @@ public class VcmrMaintainer extends ControllerMaintainer { private boolean shouldRetire(VespaChangeRequest changeRequest, HostAction action) { return action.getState() == State.PENDING_RETIREMENT && - changeRequest.getChangeRequestSource().getPlannedStartTime() - .minus(ALLOWED_RETIREMENT_TIME) + getRetirementStartTime(changeRequest.getChangeRequestSource().getPlannedStartTime()) .isBefore(ZonedDateTime.now()); } @@ -337,4 +336,16 @@ public class VcmrMaintainer extends ControllerMaintainer { nodeRepository.updateReports(zoneId, node.hostname().value(), report.toNodeReports()); } + // Calculate wanted retirement start time, ignoring weekends + // protected for testing + protected ZonedDateTime getRetirementStartTime(ZonedDateTime plannedStartTime) { + var time = plannedStartTime; + var days = 0; + while (days < DAYS_TO_RETIRE) { + time = time.minusDays(1); + if (time.getDayOfWeek().getValue() < 6) days++; + } + return time; + } + } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java index 33307ea1677..3f610d27950 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java @@ -24,6 +24,8 @@ import com.yahoo.vespa.hosted.controller.api.integration.billing.CollectionMetho import com.yahoo.vespa.hosted.controller.api.integration.billing.InstrumentOwner; import com.yahoo.vespa.hosted.controller.api.integration.billing.PaymentInstrument; import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; +import com.yahoo.vespa.hosted.controller.api.role.Role; +import com.yahoo.vespa.hosted.controller.api.role.SecurityContext; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import com.yahoo.yolean.Exceptions; @@ -41,6 +43,7 @@ import java.time.format.DateTimeParseException; import java.util.Comparator; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.Executor; import java.util.logging.Level; import java.util.stream.Collectors; @@ -158,9 +161,11 @@ public class BillingApiHandler extends ThreadedHttpRequestHandler { var tenantName = TenantName.from(tenant); var slime = inspectorOrThrow(request); var planId = PlanId.from(slime.field("plan").asString()); + var roles = requestRoles(request); + var isAccountant = roles.contains(Role.hostedAccountant()); var hasDeployments = hasDeployments(tenantName); - var result = billingController.setPlan(tenantName, planId, hasDeployments); + var result = billingController.setPlan(tenantName, planId, hasDeployments, isAccountant); if (result.isSuccess()) return new StringResponse("Plan: " + planId.value()); @@ -483,4 +488,12 @@ public class BillingApiHandler extends ThreadedHttpRequestHandler { .count() > 0; } + private static Set<Role> requestRoles(HttpRequest request) { + return Optional.ofNullable(request.getJDiscRequest().context().get(SecurityContext.ATTRIBUTE_NAME)) + .filter(SecurityContext.class::isInstance) + .map(SecurityContext.class::cast) + .map(SecurityContext::roles) + .orElseThrow(() -> new IllegalArgumentException("Attribute '" + SecurityContext.ATTRIBUTE_NAME + "' was not set on request")); + } + } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java index 0f3e5b7f76b..087d6152afc 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java @@ -110,7 +110,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler if (newPlan.valid() && newPlan.type() == Type.STRING) { var planId = PlanId.from(newPlan.asString()); var hasDeployments = tenantHasDeployments(tenant.name()); - var result = billing.setPlan(tenant.name(), planId, hasDeployments); + var result = billing.setPlan(tenant.name(), planId, hasDeployments, false); if (! result.isSuccess()) { throw new RestApiException.Forbidden(result.getErrorMessage().get()); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java index f768ab5e61b..2e34c6511a7 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirerTest.java @@ -86,7 +86,7 @@ public class CloudTrialExpirerTest { private void registerTenant(String tenantName, String plan, Duration timeSinceLastLogin) { var name = TenantName.from(tenantName); tester.createTenant(tenantName, Tenant.Type.cloud); - tester.serviceRegistry().billingController().setPlan(name, PlanId.from(plan), false); + tester.serviceRegistry().billingController().setPlan(name, PlanId.from(plan), false, false); tester.controller().tenants().updateLastLogin(name, List.of(LastLoginInfo.UserLevel.user), tester.controller().clock().instant().minus(timeSinceLastLogin)); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java index 64e3a95605a..215c03030a9 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporterTest.java @@ -490,8 +490,8 @@ public class MetricsReporterTest { tester.createTenant("foo", Tenant.Type.cloud); tester.createTenant("bar", Tenant.Type.cloud); tester.createTenant("fix", Tenant.Type.cloud); - tester.controller().serviceRegistry().billingController().setPlan(TenantName.from("foo"), PlanId.from("pay-as-you-go"), false); - tester.controller().serviceRegistry().billingController().setPlan(TenantName.from("bar"), PlanId.from("pay-as-you-go"), false); + tester.controller().serviceRegistry().billingController().setPlan(TenantName.from("foo"), PlanId.from("pay-as-you-go"), false, false); + tester.controller().serviceRegistry().billingController().setPlan(TenantName.from("bar"), PlanId.from("pay-as-you-go"), false, false); var reporter = createReporter(tester.controller()); reporter.maintain(); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainerTest.java index e7a6c3ea3c3..bfbd3836ce7 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/VcmrMaintainerTest.java @@ -18,9 +18,11 @@ import com.yahoo.vespa.hosted.controller.integration.NodeRepositoryMock; import org.junit.Before; import org.junit.Test; +import java.time.DayOfWeek; import java.time.Duration; import java.time.Instant; import java.time.ZonedDateTime; +import java.time.temporal.TemporalAdjusters; import java.util.List; import static org.junit.Assert.assertEquals; @@ -244,6 +246,17 @@ public class VcmrMaintainerTest { assertEquals(Status.OUT_OF_SYNC, writtenChangeRequest.getStatus()); } + @Test + public void retirement_start_time_ignores_weekends() { + var plannedStartTime = ZonedDateTime.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.WEDNESDAY)); + var retirementStartTime = maintainer.getRetirementStartTime(plannedStartTime); + assertEquals(plannedStartTime.minusDays(2), retirementStartTime); + + plannedStartTime = ZonedDateTime.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY)); + retirementStartTime = maintainer.getRetirementStartTime(plannedStartTime); + assertEquals(plannedStartTime.minusDays(4), retirementStartTime); + } + private VespaChangeRequest canceledChangeRequest() { return newChangeRequest(ChangeRequestSource.Status.CANCELED, State.RETIRED, State.RETIRING, ZonedDateTime.now()); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java index 33b7500ceac..5368cc73480 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java @@ -211,7 +211,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { @Test public void trial_tenant_limit_reached() { ((InMemoryFlagSource) tester.controller().flagSource()).withIntFlag(PermanentFlags.MAX_TRIAL_TENANTS.id(), 1); - tester.controller().serviceRegistry().billingController().setPlan(tenantName, PlanId.from("pay-as-you-go"), false); + tester.controller().serviceRegistry().billingController().setPlan(tenantName, PlanId.from("pay-as-you-go"), false, false); // tests that we can create the one trial tenant the flag says we can have -- and that the tenant created // in @Before does not count towards that limit. diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java index 0ef242aed16..b58e5294f66 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java @@ -102,7 +102,7 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest { billingController.addBill(tenant, bill, true); billingController.addBill(tenant, bill, false); - billingController.setPlan(tenant, PlanId.from("some-plan"), true); + billingController.setPlan(tenant, PlanId.from("some-plan"), true, false); var request = request("/billing/v1/tenant/tenant1/billing?until=2020-05-28").roles(tenantRole); tester.assertResponse(request, new File("tenant-billing-view.json")); @@ -179,8 +179,8 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest { tester.controller().tenants().create(new CloudTenantSpec(tenant2, ""), new Auth0Credentials(() -> "foo", Set.of(Role.hostedOperator()))); var bill = createBill(); - billingController.setPlan(tenant, PlanId.from("some-plan"), true); - billingController.setPlan(tenant2, PlanId.from("some-plan"), true); + billingController.setPlan(tenant, PlanId.from("some-plan"), true, false); + billingController.setPlan(tenant2, PlanId.from("some-plan"), true, false); billingController.addBill(tenant, bill, false); billingController.addLineItem(tenant, "support", new BigDecimal("42"), "Smith"); billingController.addBill(tenant2, bill, false); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java index d0c95fe593e..1bb409b9906 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java @@ -291,7 +291,7 @@ public class UserApiTest extends ControllerContainerCloudTest { var tenant1 = controller.createTenant("tenant1", Tenant.Type.cloud); var tenant2 = controller.createTenant("tenant2", Tenant.Type.cloud); - controller.serviceRegistry().billingController().setPlan(tenant2, PlanId.from("paid"), false); + controller.serviceRegistry().billingController().setPlan(tenant2, PlanId.from("paid"), false, false); tester.assertResponse( request("/user/v1/user") |