From 071409eb1b28e1088fc7456dca43a26049a6efef Mon Sep 17 00:00:00 2001 From: richardwang98 Date: Mon, 19 Jun 2023 12:27:23 -0400 Subject: [PATCH] set additional info for report urls --- .../workflow/context/WorkContextDelegate.java | 4 +- .../workflow/task/BaseWorkFlowTask.java | 4 + .../workflow/utils/WorkContextUtils.java | 26 ++ .../CreateApplicationTask.java | 1 + .../migrationtoolkit/GetAnalysisTask.java | 1 + .../simple/task/DoNothingWorkFlowTask.java | 1 + .../PendingWithAlertMessageWorkFlowTask.java | 1 + workflow-service-sdk/README.md | 1 + workflow-service-sdk/api/openapi.yaml | 20 ++ workflow-service-sdk/docs/AdditionalInfo.md | 14 ++ .../docs/WorkFlowResponseDTO.md | 1 + workflow-service-sdk/docs/WorkflowApi.md | 2 +- .../com/redhat/parodos/sdk/invoker/JSON.java | 2 + .../parodos/sdk/model/AdditionalInfo.java | 231 ++++++++++++++++++ .../sdk/model/WorkFlowResponseDTO.java | 61 ++++- .../generated/openapi/openapi.json | 19 +- .../execution/dto/WorkFlowResponseDTO.java | 6 + .../service/WorkFlowServiceImpl.java | 13 +- .../service/WorkFlowServiceImplTest.java | 19 +- 19 files changed, 418 insertions(+), 9 deletions(-) create mode 100644 workflow-service-sdk/docs/AdditionalInfo.md create mode 100644 workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/AdditionalInfo.java diff --git a/parodos-model-api/src/main/java/com/redhat/parodos/workflow/context/WorkContextDelegate.java b/parodos-model-api/src/main/java/com/redhat/parodos/workflow/context/WorkContextDelegate.java index 5b17a6b0f..6d37791c7 100644 --- a/parodos-model-api/src/main/java/com/redhat/parodos/workflow/context/WorkContextDelegate.java +++ b/parodos-model-api/src/main/java/com/redhat/parodos/workflow/context/WorkContextDelegate.java @@ -56,7 +56,9 @@ public enum Resource { WORKFLOW_OPTIONS(Visibility.PUBLIC), - PARENT_WORKFLOW; + PARENT_WORKFLOW, + + ADDITIONAL_INFO; // @formatter:on private final Visibility visibility; diff --git a/parodos-model-api/src/main/java/com/redhat/parodos/workflow/task/BaseWorkFlowTask.java b/parodos-model-api/src/main/java/com/redhat/parodos/workflow/task/BaseWorkFlowTask.java index a10055052..b9c82a346 100644 --- a/parodos-model-api/src/main/java/com/redhat/parodos/workflow/task/BaseWorkFlowTask.java +++ b/parodos-model-api/src/main/java/com/redhat/parodos/workflow/task/BaseWorkFlowTask.java @@ -97,6 +97,10 @@ public Map getAllParameters(WorkContext workContext) { return WorkContextUtils.getAllParameters(workContext, name); } + public void addAdditionInfo(String key, String value) { + WorkContextUtils.addAdditionalInfo(workContext, key, value); + } + /** * Get Parameters specific to this WorkFlowTask, this is a required parameter * @param parameterName diff --git a/parodos-model-api/src/main/java/com/redhat/parodos/workflow/utils/WorkContextUtils.java b/parodos-model-api/src/main/java/com/redhat/parodos/workflow/utils/WorkContextUtils.java index c24dca633..b49154d6c 100644 --- a/parodos-model-api/src/main/java/com/redhat/parodos/workflow/utils/WorkContextUtils.java +++ b/parodos-model-api/src/main/java/com/redhat/parodos/workflow/utils/WorkContextUtils.java @@ -120,6 +120,32 @@ public static void addParameter(WorkContext workContext, String key, String valu WorkContextDelegate.Resource.ARGUMENTS, parameterMap); } + /** + * add additional info for the workflow, e.g. result links + * @param workContext + * @param key + * @param value + */ + public static void addAdditionalInfo(WorkContext workContext, String key, String value) { + Map additionalInfoMap = Optional + .ofNullable(new ObjectMapper().convertValue( + WorkContextDelegate.read(workContext, WorkContextDelegate.ProcessType.WORKFLOW_EXECUTION, + WorkContextDelegate.Resource.ADDITIONAL_INFO), + new TypeReference>() { + })) + .orElse(new HashMap<>()); + additionalInfoMap.put(key, value); + WorkContextDelegate.write(workContext, WorkContextDelegate.ProcessType.WORKFLOW_EXECUTION, + WorkContextDelegate.Resource.ADDITIONAL_INFO, additionalInfoMap); + } + + public static Map getAdditionalInfo(WorkContext workContext) { + return new ObjectMapper().convertValue(WorkContextDelegate.read(workContext, + WorkContextDelegate.ProcessType.WORKFLOW_EXECUTION, WorkContextDelegate.Resource.ADDITIONAL_INFO), + new TypeReference<>() { + }); + } + /** * get all available parameters for a task * @param workContext work context diff --git a/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/migrationtoolkit/CreateApplicationTask.java b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/migrationtoolkit/CreateApplicationTask.java index 4d94f3cdc..6b3b206f7 100644 --- a/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/migrationtoolkit/CreateApplicationTask.java +++ b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/migrationtoolkit/CreateApplicationTask.java @@ -71,6 +71,7 @@ else if (result instanceof Result.Success success) { workContext.put("application", success.value()); taskLogger.logInfoWithSlf4j("MTA client returned success result for application creation: {}", success.value().name()); + addAdditionInfo("VCS branch", repo); return new DefaultWorkReport(WorkStatus.COMPLETED, workContext); } throw new IllegalArgumentException(); diff --git a/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/migrationtoolkit/GetAnalysisTask.java b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/migrationtoolkit/GetAnalysisTask.java index 91dead950..b738c09b1 100644 --- a/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/migrationtoolkit/GetAnalysisTask.java +++ b/prebuilt-tasks/src/main/java/com/redhat/parodos/tasks/migrationtoolkit/GetAnalysisTask.java @@ -101,6 +101,7 @@ else if (result instanceof Result.Success success) { success.value().tasks()[0].application().id(), success.value().data().output()); taskLogger.logInfoWithSlf4j("MTA client returned success result with report url: {}", reportURL); addParameter("reportURL", reportURL); + addAdditionInfo("MTA assessment report", reportURL); notificationSender.send("Migration Analysis Report Completed", "[Migration analysis report](%s) completed.".formatted(reportURL)); return new DefaultWorkReport(WorkStatus.COMPLETED, workContext); diff --git a/workflow-examples/src/main/java/com/redhat/parodos/examples/negative/simple/task/DoNothingWorkFlowTask.java b/workflow-examples/src/main/java/com/redhat/parodos/examples/negative/simple/task/DoNothingWorkFlowTask.java index 6b6e425cb..62af3f16e 100644 --- a/workflow-examples/src/main/java/com/redhat/parodos/examples/negative/simple/task/DoNothingWorkFlowTask.java +++ b/workflow-examples/src/main/java/com/redhat/parodos/examples/negative/simple/task/DoNothingWorkFlowTask.java @@ -16,6 +16,7 @@ public class DoNothingWorkFlowTask extends BaseInfrastructureWorkFlowTask { @Override public WorkReport execute(WorkContext workContext) { log.info("DoNothingWorkFlowTask execution should return COMPLETE"); + addAdditionInfo("DoNothing", null); return new DefaultWorkReport(WorkStatus.COMPLETED, workContext); } diff --git a/workflow-examples/src/main/java/com/redhat/parodos/examples/negative/simple/task/PendingWithAlertMessageWorkFlowTask.java b/workflow-examples/src/main/java/com/redhat/parodos/examples/negative/simple/task/PendingWithAlertMessageWorkFlowTask.java index 81b863895..8db2f4ab0 100644 --- a/workflow-examples/src/main/java/com/redhat/parodos/examples/negative/simple/task/PendingWithAlertMessageWorkFlowTask.java +++ b/workflow-examples/src/main/java/com/redhat/parodos/examples/negative/simple/task/PendingWithAlertMessageWorkFlowTask.java @@ -16,6 +16,7 @@ public class PendingWithAlertMessageWorkFlowTask extends BaseInfrastructureWorkF @Override public WorkReport execute(WorkContext workContext) { log.info("FailedWithAlertMessageWorkFlowTask execution should return PENDING"); + addAdditionInfo("Alert message", "http://localhost:8080"); return new DefaultWorkReport(WorkStatus.PENDING, workContext, "[link](http://localhost:8080)"); } diff --git a/workflow-service-sdk/README.md b/workflow-service-sdk/README.md index 6c9515855..4fc485727 100644 --- a/workflow-service-sdk/README.md +++ b/workflow-service-sdk/README.md @@ -137,6 +137,7 @@ Class | Method | HTTP request | Description - [AccessResponseDTO](docs/AccessResponseDTO.md) - [AccessStatusRequestDTO](docs/AccessStatusRequestDTO.md) - [AccessStatusResponseDTO](docs/AccessStatusResponseDTO.md) + - [AdditionalInfo](docs/AdditionalInfo.md) - [ArgumentRequestDTO](docs/ArgumentRequestDTO.md) - [ErrorMessageDTO](docs/ErrorMessageDTO.md) - [ProjectDTO](docs/ProjectDTO.md) diff --git a/workflow-service-sdk/api/openapi.yaml b/workflow-service-sdk/api/openapi.yaml index 51445e704..80001f5f7 100644 --- a/workflow-service-sdk/api/openapi.yaml +++ b/workflow-service-sdk/api/openapi.yaml @@ -723,6 +723,7 @@ paths: - STATUS - WORKFLOW_OPTIONS - PARENT_WORKFLOW + - ADDITIONAL_INFO type: string type: array style: form @@ -930,6 +931,16 @@ components: - REJECTED type: string type: object + AdditionalInfo: + example: + value: value + key: key + properties: + key: + type: string + value: + type: string + type: object ArgumentRequestDTO: example: value: value @@ -1523,6 +1534,11 @@ components: WorkFlowResponseDTO: example: workStatus: FAILED + additionalInfos: + - value: value + key: key + - value: value + key: key workFlowName: workFlowName executeBy: executeBy endDate: endDate @@ -1530,6 +1546,10 @@ components: projectId: 046b6c7f-0b8a-43b9-b35d-6489e6daee91 startDate: startDate properties: + additionalInfos: + items: + $ref: '#/components/schemas/AdditionalInfo' + type: array endDate: type: string executeBy: diff --git a/workflow-service-sdk/docs/AdditionalInfo.md b/workflow-service-sdk/docs/AdditionalInfo.md new file mode 100644 index 000000000..5df96e441 --- /dev/null +++ b/workflow-service-sdk/docs/AdditionalInfo.md @@ -0,0 +1,14 @@ + + +# AdditionalInfo + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**key** | **String** | | [optional] | +|**value** | **String** | | [optional] | + + + diff --git a/workflow-service-sdk/docs/WorkFlowResponseDTO.md b/workflow-service-sdk/docs/WorkFlowResponseDTO.md index aba112c7a..dc58a9a57 100644 --- a/workflow-service-sdk/docs/WorkFlowResponseDTO.md +++ b/workflow-service-sdk/docs/WorkFlowResponseDTO.md @@ -7,6 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| +|**additionalInfos** | [**List<AdditionalInfo>**](AdditionalInfo.md) | | [optional] | |**endDate** | **String** | | [optional] | |**executeBy** | **String** | | [optional] | |**projectId** | **UUID** | | [optional] | diff --git a/workflow-service-sdk/docs/WorkflowApi.md b/workflow-service-sdk/docs/WorkflowApi.md index 11413d1e0..a6b3a69bd 100644 --- a/workflow-service-sdk/docs/WorkflowApi.md +++ b/workflow-service-sdk/docs/WorkflowApi.md @@ -318,7 +318,7 @@ public class Example { | Name | Type | Description | Notes | |------------- | ------------- | ------------- | -------------| | **workFlowExecutionId** | **UUID**| | | -| **param** | [**List<String>**](String.md)| | [enum: ID, NAME, PARAMETERS, ARGUMENTS, STATUS, WORKFLOW_OPTIONS, PARENT_WORKFLOW] | +| **param** | [**List<String>**](String.md)| | [enum: ID, NAME, PARAMETERS, ARGUMENTS, STATUS, WORKFLOW_OPTIONS, PARENT_WORKFLOW, ADDITIONAL_INFO] | ### Return type diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/invoker/JSON.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/invoker/JSON.java index 5f045d2b2..015d4a915 100644 --- a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/invoker/JSON.java +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/invoker/JSON.java @@ -93,6 +93,8 @@ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, Stri new com.redhat.parodos.sdk.model.AccessStatusRequestDTO.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory( new com.redhat.parodos.sdk.model.AccessStatusResponseDTO.CustomTypeAdapterFactory()); + gsonBuilder + .registerTypeAdapterFactory(new com.redhat.parodos.sdk.model.AdditionalInfo.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory( new com.redhat.parodos.sdk.model.ArgumentRequestDTO.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory( diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/AdditionalInfo.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/AdditionalInfo.java new file mode 100644 index 000000000..b494dc84b --- /dev/null +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/AdditionalInfo.java @@ -0,0 +1,231 @@ +/* + * Parodos Workflow Service API + * This is the API documentation for the Parodos Workflow Service. It provides operations to execute assessments to determine infrastructure options (tooling + environments). Also executes infrastructure task workflows to call downstream systems to stand-up an infrastructure option. + * + * The version of the OpenAPI document: v1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package com.redhat.parodos.sdk.model; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.redhat.parodos.sdk.invoker.JSON; + +/** + * AdditionalInfo + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class AdditionalInfo { + + public static final String SERIALIZED_NAME_KEY = "key"; + + @SerializedName(SERIALIZED_NAME_KEY) + private String key; + + public static final String SERIALIZED_NAME_VALUE = "value"; + + @SerializedName(SERIALIZED_NAME_VALUE) + private String value; + + public AdditionalInfo() { + } + + public AdditionalInfo key(String key) { + + this.key = key; + return this; + } + + /** + * Get key + * @return key + **/ + @javax.annotation.Nullable + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public AdditionalInfo value(String value) { + + this.value = value; + return this; + } + + /** + * Get value + * @return value + **/ + @javax.annotation.Nullable + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdditionalInfo additionalInfo = (AdditionalInfo) o; + return Objects.equals(this.key, additionalInfo.key) && Objects.equals(this.value, additionalInfo.value); + } + + @Override + public int hashCode() { + return Objects.hash(key, value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class AdditionalInfo {\n"); + sb.append(" key: ").append(toIndentedString(key)).append("\n"); + sb.append(" value: ").append(toIndentedString(value)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the + * first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public static HashSet openapiFields; + + public static HashSet openapiRequiredFields; + + static { + // a set of all properties/fields (JSON key names) + openapiFields = new HashSet(); + openapiFields.add("key"); + openapiFields.add("value"); + + // a set of required properties/fields (JSON key names) + openapiRequiredFields = new HashSet(); + } + + /** + * Validates the JSON Object and throws an exception if issues found + * @param jsonObj JSON Object + * @throws IOException if the JSON Object is invalid with respect to AdditionalInfo + */ + public static void validateJsonObject(JsonObject jsonObj) throws IOException { + if (jsonObj == null) { + if (!AdditionalInfo.openapiRequiredFields.isEmpty()) { // has required fields + // but JSON object is + // null + throw new IllegalArgumentException(String.format( + "The required field(s) %s in AdditionalInfo is not found in the empty JSON string", + AdditionalInfo.openapiRequiredFields.toString())); + } + } + + Set> entries = jsonObj.entrySet(); + // check to see if the JSON string contains additional fields + for (Entry entry : entries) { + if (!AdditionalInfo.openapiFields.contains(entry.getKey())) { + throw new IllegalArgumentException(String.format( + "The field `%s` in the JSON string is not defined in the `AdditionalInfo` properties. JSON: %s", + entry.getKey(), jsonObj.toString())); + } + } + if ((jsonObj.get("key") != null && !jsonObj.get("key").isJsonNull()) && !jsonObj.get("key").isJsonPrimitive()) { + throw new IllegalArgumentException( + String.format("Expected the field `key` to be a primitive type in the JSON string but got `%s`", + jsonObj.get("key").toString())); + } + if ((jsonObj.get("value") != null && !jsonObj.get("value").isJsonNull()) + && !jsonObj.get("value").isJsonPrimitive()) { + throw new IllegalArgumentException( + String.format("Expected the field `value` to be a primitive type in the JSON string but got `%s`", + jsonObj.get("value").toString())); + } + } + + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!AdditionalInfo.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes 'AdditionalInfo' and its + // subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + final TypeAdapter thisAdapter = gson.getDelegateAdapter(this, + TypeToken.get(AdditionalInfo.class)); + + return (TypeAdapter) new TypeAdapter() { + @Override + public void write(JsonWriter out, AdditionalInfo value) throws IOException { + JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject(); + elementAdapter.write(out, obj); + } + + @Override + public AdditionalInfo read(JsonReader in) throws IOException { + JsonObject jsonObj = elementAdapter.read(in).getAsJsonObject(); + validateJsonObject(jsonObj); + return thisAdapter.fromJsonTree(jsonObj); + } + + }.nullSafe(); + } + + } + + /** + * Create an instance of AdditionalInfo given an JSON string + * @param jsonString JSON string + * @return An instance of AdditionalInfo + * @throws IOException if the JSON string is invalid with respect to AdditionalInfo + */ + public static AdditionalInfo fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, AdditionalInfo.class); + } + + /** + * Convert an instance of AdditionalInfo to an JSON string + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } + +} diff --git a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowResponseDTO.java b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowResponseDTO.java index a831ce6bc..7cd390881 100644 --- a/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowResponseDTO.java +++ b/workflow-service-sdk/src/main/java/com/redhat/parodos/sdk/model/WorkFlowResponseDTO.java @@ -13,13 +13,16 @@ package com.redhat.parodos.sdk.model; import java.io.IOException; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.UUID; import com.google.gson.Gson; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.TypeAdapter; @@ -37,6 +40,11 @@ @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public class WorkFlowResponseDTO { + public static final String SERIALIZED_NAME_ADDITIONAL_INFOS = "additionalInfos"; + + @SerializedName(SERIALIZED_NAME_ADDITIONAL_INFOS) + private List additionalInfos = new ArrayList<>(); + public static final String SERIALIZED_NAME_END_DATE = "endDate"; @SerializedName(SERIALIZED_NAME_END_DATE) @@ -132,6 +140,34 @@ public WorkStatusEnum read(final JsonReader jsonReader) throws IOException { public WorkFlowResponseDTO() { } + public WorkFlowResponseDTO additionalInfos(List additionalInfos) { + + this.additionalInfos = additionalInfos; + return this; + } + + public WorkFlowResponseDTO addAdditionalInfosItem(AdditionalInfo additionalInfosItem) { + if (this.additionalInfos == null) { + this.additionalInfos = new ArrayList<>(); + } + this.additionalInfos.add(additionalInfosItem); + return this; + } + + /** + * Get additionalInfos + * @return additionalInfos + **/ + @javax.annotation.Nullable + + public List getAdditionalInfos() { + return additionalInfos; + } + + public void setAdditionalInfos(List additionalInfos) { + this.additionalInfos = additionalInfos; + } + public WorkFlowResponseDTO endDate(String endDate) { this.endDate = endDate; @@ -281,7 +317,8 @@ public boolean equals(Object o) { return false; } WorkFlowResponseDTO workFlowResponseDTO = (WorkFlowResponseDTO) o; - return Objects.equals(this.endDate, workFlowResponseDTO.endDate) + return Objects.equals(this.additionalInfos, workFlowResponseDTO.additionalInfos) + && Objects.equals(this.endDate, workFlowResponseDTO.endDate) && Objects.equals(this.executeBy, workFlowResponseDTO.executeBy) && Objects.equals(this.projectId, workFlowResponseDTO.projectId) && Objects.equals(this.startDate, workFlowResponseDTO.startDate) @@ -292,13 +329,15 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(endDate, executeBy, projectId, startDate, workFlowExecutionId, workFlowName, workStatus); + return Objects.hash(additionalInfos, endDate, executeBy, projectId, startDate, workFlowExecutionId, + workFlowName, workStatus); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class WorkFlowResponseDTO {\n"); + sb.append(" additionalInfos: ").append(toIndentedString(additionalInfos)).append("\n"); sb.append(" endDate: ").append(toIndentedString(endDate)).append("\n"); sb.append(" executeBy: ").append(toIndentedString(executeBy)).append("\n"); sb.append(" projectId: ").append(toIndentedString(projectId)).append("\n"); @@ -328,6 +367,7 @@ private String toIndentedString(Object o) { static { // a set of all properties/fields (JSON key names) openapiFields = new HashSet(); + openapiFields.add("additionalInfos"); openapiFields.add("endDate"); openapiFields.add("executeBy"); openapiFields.add("projectId"); @@ -366,6 +406,23 @@ public static void validateJsonObject(JsonObject jsonObj) throws IOException { entry.getKey(), jsonObj.toString())); } } + if (jsonObj.get("additionalInfos") != null && !jsonObj.get("additionalInfos").isJsonNull()) { + JsonArray jsonArrayadditionalInfos = jsonObj.getAsJsonArray("additionalInfos"); + if (jsonArrayadditionalInfos != null) { + // ensure the json data is an array + if (!jsonObj.get("additionalInfos").isJsonArray()) { + throw new IllegalArgumentException(String.format( + "Expected the field `additionalInfos` to be an array in the JSON string but got `%s`", + jsonObj.get("additionalInfos").toString())); + } + + // validate the optional field `additionalInfos` (array) + for (int i = 0; i < jsonArrayadditionalInfos.size(); i++) { + AdditionalInfo.validateJsonObject(jsonArrayadditionalInfos.get(i).getAsJsonObject()); + } + ; + } + } if ((jsonObj.get("endDate") != null && !jsonObj.get("endDate").isJsonNull()) && !jsonObj.get("endDate").isJsonPrimitive()) { throw new IllegalArgumentException( diff --git a/workflow-service/generated/openapi/openapi.json b/workflow-service/generated/openapi/openapi.json index f2fea18a1..e8a4129fc 100644 --- a/workflow-service/generated/openapi/openapi.json +++ b/workflow-service/generated/openapi/openapi.json @@ -995,7 +995,7 @@ "type" : "array", "items" : { "type" : "string", - "enum" : [ "ID", "NAME", "PARAMETERS", "ARGUMENTS", "STATUS", "WORKFLOW_OPTIONS", "PARENT_WORKFLOW" ] + "enum" : [ "ID", "NAME", "PARAMETERS", "ARGUMENTS", "STATUS", "WORKFLOW_OPTIONS", "PARENT_WORKFLOW", "ADDITIONAL_INFO" ] } } } ], @@ -1253,6 +1253,17 @@ } } }, + "AdditionalInfo" : { + "type" : "object", + "properties" : { + "key" : { + "type" : "string" + }, + "value" : { + "type" : "string" + } + } + }, "ArgumentRequestDTO" : { "type" : "object", "properties" : { @@ -1625,6 +1636,12 @@ "WorkFlowResponseDTO" : { "type" : "object", "properties" : { + "additionalInfos" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/AdditionalInfo" + } + }, "endDate" : { "type" : "string" }, diff --git a/workflow-service/src/main/java/com/redhat/parodos/workflow/execution/dto/WorkFlowResponseDTO.java b/workflow-service/src/main/java/com/redhat/parodos/workflow/execution/dto/WorkFlowResponseDTO.java index da833054f..195f36963 100644 --- a/workflow-service/src/main/java/com/redhat/parodos/workflow/execution/dto/WorkFlowResponseDTO.java +++ b/workflow-service/src/main/java/com/redhat/parodos/workflow/execution/dto/WorkFlowResponseDTO.java @@ -15,6 +15,7 @@ */ package com.redhat.parodos.workflow.execution.dto; +import java.util.List; import java.util.UUID; import com.fasterxml.jackson.annotation.JsonInclude; @@ -52,4 +53,9 @@ public class WorkFlowResponseDTO { private String executeBy; + private List additionalInfos; + + public record AdditionalInfo(String key, String value) { + } + } diff --git a/workflow-service/src/main/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImpl.java b/workflow-service/src/main/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImpl.java index 4b53c623f..8fffbcce6 100644 --- a/workflow-service/src/main/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImpl.java +++ b/workflow-service/src/main/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImpl.java @@ -398,7 +398,18 @@ private WorkFlowResponseDTO buildWorkflowResponseDTO(WorkFlowExecution workflowE .workStatus(WorkStatus.valueOf(workflowExecution.getStatus().name())) .startDate(Optional.ofNullable(workflowExecution.getStartDate()).map(Date::toString).orElse(null)) .endDate(Optional.ofNullable(workflowExecution.getEndDate()).map(Date::toString).orElse(null)) - .executeBy(workflowExecution.getUser().getUsername()).build(); + .executeBy(workflowExecution.getUser().getUsername()) + .additionalInfos(Optional.ofNullable(workflowExecution.getWorkFlowExecutionContext()) + .flatMap(workFlowExecutionContext -> Optional + .ofNullable( + WorkContextUtils.getAdditionalInfo(workFlowExecutionContext.getWorkContext())) + .map(additionalInfoMap -> additionalInfoMap.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .map(additionalInfo -> new WorkFlowResponseDTO.AdditionalInfo( + additionalInfo.getKey(), additionalInfo.getValue())) + .toList())) + .orElse(null)) + .build(); } } diff --git a/workflow-service/src/test/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImplTest.java b/workflow-service/src/test/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImplTest.java index 89e35eac6..ed286c8bb 100644 --- a/workflow-service/src/test/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImplTest.java +++ b/workflow-service/src/test/java/com/redhat/parodos/workflow/execution/service/WorkFlowServiceImplTest.java @@ -25,6 +25,7 @@ import com.redhat.parodos.workflow.enums.WorkType; import com.redhat.parodos.workflow.execution.dto.WorkFlowContextResponseDTO; import com.redhat.parodos.workflow.execution.dto.WorkFlowRequestDTO; +import com.redhat.parodos.workflow.execution.dto.WorkFlowResponseDTO; import com.redhat.parodos.workflow.execution.dto.WorkFlowStatusResponseDTO; import com.redhat.parodos.workflow.execution.dto.WorkStatusResponseDTO; import com.redhat.parodos.workflow.execution.entity.WorkFlowExecution; @@ -70,6 +71,10 @@ class WorkFlowServiceImplTest { private static final String TEST_WORKFLOW_NAME = "test-workflow"; + public static final String TEST_ADDITIONAL_INFO_KEY = "test-additional-info-key"; + + public static final String TEST_ADDITIONAL_INFO_VALUE = "test-additional-info-value"; + @Mock private ProjectService projectService; @@ -1078,8 +1083,13 @@ void getWorkFlowsByProjectId_when_projectIsFound_then_returnWorkFlowStatus() { user.setId(userId); UUID workflowExecutionId = UUID.randomUUID(); WorkFlowDefinition workFlowDefinition = sampleWorkflowDefinition(workName); + WorkContext workContext = new WorkContext(); + WorkContextDelegate.write(workContext, WorkContextDelegate.ProcessType.WORKFLOW_EXECUTION, + WorkContextDelegate.Resource.ADDITIONAL_INFO, + Map.of(TEST_ADDITIONAL_INFO_KEY, TEST_ADDITIONAL_INFO_VALUE)); WorkFlowExecution workFlowExecution = WorkFlowExecution.builder().projectId(projectId).user(user) - .status(WorkStatus.COMPLETED).workFlowDefinition(workFlowDefinition).build(); + .status(WorkStatus.COMPLETED).workFlowDefinition(workFlowDefinition) + .workFlowExecutionContext(WorkFlowExecutionContext.builder().workContext(workContext).build()).build(); workFlowExecution.setId(workflowExecutionId); when(workFlowRepository.findAllByProjectId(projectId)).thenReturn(List.of(workFlowExecution)); @@ -1089,8 +1099,11 @@ void getWorkFlowsByProjectId_when_projectIsFound_then_returnWorkFlowStatus() { when(workFlowDefinitionService.getWorkFlowDefinitionById(any())) .thenReturn(WorkFlowDefinitionResponseDTO.builder().name("test").build()); - assertThat(workFlowService.getWorkFlowsByProjectId(projectId)).hasSize(1).extracting("workStatus") - .contains(WorkStatus.COMPLETED); + assertThat(workFlowService.getWorkFlowsByProjectId(projectId)).hasSize(1).satisfies(workflowStatus -> { + assertEquals(workflowStatus.get(0).getAdditionalInfos().get(0), + new WorkFlowResponseDTO.AdditionalInfo(TEST_ADDITIONAL_INFO_KEY, TEST_ADDITIONAL_INFO_VALUE)); + assertEquals(WorkStatus.COMPLETED, workflowStatus.get(0).getWorkStatus()); + }); } @Test