From 2d6b7a3dbccbf7dc39fce0ab7e844836afba4f5c Mon Sep 17 00:00:00 2001 From: Corneil du Plessis Date: Mon, 11 Nov 2024 16:48:21 +0200 Subject: [PATCH] Back port of Task Thin Execution List and List By Name Updates api docs for tasks/thinexecutions/name and all HATEOAS links. Updates related tests for links. Fixes #5995 --- .../rest/documentation/ApiDocumentation.java | 4 + .../TaskExecutionsDocumentation.java | 23 ++++ .../src/main/asciidoc/api-guide.adoc | 127 ++++++++++++++++++ .../dataflow/rest/client/TaskOperations.java | 8 ++ .../dataflow/rest/client/TaskTemplate.java | 20 ++- .../server/controller/RootController.java | 1 + .../TaskExecutionControllerTests.java | 11 ++ .../resources/root-controller-result.json | 4 + src/scripts/build-docs.sh | 2 +- 9 files changed, 198 insertions(+), 2 deletions(-) diff --git a/spring-cloud-dataflow-classic-docs/src/test/java/org/springframework/cloud/dataflow/server/rest/documentation/ApiDocumentation.java b/spring-cloud-dataflow-classic-docs/src/test/java/org/springframework/cloud/dataflow/server/rest/documentation/ApiDocumentation.java index d024765da6..5d07a4c7f8 100644 --- a/spring-cloud-dataflow-classic-docs/src/test/java/org/springframework/cloud/dataflow/server/rest/documentation/ApiDocumentation.java +++ b/spring-cloud-dataflow-classic-docs/src/test/java/org/springframework/cloud/dataflow/server/rest/documentation/ApiDocumentation.java @@ -124,6 +124,7 @@ public void index() throws Exception { linkWithRel("tasks/platforms").description("Provides platform accounts for launching tasks. The results can be filtered to show the platforms that support scheduling by adding a request parameter of 'schedulesEnabled=true"), linkWithRel("tasks/logs").description("Retrieve the task application log"), linkWithRel("tasks/thinexecutions").description("Returns thin Task executions"), + linkWithRel("tasks/thinexecutions/name").description("Returns all thin Task executions for a given Task name"), linkWithRel("schema/versions").description("List of Spring Boot related schemas"), linkWithRel("schema/targets").description("List of schema targets"), @@ -234,6 +235,9 @@ public void index() throws Exception { fieldWithPath("_links.tasks/thinexecutions.href").description("Link to the tasks/thinexecutions"), + fieldWithPath("_links.tasks/thinexecutions/name.href").description("Link to the tasks/thinexecutions/name"), + fieldWithPath("_links.tasks/thinexecutions/name.templated").type(JsonFieldType.BOOLEAN).optional().description("Link to the tasks/thinexecutions/name is templated"), + fieldWithPath("_links.tasks/schedules.href").description("Link to the tasks/executions/schedules"), fieldWithPath("_links.tasks/schedules/instances.href").description("Link to the tasks/schedules/instances"), fieldWithPath("_links.tasks/schedules/instances.templated").type(JsonFieldType.BOOLEAN).optional().description("Link tasks/schedules/instances is templated"), diff --git a/spring-cloud-dataflow-classic-docs/src/test/java/org/springframework/cloud/dataflow/server/rest/documentation/TaskExecutionsDocumentation.java b/spring-cloud-dataflow-classic-docs/src/test/java/org/springframework/cloud/dataflow/server/rest/documentation/TaskExecutionsDocumentation.java index 6d4690a841..91925ac91e 100644 --- a/spring-cloud-dataflow-classic-docs/src/test/java/org/springframework/cloud/dataflow/server/rest/documentation/TaskExecutionsDocumentation.java +++ b/spring-cloud-dataflow-classic-docs/src/test/java/org/springframework/cloud/dataflow/server/rest/documentation/TaskExecutionsDocumentation.java @@ -314,6 +314,29 @@ public void listTaskExecutionsByName() throws Exception { subsectionWithPath("page").description("Pagination properties")))); } + @Test + public void listTaskThinExecutionsByName() throws Exception { + this.mockMvc.perform( + get("/tasks/thinexecutions") + .param("name", "taskB") + .param("page", "0") + .param("size", "10") + ) + .andExpect(status().isOk()).andDo(this.documentationHandler.document( + requestParameters( + parameterWithName("page") + .description("The zero-based page number (optional)"), + parameterWithName("size") + .description("The requested page size (optional)"), + parameterWithName("name") + .description("The name associated with the task execution")), + responseFields( + subsectionWithPath("_embedded.taskExecutionThinResourceList") + .description("Contains a collection of Task Executions/"), + subsectionWithPath("_links.self").description("Link to the task execution resource"), + subsectionWithPath("page").description("Pagination properties")))); + } + @Test public void stopTask() throws Exception { this.mockMvc.perform( diff --git a/spring-cloud-dataflow-docs/src/main/asciidoc/api-guide.adoc b/spring-cloud-dataflow-docs/src/main/asciidoc/api-guide.adoc index c96804b6da..4e9c99412c 100644 --- a/spring-cloud-dataflow-docs/src/main/asciidoc/api-guide.adoc +++ b/spring-cloud-dataflow-docs/src/main/asciidoc/api-guide.adoc @@ -1862,6 +1862,8 @@ The following topics provide more details: * <> * <> * <> +* <> +* <> * <> * <> * <> @@ -2066,7 +2068,132 @@ include::{snippets}/task-executions-documentation/list-task-executions-by-name/c include::{snippets}/task-executions-documentation/list-task-executions-by-name/http-response.adoc[] +[[api-guide-resources-task-thin-executions-list]] +==== List All Task Thin Executions +The task executions endpoint lets you list all task executions with only top-level data. +The following topics provide more details: + +* <> +* <> +* <> +* <> + +[[api-guide-resources-task-thin-executions-list-request-structure]] +===== Request Structure + +include::{snippets}/task-executions-documentation/list-task-thin-executions/http-request.adoc[] + +[[api-guide-resources-task-thin-executions-list-request-parameters]] +===== Request Parameters + +include::{snippets}/task-executions-documentation/list-task-thin-executions/query-parameters.adoc[] + +[[api-guide-resources-task-thin-executions-list-example-request]] +===== Example Request + +include::{snippets}/task-executions-documentation/list-task-thin-executions/curl-request.adoc[] + +[[api-guide-resources-task-thin-executions-list-response-structure]] +===== Response Structure + +include::{snippets}/task-executions-documentation/list-task-thin-executions/http-response.adoc[] + +[[api-guide-resources-task-thin-executions-list-by-name]] +==== List All Task Thin Executions With a Specified Task Name + +The task thin executions endpoint lets you list task executions with a specified task name. +The following topics provide more details: + +* <> +* <> +* <> +* <> + + + +[[api-guide-resources-task-thin-executions-list-by-name-request-structure]] +===== Request Structure + +include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/http-request.adoc[] + + + +[[api-guide-resources-task-thin-executions-list-by-name-request-parameters]] +===== Request Parameters + +include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/query-parameters.adoc[] + + + +[[api-guide-resources-task-thin-executions-list-by-name-example-request]] +===== Example Request + +include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/curl-request.adoc[] + +[[api-guide-resources-task-thin-executions-list-by-name-response-structure]] +===== Response Structure + +include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/http-response.adoc[] + +[[api-guide-resources-task-thin-executions-list-request-structure]] +===== Request Structure + +include::{snippets}/task-executions-documentation/list-task-thin-executions/http-request.adoc[] + + + +[[api-guide-resources-task-thin-executions-list-request-parameters]] +===== Request Parameters + +include::{snippets}/task-executions-documentation/list-task-thin-executions/request-parameters.adoc[] + + + +[[api-guide-resources-task-thin-executions-list-example-request]] +===== Example Request + +include::{snippets}/task-executions-documentation/list-task-thin-executions/curl-request.adoc[] + + + +[[api-guide-resources-task-thin-executions-list-response-structure]] +===== Response Structure + +include::{snippets}/task-executions-documentation/list-task-thin-executions/http-response.adoc[] + + + +[[api-guide-resources-task-thin-executions-list-by-name]] +==== List All Task Thin Executions With a Specified Task Name + +The task thin executions endpoint lets you list task executions with a specified task name. +The following topics provide more details: + +* <> +* <> +* <> +* <> + +[[api-guide-resources-task-thin-executions-list-by-name-request-structure]] +===== Request Structure + +include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/http-request.adoc[] + +[[api-guide-resources-task-thin-executions-list-by-name-request-parameters]] +===== Request Parameters + +include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/request-parameters.adoc[] + +[[api-guide-resources-task-thin-executions-list-by-name-example-request]] +===== Example Request + +include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/curl-request.adoc[] + +[[api-guide-resources-task-thin-executions-list-by-name-response-structure]] +===== Response Structure + +include::{snippets}/task-executions-documentation/list-task-thin-executions-by-name/http-response.adoc[] [[api-guide-resources-task-executions-detail]] ==== Task Execution Detail diff --git a/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/TaskOperations.java b/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/TaskOperations.java index c38cc83135..b47bfba585 100644 --- a/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/TaskOperations.java +++ b/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/TaskOperations.java @@ -123,6 +123,14 @@ public interface TaskOperations { */ PagedModel executionListByTaskName(String taskName); + /** + * List task thin executions known to the system filtered by task name. + * + * @param taskName of the executions. + * @return the list of thin task executions known to the system. + */ + PagedModel thinExecutionListByTaskName(String taskName); + /** * Return the {@link TaskExecutionResource} for the id specified. * diff --git a/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/TaskTemplate.java b/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/TaskTemplate.java index 1d84bf20a6..eaeb84df42 100644 --- a/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/TaskTemplate.java +++ b/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/TaskTemplate.java @@ -76,6 +76,8 @@ public class TaskTemplate implements TaskOperations { private static final String THIN_EXECUTIONS_RELATION = "tasks/thinexecutions"; + private static final String THIN_EXECUTIONS_BY_NAME_RELATION = "tasks/thinexecutions/name"; + private static final String EXECUTIONS_CURRENT_RELATION = "tasks/executions/current"; private static final String EXECUTION_RELATION = "tasks/executions/execution"; @@ -102,6 +104,8 @@ public class TaskTemplate implements TaskOperations { private final Link thinExecutionsLink; + private final Link thinExecutionsByNameLink; + private final Link executionLink; private final Link executionLaunchLink; @@ -158,6 +162,11 @@ public class TaskTemplate implements TaskOperations { this.thinExecutionsLink = null; } + if(resources.getLink(THIN_EXECUTIONS_BY_NAME_RELATION).isPresent()) { + this.thinExecutionsByNameLink = resources.getLink(THIN_EXECUTIONS_BY_NAME_RELATION).get(); + } else { + this.thinExecutionsByNameLink = null; + } if (VersionUtils.isDataFlowServerVersionGreaterThanOrEqualToRequiredVersion(version, VALIDATION_TASK_LAUNCH_VERSION)) { Assert.isTrue(resources.getLink(EXECUTION_LAUNCH_RELATION).isPresent(), () -> EXECUTION_LAUNCH_RELATION + " relation is required"); this.executionLaunchLink = resources.getLink(EXECUTION_LAUNCH_RELATION).get(); @@ -283,7 +292,7 @@ public TaskExecutionResource.Page executionList() { } @Override - public PagedModel thinExecutionList() { + public TaskExecutionThinResource.Page thinExecutionList() { if(thinExecutionsLink != null) { return restTemplate.getForObject(thinExecutionsLink.getHref(), TaskExecutionThinResource.Page.class); } else { @@ -291,6 +300,15 @@ public PagedModel thinExecutionList() { } } + @Override + public TaskExecutionThinResource.Page thinExecutionListByTaskName(String taskName) { + if(thinExecutionsByNameLink != null) { + return restTemplate.getForObject(thinExecutionsByNameLink.expand(taskName).getHref(), TaskExecutionThinResource.Page.class); + } else { + return restTemplate.getForObject(executionsLink.expand(taskName).getHref(), TaskExecutionThinResource.Page.class); + } + } + @Override public TaskExecutionResource.Page executionListByTaskName(String taskName) { return restTemplate.getForObject(executionByNameLink.expand(taskName).getHref(), diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/RootController.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/RootController.java index ff55fb6ec3..d45beb0a95 100644 --- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/RootController.java +++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/controller/RootController.java @@ -159,6 +159,7 @@ public RootResource info() { root.add(linkTo(methodOn(TasksInfoController.class).getInfo(null, null, null)).withRel("tasks/info/executions")); root.add(linkTo(methodOn(TaskLogsController.class).getLog(null, null, null)).withRel("tasks/logs")); root.add(linkTo(methodOn(TaskExecutionThinController.class).listTasks(null, null)).withRel("tasks/thinexecutions")); + root.add(linkTo(methodOn(TaskExecutionThinController.class).retrieveTasksByName(null, null, null)).withRel("tasks/thinexecutions/name")); if (featuresProperties.isSchedulesEnabled()) { root.add(entityLinks.linkToCollectionResource(ScheduleInfoResource.class).withRel("tasks/schedules")); String scheduleTemplated = entityLinks.linkToCollectionResource(ScheduleInfoResource.class).getHref() diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/TaskExecutionControllerTests.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/TaskExecutionControllerTests.java index a4bcbf1302..686d6d06f9 100644 --- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/TaskExecutionControllerTests.java +++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/controller/TaskExecutionControllerTests.java @@ -374,6 +374,17 @@ void getAllThinExecutions() throws Exception { .andExpect(jsonPath("$._embedded.taskExecutionThinResourceList", hasSize(4))); } + + @Test + void getThinExecutionsByTaskName() throws Exception { + mockMvc.perform(get("/tasks/thinexecutions").queryParam("name", TASK_NAME_ORIG).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.taskExecutionThinResourceList[*].executionId", containsInAnyOrder(2, 1))) + .andExpect(jsonPath("$._embedded.taskExecutionThinResourceList[*].parentExecutionId", containsInAnyOrder(null, 1))) + .andExpect(jsonPath("$._embedded.taskExecutionThinResourceList[*].taskExecutionStatus", containsInAnyOrder("RUNNING", "RUNNING"))) + .andExpect(jsonPath("$._embedded.taskExecutionThinResourceList", hasSize(2))); + } + @Test void getCurrentExecutions() throws Exception { when(taskLauncher.getRunningTaskExecutionCount()).thenReturn(4); diff --git a/spring-cloud-dataflow-server-core/src/test/resources/root-controller-result.json b/spring-cloud-dataflow-server-core/src/test/resources/root-controller-result.json index 74ca47aa6b..16eb48ca70 100644 --- a/spring-cloud-dataflow-server-core/src/test/resources/root-controller-result.json +++ b/spring-cloud-dataflow-server-core/src/test/resources/root-controller-result.json @@ -156,6 +156,10 @@ "tasks/thinexecutions": { "href":"http://localhost/tasks/thinexecutions" }, + "tasks/thinexecutions/name": { + "href":"http://localhost/tasks/thinexecutions/?name={name}", + "templated": true + }, "jobs/executions": { "href": "http://localhost/jobs/executions" }, diff --git a/src/scripts/build-docs.sh b/src/scripts/build-docs.sh index 8f7870a359..36d5e17d55 100755 --- a/src/scripts/build-docs.sh +++ b/src/scripts/build-docs.sh @@ -5,6 +5,6 @@ if [ -z "$BASH_VERSION" ]; then fi SCDIR=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")") SCDIR=$(realpath $SCDIR) -pushd "$SCDIR" > /dev/null || exit +pushd "$SCDIR/../.." > /dev/null || exit ./mvnw install -DskipTests -am -pl :spring-cloud-dataflow-classic-docs,:spring-cloud-dataflow-docs,:spring-cloud-skipper-server-core,:spring-cloud-skipper-docs -Pfull,docs popd > /dev/null || exit