diff options
Diffstat (limited to 'controller-server/src/test/java')
9 files changed, 184 insertions, 151 deletions
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java index 53ab488949e..db58ef1830f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java @@ -526,6 +526,37 @@ public class DeploymentTriggerTest { } @Test + public void testJobPause() { + Application app = tester.createAndDeploy("app", 3, "default"); + tester.upgradeSystem(new Version("9.8.7")); + + tester.applications().deploymentTrigger().pauseJob(app.id(), productionUsWest1, tester.clock().instant().plus(Duration.ofSeconds(1))); + tester.applications().deploymentTrigger().pauseJob(app.id(), productionUsEast3, tester.clock().instant().plus(Duration.ofSeconds(3))); + + // us-west-1 does not trigger when paused. + tester.deployAndNotify(app, true, systemTest); + tester.deployAndNotify(app, true, stagingTest); + tester.assertNotRunning(productionUsWest1, app.id()); + + // us-west-1 triggers when no longer paused, but does not retry when paused again. + tester.clock().advance(Duration.ofMillis(1500)); + tester.readyJobTrigger().run(); + tester.assertRunning(productionUsWest1, app.id()); + tester.applications().deploymentTrigger().pauseJob(app.id(), productionUsWest1, tester.clock().instant().plus(Duration.ofSeconds(1))); + tester.deployAndNotify(app, false, productionUsWest1); + tester.assertNotRunning(productionUsWest1, app.id()); + tester.clock().advance(Duration.ofMillis(1000)); + tester.readyJobTrigger().run(); + tester.deployAndNotify(app, true, productionUsWest1); + + // us-east-3 does not automatically trigger when paused, but does when forced. + tester.assertNotRunning(productionUsEast3, app.id()); + tester.deploymentTrigger().forceTrigger(app.id(), productionUsEast3, "mrTrigger"); + tester.assertRunning(productionUsEast3, app.id()); + assertFalse(tester.application(app.id()).deploymentJobs().jobStatus().get(productionUsEast3).pausedUntil().isPresent()); + } + + @Test public void testUpgradingButNoJobStarted() { ReadyJobsTrigger readyJobsTrigger = new ReadyJobsTrigger(tester.controller(), Duration.ofHours(1), diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java index b87458e6ecf..e1a557f26f1 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java @@ -43,6 +43,7 @@ import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.succeeded import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.unfinished; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author jonmv @@ -65,7 +66,7 @@ public class InternalStepRunnerTest { } @Test - public void canSwitchFromScrewdriver() { + public void canSwitchFromScrewdriverAndBackAgain() { // Deploys a default application package with default build number. tester.tester().deployCompletely(tester.app(), InternalDeploymentTester.applicationPackage); tester.setEndpoints(InternalDeploymentTester.appId, JobType.productionUsCentral1.zone(tester.tester().controller().system())); @@ -75,6 +76,14 @@ public class InternalStepRunnerTest { tester.deployNewSubmission(); tester.deployNewPlatform(new Version("7.1")); + + tester.jobs().unregister(InternalDeploymentTester.appId); + try { + tester.tester().deployCompletely(tester.app(), InternalDeploymentTester.applicationPackage, BuildJob.defaultBuildNumber + 1); + throw new IllegalStateException("Component job should get ahead again with build numbers to produce a change."); + } + catch (AssertionError expected) { } + tester.tester().deployCompletely(tester.app(), InternalDeploymentTester.applicationPackage, BuildJob.defaultBuildNumber + 2); } @Test diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterUtilizationMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterUtilizationMaintainerTest.java index 71d2690bb4a..66be2d09797 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterUtilizationMaintainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterUtilizationMaintainerTest.java @@ -3,45 +3,24 @@ package com.yahoo.vespa.hosted.controller.maintenance; // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -import com.github.tomakehurst.wiremock.junit.WireMockRule; -import com.github.tomakehurst.wiremock.stubbing.ServeEvent; -import com.github.tomakehurst.wiremock.verification.LoggedRequest; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.vespa.hosted.controller.ControllerTester; import com.yahoo.vespa.hosted.controller.application.Deployment; -import com.yahoo.vespa.hosted.controller.authority.config.ApiAuthorityConfig; import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; import java.time.Duration; -import java.util.List; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.findAll; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.getAllServeEvents; -import static com.github.tomakehurst.wiremock.client.WireMock.okJson; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static org.junit.Assert.assertEquals; /** * @author smorgrav */ public class ClusterUtilizationMaintainerTest { - @Rule - public WireMockRule wireMockRule = new WireMockRule(4443); - @Test public void maintain() { - wireMockRule.stubFor(post(urlEqualTo("/metricforwarding/v1/clusterutilization")) - .willReturn(aResponse().withStatus(200))); ControllerTester tester = new ControllerTester(); ApplicationId app = tester.createAndDeploy("tenant1", "domain1", "app1", Environment.dev, 123).id(); @@ -49,16 +28,12 @@ public class ClusterUtilizationMaintainerTest { Deployment deployment = tester.controller().applications().get(app).get().deployments().values().stream().findAny().get(); Assert.assertEquals(0, deployment.clusterUtils().size()); - ApiAuthorityConfig.Builder apiAuthorityConfigBuilder = new ApiAuthorityConfig.Builder().authorities("http://localhost:4443/"); - ApiAuthorityConfig apiAuthorityConfig = new ApiAuthorityConfig(apiAuthorityConfigBuilder); - ClusterUtilizationMaintainer maintainer = new ClusterUtilizationMaintainer(tester.controller(), Duration.ofHours(1), new JobControl(new MockCuratorDb()), apiAuthorityConfig); - maintainer.maintain(); + ClusterUtilizationMaintainer mainainer = new ClusterUtilizationMaintainer(tester.controller(), Duration.ofHours(1), new JobControl(new MockCuratorDb())); + mainainer.maintain(); - List<ServeEvent> allServeEvents = getAllServeEvents(); - assertEquals(allServeEvents.size(), 1); - LoggedRequest request = findAll(postRequestedFor(urlEqualTo("/metricforwarding/v1/clusterutilization"))).get(0); - String expectedBody = "[{\"applicationId\":\"tenant1:app1:default\",\"deployments\":[{\"zoneId\":\"dev.us-east-1\",\"clusterUtil\":[{\"clusterSpecId\":\"default\",\"cpu\":0.5554,\"memory\":0.6990000000000001,\"disk\":0.34590000000000004,\"diskBusy\":0.0}]}]}]"; - assertEquals(expectedBody, new String(request.getBody())); + deployment = tester.controller().applications().get(app).get().deployments().values().stream().findAny().get(); + Assert.assertEquals(1, deployment.clusterUtils().size()); + Assert.assertEquals(0.5554, deployment.clusterUtils().get(ClusterSpec.Id.from("default")).getCpu(), Double.MIN_VALUE); } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainerTest.java index a46215eaf22..cbaa37b15e3 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainerTest.java @@ -1,17 +1,13 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.maintenance; -import com.github.tomakehurst.wiremock.junit.WireMockRule; -import com.github.tomakehurst.wiremock.verification.LoggedRequest; import com.yahoo.config.provision.TenantName; import com.yahoo.vespa.hosted.controller.ControllerTester; -import com.yahoo.vespa.hosted.controller.authority.config.ApiAuthorityConfig; import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId; import com.yahoo.vespa.hosted.controller.api.integration.organization.User; import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.Contact; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import java.net.URI; @@ -22,16 +18,9 @@ import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.findAll; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.okJson; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * @author mpolden @@ -40,27 +29,13 @@ public class ContactInformationMaintainerTest { private ControllerTester tester; private ContactInformationMaintainer maintainer; - private String contactInfoPath = "/contactinfo/v1/tenant/tenant1"; - private String tenantPath = "/application/v4/tenant/"; - - @Rule - public WireMockRule wireMockRule = new WireMockRule(4443); - @Before public void before() { tester = new ControllerTester(); - ApiAuthorityConfig.Builder apiAuthorityConfigBuilder = new ApiAuthorityConfig.Builder().authorities("http://localhost:4443/"); - ApiAuthorityConfig apiAuthorityConfig = new ApiAuthorityConfig(apiAuthorityConfigBuilder); maintainer = new ContactInformationMaintainer(tester.controller(), Duration.ofDays(1), new JobControl(tester.controller().curator()), - tester.organization(), apiAuthorityConfig); - wireMockRule.stubFor(post(urlEqualTo(contactInfoPath)) - .willReturn(aResponse().withStatus(200))); - wireMockRule.stubFor(get(urlEqualTo(tenantPath)) - .willReturn(okJson("[{\"tenant\":\"tenant1\"}]"))); - wireMockRule.stubFor(get(urlEqualTo(tenantPath + "tenant1")) - .willReturn(okJson("{\"tenant\":\"tenant1\", \"athensDomain\":\"domain\", \"property\":\"property\", \"propertyId\":\"1\"}"))); + tester.organization()); } @Test @@ -69,13 +44,13 @@ public class ContactInformationMaintainerTest { TenantName name = tester.createTenant("tenant1", "domain1", propertyId); Supplier<AthenzTenant> tenant = () -> tester.controller().tenants().requireAthenzTenant(name); assertFalse("No contact information initially", tenant.get().contact().isPresent()); + Contact contact = testContact(); registerContact(propertyId, contact); maintainer.run(); - verify(1, postRequestedFor(urlEqualTo(contactInfoPath))); - LoggedRequest request = findAll(postRequestedFor(urlEqualTo(contactInfoPath))).get(0); - String expectedBody = "{\"url\":\"http://contact1.test\",\"issueTrackerUrl\":\"http://issue-tracker1.test\",\"propertyUrl\":\"http://property1.test\",\"persons\":[[\"alice\"],[\"bob\"]]}"; - assertEquals(expectedBody, new String(request.getBody())); + + assertTrue("Contact information added", tenant.get().contact().isPresent()); + assertEquals(contact, tenant.get().contact().get()); } private void registerContact(long propertyId, Contact contact) { diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainerTest.java index 5014f796933..e11440a372c 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainerTest.java @@ -1,38 +1,27 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.maintenance; -import com.github.tomakehurst.wiremock.junit.WireMockRule; -import com.github.tomakehurst.wiremock.stubbing.ServeEvent; -import com.github.tomakehurst.wiremock.verification.LoggedRequest; +import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Environment; -import com.yahoo.slime.ArrayTraverser; -import com.yahoo.slime.Inspector; -import com.yahoo.slime.Slime; -import com.yahoo.vespa.config.SlimeUtils; import com.yahoo.vespa.hosted.controller.Application; -import com.yahoo.vespa.hosted.controller.api.integration.MetricsService; +import com.yahoo.vespa.hosted.controller.Controller; +import com.yahoo.vespa.hosted.controller.ControllerTester; import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneId; import com.yahoo.vespa.hosted.controller.application.ApplicationPackage; -import com.yahoo.vespa.hosted.controller.authority.config.ApiAuthorityConfig; +import com.yahoo.vespa.hosted.controller.application.Deployment; +import com.yahoo.vespa.hosted.controller.application.RotationStatus; import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder; import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester; import com.yahoo.vespa.hosted.controller.integration.MetricsServiceMock; -import org.junit.Rule; import org.junit.Test; import java.time.Duration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.findAll; -import static com.github.tomakehurst.wiremock.client.WireMock.getAllServeEvents; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import java.time.Instant; +import java.util.function.Supplier; + +import static java.time.temporal.ChronoUnit.MILLIS; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; /** * @author smorgrav @@ -40,18 +29,69 @@ import static org.junit.Assert.assertEquals; */ public class DeploymentMetricsMaintainerTest { - private static final double DELTA = 0.0000001; - - @Rule - public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort(), true); + @Test + public void updates_metrics() { + ControllerTester tester = new ControllerTester(); + ApplicationId appId = tester.createAndDeploy("tenant1", "domain1", "app1", + Environment.dev, 123).id(); + DeploymentMetricsMaintainer maintainer = maintainer(tester.controller()); + Supplier<Application> app = tester.application(appId); + Supplier<Deployment> deployment = () -> app.get().deployments().values().stream().findFirst().get(); + + // No metrics gathered yet + assertEquals(0, app.get().metrics().queryServiceQuality(), 0); + assertEquals(0, deployment.get().metrics().documentCount(), 0); + assertFalse("Never received any queries", deployment.get().activity().lastQueried().isPresent()); + assertFalse("Never received any writes", deployment.get().activity().lastWritten().isPresent()); + + // Metrics are gathered and saved to application + maintainer.maintain(); + assertEquals(0.5, app.get().metrics().queryServiceQuality(), Double.MIN_VALUE); + assertEquals(0.7, app.get().metrics().writeServiceQuality(), Double.MIN_VALUE); + assertEquals(1, deployment.get().metrics().queriesPerSecond(), Double.MIN_VALUE); + assertEquals(2, deployment.get().metrics().writesPerSecond(), Double.MIN_VALUE); + assertEquals(3, deployment.get().metrics().documentCount(), Double.MIN_VALUE); + assertEquals(4, deployment.get().metrics().queryLatencyMillis(), Double.MIN_VALUE); + assertEquals(5, deployment.get().metrics().writeLatencyMillis(), Double.MIN_VALUE); + Instant t1 = tester.clock().instant().truncatedTo(MILLIS); + assertEquals(t1, deployment.get().activity().lastQueried().get()); + assertEquals(t1, deployment.get().activity().lastWritten().get()); + + // Time passes. Activity is updated as app is still receiving traffic + tester.clock().advance(Duration.ofHours(1)); + Instant t2 = tester.clock().instant().truncatedTo(MILLIS); + maintainer.maintain(); + assertEquals(t2, deployment.get().activity().lastQueried().get()); + assertEquals(t2, deployment.get().activity().lastWritten().get()); + assertEquals(1, deployment.get().activity().lastQueriesPerSecond().getAsDouble(), Double.MIN_VALUE); + assertEquals(2, deployment.get().activity().lastWritesPerSecond().getAsDouble(), Double.MIN_VALUE); + + // Query traffic disappears. Query activity stops updating + tester.clock().advance(Duration.ofHours(1)); + Instant t3 = tester.clock().instant().truncatedTo(MILLIS); + tester.metricsService().setMetric("queriesPerSecond", 0D); + tester.metricsService().setMetric("writesPerSecond", 5D); + maintainer.maintain(); + assertEquals(t2, deployment.get().activity().lastQueried().get()); + assertEquals(t3, deployment.get().activity().lastWritten().get()); + assertEquals(1, deployment.get().activity().lastQueriesPerSecond().getAsDouble(), Double.MIN_VALUE); + assertEquals(5, deployment.get().activity().lastWritesPerSecond().getAsDouble(), Double.MIN_VALUE); + + // Feed traffic disappears. Feed activity stops updating + tester.clock().advance(Duration.ofHours(1)); + tester.metricsService().setMetric("writesPerSecond", 0D); + maintainer.maintain(); + assertEquals(t2, deployment.get().activity().lastQueried().get()); + assertEquals(t3, deployment.get().activity().lastWritten().get()); + assertEquals(1, deployment.get().activity().lastQueriesPerSecond().getAsDouble(), Double.MIN_VALUE); + assertEquals(5, deployment.get().activity().lastWritesPerSecond().getAsDouble(), Double.MIN_VALUE); + } @Test - public void maintain() { + public void updates_rotation_status() { DeploymentTester tester = new DeploymentTester(); MetricsServiceMock metricsService = tester.controllerTester().metricsService(); - ApiAuthorityConfig.Builder apiAuthorityConfigBuilder = new ApiAuthorityConfig.Builder().authorities("http://localhost:" + wireMockRule.port() + "/"); - ApiAuthorityConfig apiAuthorityConfig = new ApiAuthorityConfig(apiAuthorityConfigBuilder); - DeploymentMetricsMaintainer maintainer = new DeploymentMetricsMaintainer(tester.controller(), Duration.ofDays(1), new JobControl(tester.controller().curator()), apiAuthorityConfig); + DeploymentMetricsMaintainer maintainer = maintainer(tester.controller()); Application application = tester.createApplication("app1", "tenant1", 1, 1L); ZoneId zone1 = ZoneId.from("prod", "us-west-1"); ZoneId zone2 = ZoneId.from("prod", "us-east-3"); @@ -65,68 +105,32 @@ public class DeploymentMetricsMaintainerTest { .build(); tester.deployCompletely(application, applicationPackage); + Supplier<Application> app = () -> tester.application(application.id()); + Supplier<Deployment> deployment1 = () -> app.get().deployments().get(zone1); + Supplier<Deployment> deployment2 = () -> app.get().deployments().get(zone2); String assignedRotation = "rotation-fqdn-01"; tester.controllerTester().metricsService().addRotation(assignedRotation); + // No status gathered yet + assertEquals(RotationStatus.unknown, app.get().rotationStatus(deployment1.get())); + assertEquals(RotationStatus.unknown, app.get().rotationStatus(deployment2.get())); + // One rotation out, one in metricsService.setZoneIn(assignedRotation, "proxy.prod.us-west-1.vip.test"); metricsService.setZoneOut(assignedRotation,"proxy.prod.us-east-3.vip.test"); - - wireMockRule.stubFor(post(urlEqualTo("/metricforwarding/v1/deploymentmetrics/")) - .willReturn(aResponse().withStatus(200))); maintainer.maintain(); + assertEquals(RotationStatus.in, app.get().rotationStatus(deployment1.get())); + assertEquals(RotationStatus.out, app.get().rotationStatus(deployment2.get())); - List<ServeEvent> allServeEvents = getAllServeEvents(); - assertEquals(1, allServeEvents.size()); - LoggedRequest request = findAll(postRequestedFor(urlEqualTo("/metricforwarding/v1/deploymentmetrics/"))).get(0); - - Slime slime = SlimeUtils.jsonToSlime(request.getBody()); - Inspector inspector = slime.get().entry(0); - assertEquals("tenant1:app1:default", inspector.field("applicationId").asString()); - MetricsService.ApplicationMetrics applicationMetrics = applicationMetricsFromInspector(inspector.field("applicationMetrics")); - assertEquals(0.5, applicationMetrics.queryServiceQuality(), DELTA); - assertEquals(0.7, applicationMetrics.writeServiceQuality(), DELTA); - - Map<String, String> rotationStatus = rotationsStatusFromInspector(inspector.field("rotationStatus")); - assertEquals("in", rotationStatus.get("proxy.prod.us-west-1.vip.test")); - assertEquals("out", rotationStatus.get("proxy.prod.us-east-3.vip.test")); - - Map<String, MetricsService.DeploymentMetrics> deploymentMetricsByZone = deploymentMetricsFromInspector(inspector.field("deploymentMetrics")); - MetricsService.DeploymentMetrics deploymentMetrics = deploymentMetricsByZone.get("prod.us-west-1"); - assertEquals(1.0, deploymentMetrics.queriesPerSecond(), DELTA); - assertEquals(2.0, deploymentMetrics.writesPerSecond(), DELTA); - assertEquals(3.0, deploymentMetrics.documentCount(), DELTA); - assertEquals(4.0, deploymentMetrics.queryLatencyMillis(), DELTA); - assertEquals(5.0, deploymentMetrics.writeLatencyMillis(), DELTA); - - deploymentMetrics = deploymentMetricsByZone.get("prod.us-east-3"); - assertEquals(1.0, deploymentMetrics.queriesPerSecond(), DELTA); - assertEquals(2.0, deploymentMetrics.writesPerSecond(), DELTA); - assertEquals(3.0, deploymentMetrics.documentCount(), DELTA); - assertEquals(4.0, deploymentMetrics.queryLatencyMillis(), DELTA); - assertEquals(5.0, deploymentMetrics.writeLatencyMillis(), DELTA); - } - - private MetricsService.ApplicationMetrics applicationMetricsFromInspector(Inspector inspector) { - return new MetricsService.ApplicationMetrics(inspector.field("queryServiceQuality").asDouble(), inspector.field("writeServiceQuality").asDouble()); + // All rotations in + metricsService.setZoneIn(assignedRotation,"proxy.prod.us-east-3.vip.test"); + maintainer.maintain(); + assertEquals(RotationStatus.in, app.get().rotationStatus(deployment1.get())); + assertEquals(RotationStatus.in, app.get().rotationStatus(deployment2.get())); } - private Map<String, String> rotationsStatusFromInspector(Inspector inspector) { - HashMap<String, String> rotationStatus = new HashMap<>(); - inspector.traverse((ArrayTraverser) (index, entry) -> { - rotationStatus.put(entry.field("hostname").asString(), entry.field("rotationStatus").asString()); - }); - return rotationStatus; + private static DeploymentMetricsMaintainer maintainer(Controller controller) { + return new DeploymentMetricsMaintainer(controller, Duration.ofDays(1), new JobControl(controller.curator())); } - private Map<String, MetricsService.DeploymentMetrics> deploymentMetricsFromInspector(Inspector inspector) { - Map<String, MetricsService.DeploymentMetrics> deploymentMetricByZone = new HashMap<>(); - inspector.traverse((ArrayTraverser) (index, entry) -> { - String zone = entry.field("zoneId").asString(); - MetricsService.DeploymentMetrics deploymentMetrics = new MetricsService.DeploymentMetrics(entry.field("queriesPerSecond").asDouble(), entry.field("writesPerSecond").asDouble(), - entry.field("documentCount").asLong(), entry.field("queryLatencyMillis").asDouble(), entry.field("writeLatencyMillis").asDouble()); - deploymentMetricByZone.put(zone, deploymentMetrics); - }); - return deploymentMetricByZone; - } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java index 094f8989530..e06578a545f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java @@ -83,7 +83,8 @@ public class ApplicationSerializerTest { statusList.add(JobStatus.initial(JobType.systemTest) .withTriggering(Version.fromString("5.6.7"), ApplicationVersion.unknown, empty(), "Test", Instant.ofEpochMilli(7)) - .withCompletion(30, empty(), Instant.ofEpochMilli(8))); + .withCompletion(30, empty(), Instant.ofEpochMilli(8)) + .withPause(OptionalLong.of(1L << 32))); statusList.add(JobStatus.initial(JobType.stagingTest) .withTriggering(Version.fromString("5.6.6"), ApplicationVersion.unknown, empty(), "Test 2", Instant.ofEpochMilli(5)) .withCompletion(11, Optional.of(JobError.unknown), Instant.ofEpochMilli(6))); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java index 36d92620fa2..b82462ad595 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java @@ -49,6 +49,7 @@ import com.yahoo.vespa.hosted.controller.athenz.mock.AthenzDbMock; import com.yahoo.vespa.hosted.controller.authority.config.ApiAuthorityConfig; import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder; import com.yahoo.vespa.hosted.controller.deployment.BuildJob; +import com.yahoo.vespa.hosted.controller.deployment.DeploymentTrigger; import com.yahoo.vespa.hosted.controller.integration.ConfigServerMock; import com.yahoo.vespa.hosted.controller.integration.MetricsServiceMock; import com.yahoo.vespa.hosted.controller.maintenance.DeploymentMetricsMaintainer; @@ -347,15 +348,25 @@ public class ApplicationApiTest extends ControllerContainerTest { // DELETE (cancel) again is a no-op tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", DELETE) - .userIdentity(HOSTED_VESPA_OPERATOR), + .userIdentity(USER_ID), new File("application-deployment-cancelled-no-op.json")); // POST triggering of a full deployment to an application (if version is omitted, current system version is used) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", POST) - .userIdentity(HOSTED_VESPA_OPERATOR) + .userIdentity(USER_ID) .data("6.1.0"), new File("application-deployment.json")); + // POST a pause to a production job + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/default/job/production-us-west-1/pause", POST) + .userIdentity(USER_ID), + "{\"message\":\"production-us-west-1 for tenant1.application1 paused for " + DeploymentTrigger.maxPause + "\"}"); + + // POST a triggering to the same production job + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/default/job/production-us-west-1", POST) + .userIdentity(USER_ID), + "{\"message\":\"Triggered production-us-west-1 for tenant1.application1\"}"); + // POST a 'restart application' command tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/restart", POST) .screwdriverIdentity(SCREWDRIVER_ID), @@ -429,10 +440,38 @@ public class ApplicationApiTest extends ControllerContainerTest { .data(createApplicationSubmissionData(packageWithService)), "{\"version\":\"1.0.43-d00d\"}"); + ApplicationId app1 = ApplicationId.from("tenant1", "application1", "default"); + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/jobreport", POST) + .screwdriverIdentity(SCREWDRIVER_ID) + .data(asJson(new DeploymentJobs.JobReport(app1, + JobType.component, + 1234, + 123, + Optional.of(BuildJob.defaultSourceRevision), + Optional.empty()))), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"" + app1 + " is set up to be deployed from internally," + + " and no longer accepts reports from Screwdriver v3 jobs. If you need to revert " + + "to the old pipeline, please file a ticket at yo/vespa-support and request this.\"}", + 400); + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/default/job/production-us-west-1", DELETE) .userIdentity(USER_ID), "{\"message\":\"Nothing to abort.\"}"); + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/submit", DELETE) + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"message\":\"Unregistered 'tenant1.application1' from internal deployment pipeline.\"}"); + + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/jobreport", POST) + .screwdriverIdentity(SCREWDRIVER_ID) + .data(asJson(new DeploymentJobs.JobReport(app1, + JobType.component, + 1234, + 123, + Optional.of(BuildJob.defaultSourceRevision), + Optional.empty()))), + "{\"message\":\"ok\"}"); + // PUT (create) the authenticated user byte[] data = new byte[0]; tester.assertResponse(request("/application/v4/user?user=new_user&domain=by", PUT) @@ -469,9 +508,8 @@ public class ApplicationApiTest extends ControllerContainerTest { private void addIssues(ContainerControllerTester tester, ApplicationId id) { tester.controller().applications().lockOrThrow(id, application -> - tester.controller().applications().store(application - .withDeploymentIssueId(IssueId.from("123")) - .withOwnershipIssueId(IssueId.from("321")))); + tester.controller().applications().store(application.withDeploymentIssueId(IssueId.from("123")) + .withOwnershipIssueId(IssueId.from("321")))); } @Test diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-deployment.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-deployment.json index e3c0bbe0679..d2531638a93 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-deployment.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/application-deployment.json @@ -1 +1 @@ -{"message":"Triggered upgrade to 6.1 for application 'tenant1.application1'"}
\ No newline at end of file +{"message":"Triggered upgrade to 6.1 for tenant1.application1"}
\ No newline at end of file diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilterTest.java index 22a527bf3d3..19aa247edb4 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilterTest.java @@ -70,7 +70,7 @@ public class ControllerAuthorizationFilterTest { List<AthenzIdentity> allowed = singletonList(HOSTED_OPERATOR); List<AthenzIdentity> forbidden = singletonList(USER); - testApiAccess(PUT, "/application/v4/tenant/mytenant/application/myapp/deploying", + testApiAccess(PUT, "/zone/v2/hello-proxy-path", allowed, forbidden, filter); testApiAccess(POST, "/screwdriver/v1/trigger/tenant/mytenant/application/myapp/", allowed, forbidden, filter); |