@Test public void itForbidsQuotesInDeployIds() throws Exception { final String badDeployId = "deployKey'"; SingularityDeploy singularityDeploy = SingularityDeploy.newBuilder(badDeployId, badDeployId).build(); SingularityRequest singularityRequest = new SingularityRequestBuilder(badDeployId, RequestType.SERVICE).build(); WebApplicationException exn = (WebApplicationException) catchThrowable(() -> validator.checkDeploy(singularityRequest, singularityDeploy, Collections.emptyList(), Collections.emptyList())); assertThat((String) exn.getResponse().getEntity()) .contains("[a-zA-Z0-9_.]"); }
@Test(expected = WebApplicationException.class) public void itForbidsBracketCharactersInDeployIds() throws Exception { final String badDeployId = "deployKey[["; SingularityDeploy singularityDeploy = SingularityDeploy.newBuilder(badDeployId, badDeployId).build(); SingularityRequest singularityRequest = new SingularityRequestBuilder(badDeployId, RequestType.SERVICE).build(); validator.checkDeploy(singularityRequest, singularityDeploy, Collections.emptyList(), Collections.emptyList()); }
@Test public void itForbidsHealthCheckStartupDelaysLongerThanKillWait() { // Default kill wait time is 10 minutes (600 seconds) HealthcheckOptions healthCheck = new HealthcheckOptionsBuilder("/") .setPortNumber(Optional.of(8080L)) .setStartupDelaySeconds(Optional.of(10000)) .build(); SingularityDeploy deploy = SingularityDeploy .newBuilder("1234567", "1234567") .setHealthcheck(Optional.of(healthCheck)) .build(); SingularityRequest request = new SingularityRequestBuilder("1234567", RequestType.SERVICE).build(); WebApplicationException exn = (WebApplicationException) catchThrowable(() -> validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList())); assertThat((String) exn.getResponse().getEntity()) .contains("Health check startup delay"); }
@Test(expected = WebApplicationException.class) public void itForbidsTooLongDeployId() { String requestId = "requestId"; SingularityRequest request = new SingularityRequestBuilder(requestId, RequestType.SCHEDULED) .build(); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, tooLongId()) .build(); validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList()); }
@Test(expected = WebApplicationException.class) public void whenDeployNotOneOffOrScheduledItForbidsRunImmediately() { String requestId = "request"; String deployID = "deploy"; SingularityRequest request = new SingularityRequestBuilder(requestId, RequestType.WORKER) .build(); Optional<SingularityRunNowRequest> runNowRequest = Optional.of(runNowRequest()); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, deployID) .setCommand(Optional.of("printenv")) .setRunImmediately(runNowRequest) .build(); validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList()); }
@Test(expected = WebApplicationException.class) public void whenDeployHasRunNowSetItValidatesThatItIsLessThanACertaionLength() { String requestId = "request"; String deployID = "deploy"; SingularityRequest request = new SingularityRequestBuilder(requestId, RequestType.ON_DEMAND) .build(); Optional<SingularityRunNowRequest> runNowRequest = Optional.of(runNowRequest(tooLongId())); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, deployID) .setCommand(Optional.of("printenv")) .setRunImmediately(runNowRequest) .build(); validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList()); }
@Test public void whenDeployHasRunNowSetAndNotDeployedItWillRunImmediately() { String requestId = "request"; String deployID = "deploy"; SingularityRequest request = new SingularityRequestBuilder(requestId, RequestType.ON_DEMAND) .build(); Optional<SingularityRunNowRequest> runNowRequest = Optional.of(runNowRequest()); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, deployID) .setCommand(Optional.of("printenv")) .setRunImmediately(runNowRequest) .build(); SingularityDeploy result = validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList()); Assert.assertTrue(result.getRunImmediately().isPresent()); Assert.assertTrue(result.getRunImmediately().get().getRunId().isPresent()); }
@Test public void itForbidsHealthCheckGreaterThanMaxTotalHealthCheck() { singularityConfiguration.setHealthcheckMaxTotalTimeoutSeconds(Optional.of(100)); createValidator(); // Total wait time on this request is (startup time) + ((interval) + (http timeout)) * (1 + retries) // = 50 + (5 + 5) * (9 + 1) // = 150 HealthcheckOptions healthCheck = new HealthcheckOptionsBuilder("/") .setPortNumber(Optional.of(8080L)) .setStartupTimeoutSeconds(Optional.of(50)) .setIntervalSeconds(Optional.of(5)) .setResponseTimeoutSeconds(Optional.of(5)) .setMaxRetries(Optional.of(9)) .build(); SingularityDeploy deploy = SingularityDeploy .newBuilder("1234567", "1234567") .setHealthcheck(Optional.of(healthCheck)) .setCommand(Optional.of("sleep 100;")) .build(); SingularityRequest request = new SingularityRequestBuilder("1234567", RequestType.SERVICE).build(); WebApplicationException exn = (WebApplicationException) catchThrowable(() -> validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList())); assertThat((String) exn.getResponse().getEntity()) .contains("Max healthcheck time"); }
@Test public void testImmediateRunReplacesScheduledTask() { initScheduledRequest(); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, firstDeployId) .setCommand(Optional.of("sleep 100")) .build(); SingularityDeployRequest singularityDeployRequest = new SingularityDeployRequest(deploy, Optional.absent(), Optional.absent(), Optional.absent()); deployResource.deploy(singularityDeployRequest, singularityUser); scheduler.drainPendingQueue(); SingularityPendingTask task1 = createAndSchedulePendingTask(firstDeployId); Assert.assertEquals(1, taskManager.getPendingTaskIds().size()); Assert.assertEquals(PendingType.NEW_DEPLOY, taskManager.getPendingTaskIds().get(0).getPendingType()); requestManager.addToPendingQueue(new SingularityPendingRequest(requestId, deploy.getId(), System.currentTimeMillis(), Optional.absent(), PendingType.IMMEDIATE, deploy.getSkipHealthchecksOnDeploy(), Optional.absent())); scheduler.drainPendingQueue(); Assert.assertEquals(1, taskManager.getPendingTaskIds().size()); Assert.assertEquals(PendingType.IMMEDIATE, taskManager.getPendingTaskIds().get(0).getPendingType()); }
@Test public void testSchedulerDropsMultipleScheduledTaskInstances() { initScheduledRequest(); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, firstDeployId) .setCommand(Optional.of("sleep 100")) .build(); SingularityDeployRequest singularityDeployRequest = new SingularityDeployRequest(deploy, Optional.absent(), Optional.absent(), Optional.absent()); deployResource.deploy(singularityDeployRequest, singularityUser); scheduler.drainPendingQueue(); requestManager.addToPendingQueue(new SingularityPendingRequest(requestId, firstDeployId, Instant.now().plus(3, ChronoUnit.DAYS).toEpochMilli(), Optional.absent(), PendingType.NEW_DEPLOY, Optional.absent(), Optional.absent())); SingularityRunNowRequest runNowRequest = new SingularityRunNowRequestBuilder().build(); requestResource.scheduleImmediately(singularityUser, requestId, runNowRequest); Assert.assertEquals("Both requests make it into the pending queue", 2, requestManager.getPendingRequests().size()); Assert.assertEquals(PendingType.IMMEDIATE, requestManager.getPendingRequests().get(0).getPendingType()); Assert.assertEquals(PendingType.NEW_DEPLOY, requestManager.getPendingRequests().get(1).getPendingType()); scheduler.drainPendingQueue(); Assertions.assertThat(taskManager.getPendingTaskIds()) .describedAs("Only the immediate request gets run") .hasSize(1) .extracting(SingularityPendingTaskId::getPendingType) .containsExactly(PendingType.IMMEDIATE); Assertions.assertThat(requestManager.getPendingRequests()) .describedAs("The scheduled request is dropped from the pending queue") .hasSize(0); }
@Test public void itForbidsQuotesInDeployIds() throws Exception { final String badDeployId = "deployKey'"; SingularityDeploy singularityDeploy = SingularityDeploy.newBuilder(badDeployId, badDeployId).build(); SingularityRequest singularityRequest = new SingularityRequestBuilder(badDeployId, RequestType.SERVICE).build(); WebApplicationException exn = (WebApplicationException) catchThrowable(() -> validator.checkDeploy(singularityRequest, singularityDeploy, Collections.emptyList(), Collections.emptyList())); assertThat((String) exn.getResponse().getEntity()) .contains("[a-zA-Z0-9_.]"); }
@Test(expected = WebApplicationException.class) public void itForbidsBracketCharactersInDeployIds() throws Exception { final String badDeployId = "deployKey[["; SingularityDeploy singularityDeploy = SingularityDeploy.newBuilder(badDeployId, badDeployId).build(); SingularityRequest singularityRequest = new SingularityRequestBuilder(badDeployId, RequestType.SERVICE).build(); validator.checkDeploy(singularityRequest, singularityDeploy, Collections.emptyList(), Collections.emptyList()); }
@Test(expected = WebApplicationException.class) public void whenDeployNotOneOffOrScheduledItForbidsRunImmediately() { String requestId = "request"; String deployID = "deploy"; SingularityRequest request = new SingularityRequestBuilder(requestId, RequestType.WORKER) .build(); Optional<SingularityRunNowRequest> runNowRequest = Optional.of(runNowRequest()); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, deployID) .setCommand(Optional.of("printenv")) .setRunImmediately(runNowRequest) .build(); validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList()); }
@Test public void itForbidsHealthCheckStartupDelaysLongerThanKillWait() { // Default kill wait time is 10 minutes (600 seconds) HealthcheckOptions healthCheck = new HealthcheckOptionsBuilder("/") .setPortNumber(Optional.of(8080L)) .setStartupDelaySeconds(Optional.of(10000)) .build(); SingularityDeploy deploy = SingularityDeploy .newBuilder("1234567", "1234567") .setHealthcheck(Optional.of(healthCheck)) .build(); SingularityRequest request = new SingularityRequestBuilder("1234567", RequestType.SERVICE).build(); WebApplicationException exn = (WebApplicationException) catchThrowable(() -> validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList())); assertThat((String) exn.getResponse().getEntity()) .contains("Health check startup delay"); }
@Test(expected = WebApplicationException.class) public void itForbidsTooLongDeployId() { String requestId = "requestId"; SingularityRequest request = new SingularityRequestBuilder(requestId, RequestType.SCHEDULED) .build(); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, tooLongId()) .build(); validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList()); }
@Test(expected = WebApplicationException.class) public void whenDeployHasRunNowSetItValidatesThatItIsLessThanACertaionLength() { String requestId = "request"; String deployID = "deploy"; SingularityRequest request = new SingularityRequestBuilder(requestId, RequestType.ON_DEMAND) .build(); Optional<SingularityRunNowRequest> runNowRequest = Optional.of(runNowRequest(tooLongId())); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, deployID) .setCommand(Optional.of("printenv")) .setRunImmediately(runNowRequest) .build(); validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList()); }
@Test public void whenDeployHasRunNowSetAndNotDeployedItWillRunImmediately() { String requestId = "request"; String deployID = "deploy"; SingularityRequest request = new SingularityRequestBuilder(requestId, RequestType.ON_DEMAND) .build(); Optional<SingularityRunNowRequest> runNowRequest = Optional.of(runNowRequest()); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, deployID) .setCommand(Optional.of("printenv")) .setRunImmediately(runNowRequest) .build(); SingularityDeploy result = validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList()); Assert.assertTrue(result.getRunImmediately().isPresent()); Assert.assertTrue(result.getRunImmediately().get().getRunId().isPresent()); }
@Test public void itForbidsHealthCheckGreaterThanMaxTotalHealthCheck() { singularityConfiguration.setHealthcheckMaxTotalTimeoutSeconds(Optional.of(100)); createValidator(); // Total wait time on this request is (startup time) + ((interval) + (http timeout)) * (1 + retries) // = 50 + (5 + 5) * (9 + 1) // = 150 HealthcheckOptions healthCheck = new HealthcheckOptionsBuilder("/") .setPortNumber(Optional.of(8080L)) .setStartupTimeoutSeconds(Optional.of(50)) .setIntervalSeconds(Optional.of(5)) .setResponseTimeoutSeconds(Optional.of(5)) .setMaxRetries(Optional.of(9)) .build(); SingularityDeploy deploy = SingularityDeploy .newBuilder("1234567", "1234567") .setHealthcheck(Optional.of(healthCheck)) .setCommand(Optional.of("sleep 100;")) .build(); SingularityRequest request = new SingularityRequestBuilder("1234567", RequestType.SERVICE).build(); WebApplicationException exn = (WebApplicationException) catchThrowable(() -> validator.checkDeploy(request, deploy, Collections.emptyList(), Collections.emptyList())); assertThat((String) exn.getResponse().getEntity()) .contains("Max healthcheck time"); }
@Test public void testImmediateRunReplacesScheduledTask() { initScheduledRequest(); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, firstDeployId) .setCommand(Optional.of("sleep 100")) .build(); SingularityDeployRequest singularityDeployRequest = new SingularityDeployRequest(deploy, Optional.absent(), Optional.absent(), Optional.absent()); deployResource.deploy(singularityDeployRequest, singularityUser); scheduler.drainPendingQueue(); SingularityPendingTask task1 = createAndSchedulePendingTask(firstDeployId); Assert.assertEquals(1, taskManager.getPendingTaskIds().size()); Assert.assertEquals(PendingType.NEW_DEPLOY, taskManager.getPendingTaskIds().get(0).getPendingType()); requestManager.addToPendingQueue(new SingularityPendingRequest(requestId, deploy.getId(), System.currentTimeMillis(), Optional.absent(), PendingType.IMMEDIATE, deploy.getSkipHealthchecksOnDeploy(), Optional.absent())); scheduler.drainPendingQueue(); Assert.assertEquals(1, taskManager.getPendingTaskIds().size()); Assert.assertEquals(PendingType.IMMEDIATE, taskManager.getPendingTaskIds().get(0).getPendingType()); }
@Test public void testSchedulerDropsMultipleScheduledTaskInstances() { initScheduledRequest(); SingularityDeploy deploy = SingularityDeploy.newBuilder(requestId, firstDeployId) .setCommand(Optional.of("sleep 100")) .build(); SingularityDeployRequest singularityDeployRequest = new SingularityDeployRequest(deploy, Optional.absent(), Optional.absent(), Optional.absent()); deployResource.deploy(singularityDeployRequest, singularityUser); scheduler.drainPendingQueue(); requestManager.addToPendingQueue(new SingularityPendingRequest(requestId, firstDeployId, Instant.now().plus(3, ChronoUnit.DAYS).toEpochMilli(), Optional.absent(), PendingType.NEW_DEPLOY, Optional.absent(), Optional.absent())); SingularityRunNowRequest runNowRequest = new SingularityRunNowRequestBuilder().build(); requestResource.scheduleImmediately(singularityUser, requestId, runNowRequest); Assert.assertEquals("Both requests make it into the pending queue", 2, requestManager.getPendingRequests().size()); Assert.assertEquals(PendingType.IMMEDIATE, requestManager.getPendingRequests().get(0).getPendingType()); Assert.assertEquals(PendingType.NEW_DEPLOY, requestManager.getPendingRequests().get(1).getPendingType()); scheduler.drainPendingQueue(); Assertions.assertThat(taskManager.getPendingTaskIds()) .describedAs("Only the immediate request gets run") .hasSize(1) .extracting(SingularityPendingTaskId::getPendingType) .containsExactly(PendingType.IMMEDIATE); Assertions.assertThat(requestManager.getPendingRequests()) .describedAs("The scheduled request is dropped from the pending queue") .hasSize(0); }