WorkflowResource { private Response<WorkflowState> patchState(String componentId, String id, Request request, AuthContext ac) { final Optional<ByteString> payload = request.payload(); if (payload.isEmpty()) { return Response.forStatus(Status.BAD_REQUEST.withReasonPhrase("Missing payload.")); } final WorkflowId workflowId = WorkflowId.create(componentId, id); workflowActionAuthorizer.authorizeWorkflowAction(ac, workflowId); final WorkflowState patchState; try { patchState = OBJECT_MAPPER.readValue(payload.get().toByteArray(), WorkflowState.class); } catch (IOException e) { return Response.forStatus(Status.BAD_REQUEST.withReasonPhrase("Invalid payload.")); } try { storage.patchState(workflowId, patchState); } catch (ResourceNotFoundException e) { return Response.forStatus(Status.NOT_FOUND.withReasonPhrase(e.getMessage())); } catch (IOException e) { throw new RuntimeException("Failed to update the state of workflow " + workflowId.toKey(), e); } return state(componentId, id); } WorkflowResource(Storage storage, WorkflowValidator workflowValidator,
                          WorkflowInitializer workflowInitializer,
                          BiConsumer<Optional<Workflow>, Optional<Workflow>> workflowConsumer,
                          WorkflowActionAuthorizer workflowActionAuthorizer); Stream<Route<AsyncHandler<Response<ByteString>>>> routes(RequestAuthenticator requestAuthenticator);  }
@Test public void patchShouldFailWithForbiddenIfNotAuthorized() throws Exception { sinceVersion(Api.Version.V3); doThrow(new ResponseException(Response.forStatus(FORBIDDEN))) .when(workflowActionAuthorizer).authorizeWorkflowAction(any(), any(WorkflowId.class)); final Response<ByteString> response = awaitResponse(serviceHelper.request("PATCH", path("/foo/bar/state"), STATEPAYLOAD_FULL)); assertThat(response, hasStatus(withCode(FORBIDDEN))); verify(storage, never()).patchState(any(), any()); }
@Test public void shouldFailToPatchStateOfNonexistWorkflow() throws Exception { sinceVersion(Api.Version.V3); doThrow(new ResourceNotFoundException("")) .when(storage).patchState(WorkflowId.create("foo", "bar"), WorkflowState.patchEnabled(true)); Response<ByteString> response = awaitResponse(serviceHelper.request("PATCH", path("/foo/bar/state"), STATEPAYLOAD_ENABLED)); assertThat(response, hasStatus(withCode(Status.NOT_FOUND))); }
@Test public void shouldFailToPatchStateOfWorkflowDueToStorageError() throws Exception { sinceVersion(Api.Version.V3); doThrow(new IOException()) .when(storage).patchState(WorkflowId.create("foo", "bar"), WorkflowState.patchEnabled(true)); Response<ByteString> response = awaitResponse(serviceHelper.request("PATCH", path("/foo/bar/state"), STATEPAYLOAD_ENABLED)); assertThat(response, hasStatus(withCode(Status.INTERNAL_SERVER_ERROR))); }
@Test public void shouldReturnCurrentWorkflowState() throws Exception { sinceVersion(Api.Version.V3); Response<ByteString> response = awaitResponse(serviceHelper.request("GET", path("/foo/bar/state"))); assertThat(response, hasStatus(withCode(Status.OK))); assertJson(response, "enabled", equalTo(false)); storage.patchState(WORKFLOW.id(), WorkflowState.patchEnabled(true)); response = awaitResponse(serviceHelper.request("GET", path("/foo/bar/state"))); assertThat(response, hasStatus(withCode(Status.OK))); assertJson(response, "enabled", equalTo(true)); }
@Test public void shouldTailPaginateWorkflowInstancesData() throws Exception { sinceVersion(Api.Version.V3); final WorkflowState workflowState = WorkflowState.builder() .nextNaturalTrigger(ParameterUtil.parseDate("2016-08-14")) .build(); storage.patchState(WORKFLOW.id(), workflowState); WorkflowInstance wfi1 = WorkflowInstance.create(WORKFLOW.id(), "2016-08-11"); WorkflowInstance wfi2 = WorkflowInstance.create(WORKFLOW.id(), "2016-08-12"); WorkflowInstance wfi3 = WorkflowInstance.create(WORKFLOW.id(), "2016-08-13"); storage.writeEvent(create(Event.triggerExecution(wfi1, NATURAL_TRIGGER, TRIGGER_PARAMETERS), 0L, ms("07:00:00"))); storage.writeEvent(create(Event.triggerExecution(wfi2, NATURAL_TRIGGER, TRIGGER_PARAMETERS), 0L, ms("07:00:00"))); storage.writeEvent(create(Event.triggerExecution(wfi3, NATURAL_TRIGGER, TRIGGER_PARAMETERS), 0L, ms("07:00:00"))); Response<ByteString> response = awaitResponse( serviceHelper.request("GET", path("/foo/bar/instances?limit=2&tail=true"))); assertThat(response, hasStatus(withCode(Status.OK))); assertJson(response, "[*]", hasSize(2)); assertJson(response, "[0].workflow_instance.parameter", is("2016-08-12")); assertJson(response, "[1].workflow_instance.parameter", is("2016-08-13")); }
@Test public void createWorkflowShouldFailWithForbiddenIfNotAuthorized() throws Exception { sinceVersion(Api.Version.V3); doThrow(new ResponseException(Response.forStatus(FORBIDDEN))) .when(workflowActionAuthorizer).authorizeWorkflowAction(any(), any(Workflow.class)); final Response<ByteString> response = awaitResponse( serviceHelper.request("POST", path("/foo"), serialize(WORKFLOW_CONFIGURATION))); assertThat(response, hasStatus(withCode(FORBIDDEN))); verify(storage, never()).patchState(any(), any()); verifyNoInteractions(workflowValidator); verifyNoInteractions(workflowInitializer); verifyNoInteractions(workflowConsumer); }