From 266eadfd2bba89f8b66bda089737fc5707725b7b Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Wed, 3 May 2023 15:00:53 +0200 Subject: [PATCH 01/43] feat(impl):[TRI-1191] cancel batch order impl --- docs/src/api/irs-v1.0.yaml | 66 +++++++++++++++++++ .../irs/connector/batch/BatchOrderStore.java | 4 +- .../irs/controllers/BatchController.java | 50 ++++++++++++++ .../CancelBatchProcessingService.java | 14 ++++ 4 files changed, 132 insertions(+), 2 deletions(-) diff --git a/docs/src/api/irs-v1.0.yaml b/docs/src/api/irs-v1.0.yaml index 131267d953..14a77cbd0a 100644 --- a/docs/src/api/irs-v1.0.yaml +++ b/docs/src/api/irs-v1.0.yaml @@ -603,6 +603,72 @@ paths: summary: Get a batch order for a given orderId. tags: - Item Relationship Service + put: + description: Cancel a batch order for a given orderId. + operationId: cancelBatchOrder + parameters: + - description: Id of the order. + example: 6c311d29-5753-46d4-b32c-19b918ea93b0 + in: path + name: orderId + required: true + schema: + type: string + format: uuid + maxLength: 36 + minLength: 36 + responses: + "200": + content: + application/json: + examples: + complete: + $ref: '#/components/examples/complete-order-result' + schema: + $ref: '#/components/schemas/BatchOrderResponse' + description: Cancel a batch order for a given orderId. + "400": + content: + application/json: + examples: + error: + $ref: '#/components/examples/error-response-400' + schema: + $ref: '#/components/schemas/ErrorResponse' + description: Return Batch Order failed. + "401": + content: + application/json: + examples: + error: + $ref: '#/components/examples/error-response-401' + schema: + $ref: '#/components/schemas/ErrorResponse' + description: Authorized failed. + "403": + content: + application/json: + examples: + error: + $ref: '#/components/examples/error-response-403' + schema: + $ref: '#/components/schemas/ErrorResponse' + description: Authorized failed. + "404": + content: + application/json: + examples: + error: + $ref: '#/components/examples/error-response-404' + schema: + $ref: '#/components/schemas/ErrorResponse' + description: Batch Order with the requested orderId not found. + security: + - oAuth2: + - profile email + summary: Cancel a batch order for a given orderId. + tags: + - Item Relationship Service /irs/orders/{orderId}/batches/{batchId}: get: description: Get a batch with a given batchId for a given orderId. diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/BatchOrderStore.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/BatchOrderStore.java index 371c184b69..997c2280df 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/BatchOrderStore.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/batch/BatchOrderStore.java @@ -31,9 +31,9 @@ */ public interface BatchOrderStore { - void save(UUID batchId, BatchOrder batch); + void save(UUID batchOrderId, BatchOrder batch); - Optional find(UUID batchId); + Optional find(UUID batchOrderId); List findAll(); diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java index f41a65493f..96f273c139 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java @@ -47,11 +47,13 @@ import org.eclipse.tractusx.irs.services.AuthorizationService; import org.eclipse.tractusx.irs.services.CreationBatchService; import org.eclipse.tractusx.irs.services.QueryBatchService; +import org.eclipse.tractusx.irs.services.timeouts.CancelBatchProcessingService; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; @@ -71,6 +73,7 @@ public class BatchController { private final CreationBatchService creationBatchService; private final QueryBatchService queryBatchService; + private final CancelBatchProcessingService cancelBatchProcessingService; private final AuthorizationService authorizationService; @Operation(operationId = "registerOrder", @@ -209,4 +212,51 @@ public BatchResponse getBatch( return queryBatchService.findBatchById(orderId, batchId); } + @Operation(description = "Cancel a batch order for a given orderId.", + operationId = "cancelBatchOrder", + summary = "Cancel a batch order for a given orderId.", + security = @SecurityRequirement(name = "oAuth2", scopes = "profile email"), + tags = { "Item Relationship Service" }) + @ApiResponses(value = { @ApiResponse(responseCode = "200", + description = "Cancel a batch order for a given orderId.", + content = { @Content(mediaType = APPLICATION_JSON_VALUE, + schema = @Schema(implementation = BatchOrderResponse.class), + examples = @ExampleObject(name = "complete", + ref = "#/components/examples/complete-order-result")) + }), + @ApiResponse(responseCode = "400", description = "Return Batch Order failed.", + content = { @Content(mediaType = APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ErrorResponse.class), + examples = @ExampleObject(name = "error", + ref = "#/components/examples/error-response-400")) + }), + @ApiResponse(responseCode = "401", description = "Authorized failed.", + content = { @Content(mediaType = APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ErrorResponse.class), + examples = @ExampleObject(name = "error", + ref = "#/components/examples/error-response-401")) + }), + @ApiResponse(responseCode = "403", description = "Authorized failed.", + content = { @Content(mediaType = APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ErrorResponse.class), + examples = @ExampleObject(name = "error", + ref = "#/components/examples/error-response-403")) + }), + @ApiResponse(responseCode = "404", description = "Batch Order with the requested orderId not found.", + content = { @Content(mediaType = APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ErrorResponse.class), + examples = @ExampleObject(name = "error", + ref = "#/components/examples/error-response-404")) + }), + }) + @PutMapping("/orders/{orderId}") + @PreAuthorize("@authorizationService.verifyBpn() && hasAuthority('view_irs')") + public BatchOrderResponse cancelBatchOrder( + @Parameter(description = "Id of the order.", schema = @Schema(implementation = UUID.class), name = "orderId", + example = "6c311d29-5753-46d4-b32c-19b918ea93b0") @Size(min = IrsAppConstants.JOB_ID_SIZE, + max = IrsAppConstants.JOB_ID_SIZE) @Valid @PathVariable final UUID orderId) { + cancelBatchProcessingService.cancelNotFinishedJobsInBatchOrder(orderId); + return queryBatchService.findOrderById(orderId); + } + } diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/services/timeouts/CancelBatchProcessingService.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/services/timeouts/CancelBatchProcessingService.java index 77a0e00412..2177a3be64 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/services/timeouts/CancelBatchProcessingService.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/services/timeouts/CancelBatchProcessingService.java @@ -29,6 +29,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.irs.component.enums.JobState; import org.eclipse.tractusx.irs.component.enums.ProcessingState; +import org.eclipse.tractusx.irs.connector.batch.Batch; import org.eclipse.tractusx.irs.connector.batch.BatchStore; import org.eclipse.tractusx.irs.connector.batch.JobProgress; import org.eclipse.tractusx.irs.services.IrsItemGraphQueryService; @@ -65,6 +66,19 @@ public void cancelNotFinishedJobsInBatch(final UUID batchId) { }); } + public void cancelNotFinishedJobsInBatchOrder(final UUID batchOrderId) { + log.info("Canceling processing of jobs in order with id: {}", batchOrderId.toString()); + final List batches = batchStore.findAll() + .stream() + .filter(batch -> batch.getBatchOrderId().equals(batchOrderId)) + .toList(); + batches.forEach(batch -> { + if (isBatchNotCompleted(batch.getBatchState())) { + cancelNotFinishedJobs(batch.getJobProgressList().stream().map(JobProgress::getJobId).toList()); + } + }); + } + private boolean isNotCompleted(final JobState jobState) { return JobState.RUNNING.equals(jobState) || JobState.INITIAL.equals(jobState) || JobState.UNSAVED.equals(jobState); } From 31a6158b1b3be24bc897e99c7bc11d8e3349ac3e Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Thu, 4 May 2023 15:37:00 +0200 Subject: [PATCH 02/43] feat(impl):[TRI-1191] cover impl with unit tests --- .../irs/controllers/BatchControllerTest.java | 18 +++++++++ .../CancelBatchProcessingServiceTest.java | 37 ++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/controllers/BatchControllerTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/controllers/BatchControllerTest.java index 6eac8b0353..877e70ef69 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/controllers/BatchControllerTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/controllers/BatchControllerTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -40,6 +41,7 @@ import org.eclipse.tractusx.irs.services.AuthorizationService; import org.eclipse.tractusx.irs.services.CreationBatchService; import org.eclipse.tractusx.irs.services.QueryBatchService; +import org.eclipse.tractusx.irs.services.timeouts.CancelBatchProcessingService; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -63,6 +65,9 @@ class BatchControllerTest { @MockBean private QueryBatchService queryBatchService; + @MockBean + private CancelBatchProcessingService cancelBatchProcessingService; + @MockBean(name = "authorizationService") private AuthorizationService authorizationService; @@ -136,4 +141,17 @@ void shouldReturnBatch() throws Exception { .andExpect(content().string(containsString(orderId.toString()))) .andExpect(content().string(containsString(batchId.toString()))); } + + @Test + @WithMockUser(authorities = "view_irs") + void shouldCancelBatchOrder() throws Exception { + when(authorizationService.verifyBpn()).thenReturn(Boolean.TRUE); + + final UUID orderId = UUID.randomUUID(); + when(queryBatchService.findOrderById(orderId)).thenReturn(BatchOrderResponse.builder().orderId(orderId).build()); + + this.mockMvc.perform(put("/irs/orders/" + orderId)) + .andExpect(status().isOk()) + .andExpect(content().string(containsString(orderId.toString()))); + } } diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/timeouts/CancelBatchProcessingServiceTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/timeouts/CancelBatchProcessingServiceTest.java index 69e5a8f1b2..d2bb06afbd 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/timeouts/CancelBatchProcessingServiceTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/timeouts/CancelBatchProcessingServiceTest.java @@ -95,7 +95,7 @@ void shouldCancelOnlyNotCompletedJobInBatch() { jobInState(JobState.RUNNING) ); - batchStore.save(batchId, createBatch(batchId, ProcessingState.PROCESSING, + batchStore.save(batchId, createBatch(batchId, UUID.randomUUID(), ProcessingState.PROCESSING, List.of(firstJobId, secondJobId, runningJobId))); // when @@ -106,13 +106,46 @@ void shouldCancelOnlyNotCompletedJobInBatch() { assertThat(captor.getValue()).isEqualTo(runningJobId); } + @Test + void shouldCancelOnlyNotCompletedJobInBatchOrder() { + // given + UUID firstJobId = UUID.randomUUID(); + UUID secondJobId = UUID.randomUUID(); + UUID runningJobId = UUID.randomUUID(); + UUID batchId = UUID.randomUUID(); + UUID batchOrderId = UUID.randomUUID(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(UUID.class); + + given(irsItemGraphQueryService.getJobForJobId(firstJobId, false)).willReturn( + jobInState(JobState.COMPLETED) + ); + given(irsItemGraphQueryService.getJobForJobId(secondJobId, false)).willReturn( + jobInState(JobState.ERROR) + ); + given(irsItemGraphQueryService.getJobForJobId(runningJobId, false)).willReturn( + jobInState(JobState.RUNNING) + ); + + batchStore.save(batchId, createBatch(batchId, batchOrderId, ProcessingState.PROCESSING, + List.of(firstJobId, secondJobId, runningJobId))); + + // when + cancelBatchProcessingService.cancelNotFinishedJobsInBatchOrder(batchOrderId); + + // then + verify(irsItemGraphQueryService).cancelJobById(captor.capture()); + assertThat(captor.getValue()).isEqualTo(runningJobId); + } + private static Jobs jobInState(final JobState completed) { return Jobs.builder().job(Job.builder().state(completed).build()).build(); } - private Batch createBatch(final UUID batchId, final ProcessingState state, final List jobIds) { + private Batch createBatch(final UUID batchId, final UUID batchOrderId, final ProcessingState state, final List jobIds) { return Batch.builder() .batchId(batchId) + .batchOrderId(batchOrderId) .batchState(state) .jobProgressList( jobIds.stream().map(uuid -> JobProgress.builder().jobId(uuid).build()).toList() From cd1bf8e821c5d27b66d21c09e84b6b2514f46991 Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Thu, 4 May 2023 15:39:10 +0200 Subject: [PATCH 03/43] feat(impl):[TRI-1191] update api desc --- .../org/eclipse/tractusx/irs/controllers/BatchController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java index 0fa0359c9f..8c95994cfc 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java @@ -230,13 +230,13 @@ public BatchResponse getBatch( examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "Authorized failed.", + @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorized failed.", + @ApiResponse(responseCode = "403", description = "Authorization refused by server.", content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", From 8f3fcc898d80896116fcf4e8f03e8577c96f8435 Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Thu, 4 May 2023 15:50:10 +0200 Subject: [PATCH 04/43] feat(impl):[TRI-1191] fix test --- docs/src/api/irs-v1.0.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/api/irs-v1.0.yaml b/docs/src/api/irs-v1.0.yaml index 3b272b24eb..1dc3dfcb1e 100644 --- a/docs/src/api/irs-v1.0.yaml +++ b/docs/src/api/irs-v1.0.yaml @@ -644,7 +644,7 @@ paths: $ref: '#/components/examples/error-response-401' schema: $ref: '#/components/schemas/ErrorResponse' - description: Authorized failed. + description: No valid authentication credentials. "403": content: application/json: @@ -653,7 +653,7 @@ paths: $ref: '#/components/examples/error-response-403' schema: $ref: '#/components/schemas/ErrorResponse' - description: Authorized failed. + description: Authorization refused by server. "404": content: application/json: From 940600f294d773bf98ed1677297453c83edad69c Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Mon, 8 May 2023 15:56:32 +0200 Subject: [PATCH 05/43] feat(impl):[TRI-1192] additional unit test, exteneded assertions --- .../irs/services/BatchOrderEventListener.java | 6 +-- .../services/BatchOrderEventListenerTest.java | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/services/BatchOrderEventListener.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/services/BatchOrderEventListener.java index 63ad5107cd..d530fce131 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/services/BatchOrderEventListener.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/services/BatchOrderEventListener.java @@ -88,10 +88,10 @@ public void handleBatchProcessingFinishedEvent(final BatchProcessingFinishedEven .equals(batchOrder.getBatchOrderId())) .map(Batch::getBatchState) .toList(); - final ProcessingState batchState = calculateBatchOrderState(batchStates); - batchOrder.setBatchOrderState(batchState); + final ProcessingState batchOrderState = calculateBatchOrderState(batchStates); + batchOrder.setBatchOrderState(batchOrderState); batchOrderStore.save(batchOrder.getBatchOrderId(), batchOrder); - if (ProcessingState.COMPLETED.equals(batchState) || ProcessingState.ERROR.equals(batchState)) { + if (ProcessingState.COMPLETED.equals(batchOrderState) || ProcessingState.ERROR.equals(batchOrderState)) { applicationEventPublisher.publishEvent( new BatchOrderProcessingFinishedEvent(batchOrder.getBatchOrderId(), batchOrder.getBatchOrderState(), batchOrder.getCallbackUrl())); diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/BatchOrderEventListenerTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/BatchOrderEventListenerTest.java index 21ec31a87a..871339727c 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/BatchOrderEventListenerTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/BatchOrderEventListenerTest.java @@ -23,6 +23,7 @@ package org.eclipse.tractusx.irs.services; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -44,6 +45,7 @@ import org.eclipse.tractusx.irs.connector.batch.InMemoryBatchStore; import org.eclipse.tractusx.irs.connector.batch.JobProgress; import org.eclipse.tractusx.irs.services.events.BatchOrderRegisteredEvent; +import org.eclipse.tractusx.irs.services.events.BatchProcessingFinishedEvent; import org.eclipse.tractusx.irs.services.timeouts.TimeoutSchedulerBatchProcessingService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -75,10 +77,13 @@ void beforeEach() { void shouldStartFirstBatch() { // given final int numberOfJobs = 10; + final int timeout = 60; final BatchOrder batchOrder = BatchOrder.builder() .batchOrderId(BATCH_ORDER_ID) .batchOrderState(ProcessingState.INITIALIZED) .collectAspects(Boolean.TRUE) + .timeout(timeout) + .jobTimeout(timeout) .lookupBPNs(Boolean.TRUE) .build(); final Batch firstBatch = Batch.builder() @@ -105,6 +110,49 @@ void shouldStartFirstBatch() { eventListener.handleBatchOrderRegisteredEvent(new BatchOrderRegisteredEvent(BATCH_ORDER_ID)); // then verify(irsItemGraphQueryService, times(numberOfJobs)).registerItemJob(any(), eq(FIRST_BATCH_ID)); + verify(timeoutScheduler, times(1)).registerBatchTimeout(eq(FIRST_BATCH_ID), eq(timeout)); + verify(timeoutScheduler, times(1)).registerJobsTimeout(anyList(), eq(timeout)); + } + + @Test + void shouldStartNextBatchWhenPreviousFinished() { + // given + final int numberOfJobs = 10; + final int timeout = 60; + final BatchOrder batchOrder = BatchOrder.builder() + .batchOrderId(BATCH_ORDER_ID) + .batchOrderState(ProcessingState.INITIALIZED) + .collectAspects(Boolean.TRUE) + .timeout(timeout) + .jobTimeout(timeout) + .lookupBPNs(Boolean.TRUE) + .build(); + final Batch firstBatch = Batch.builder() + .batchId(FIRST_BATCH_ID) + .batchState(ProcessingState.PARTIAL) + .batchNumber(1) + .batchOrderId(BATCH_ORDER_ID) + .build(); + final Batch secondBatch = Batch.builder() + .batchId(SECOND_BATCH_ID) + .batchState(ProcessingState.INITIALIZED) + .batchNumber(2) + .batchOrderId(BATCH_ORDER_ID) + .jobProgressList(createJobProgressList(numberOfJobs)) + .build(); + + given(irsItemGraphQueryService.registerItemJob(any(), any())).willReturn( + JobHandle.builder().id(UUID.randomUUID()).build()); + + batchOrderStore.save(BATCH_ORDER_ID, batchOrder); + batchStore.save(FIRST_BATCH_ID, firstBatch); + batchStore.save(SECOND_BATCH_ID, secondBatch); + // when + eventListener.handleBatchProcessingFinishedEvent(new BatchProcessingFinishedEvent(BATCH_ORDER_ID, FIRST_BATCH_ID, ProcessingState.PARTIAL, ProcessingState.COMPLETED, 1, "")); + // then + verify(irsItemGraphQueryService, times(numberOfJobs)).registerItemJob(any(), eq(SECOND_BATCH_ID)); + verify(timeoutScheduler, times(1)).registerBatchTimeout(eq(SECOND_BATCH_ID), eq(timeout)); + verify(timeoutScheduler, times(1)).registerJobsTimeout(anyList(), eq(timeout)); } private List createJobProgressList(Integer size) { From d2d1fc26f80c212c10a5e0eefc4a73036104cd6b Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Mon, 8 May 2023 17:59:11 +0200 Subject: [PATCH 06/43] feat(testdata): Update script to register decentralized registry --- .../testing/testdata/transform-and-upload.py | 82 ++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/local/testing/testdata/transform-and-upload.py b/local/testing/testdata/transform-and-upload.py index bed3004a00..8a8792384f 100644 --- a/local/testing/testdata/transform-and-upload.py +++ b/local/testing/testdata/transform-and-upload.py @@ -47,6 +47,30 @@ def create_edc_asset_payload(submodel_url_, asset_prop_id_, digital_twin_submode }) +def create_edc_registry_asset_payload(registry_url_, asset_prop_id_): + return json.dumps({ + "asset": { + "properties": { + "asset:prop:id": asset_prop_id_, # DTR-EDC-instance-unique-ID + "asset:prop:type": "data.core.digitalTwinRegistry", + "asset:prop:name": "Digital Twin Registry Endpoint of IRS DEV", + "asset:prop:contenttype": "application/json", + "asset:prop:policy-id": "use-eu" + } + }, + "dataAddress": { + "properties": { + "type": "HttpData", + "baseUrl": registry_url_, + "proxyPath": True, + "proxyBody": True, + "proxyMethod": True, + "proxyQueryParams": True + } + } + }) + + def create_esr_edc_asset_payload(esr_url_, asset_prop_id_, digital_twin_id_): return json.dumps({ "asset": { @@ -162,6 +186,48 @@ def create_policy(policy_, edc_upload_url_, edc_policy_path_, headers_, session_ print(f"Successfully created policy {response_.json()['id']}.") +def create_registry_asset(edc_upload_urls_, edc_asset_path_, edc_contract_definition_path_, catalog_path_, header_, + session_, edc_urls_, policy_, registry_asset_id_, aas_upload_url_): + for edc_upload_url_ in edc_upload_urls_: + index = edc_upload_urls_.index(edc_upload_url_) + edc_url_ = edc_urls_[index] + print(index) + print(edc_url_) + print(edc_upload_url_) + + catalog_url_ = edc_upload_url_ + catalog_path_ + payload_ = { + "providerUrl": edc_url_ + "/api/v1/ids/data", + "querySpec": { + "filter": "asset:prop:type=data.core.digitalTwinRegistry" + } + } + response_ = session_.request(method="POST", url=catalog_url_, headers=header_, data=json.dumps(payload_)) + + asset_url_ = edc_upload_url_ + edc_asset_path_ + print(response_.status_code) + print(response_.json()) + if response_.status_code == 200 and len(response_.json()['contractOffers']) >= 1: + print(f"Asset {response_.json()['contractOffers'][0]['asset']['id']} already exists. Skipping creation.") + else: + payload_ = create_edc_registry_asset_payload(aas_upload_url_, registry_asset_id_) + response_ = session_.request(method="POST", url=asset_url_, + headers=header_, + data=payload_) + print(response_) + if response_.status_code > 205: + print(response_.text) + else: + print(f"Successfully created registry asset {response_.json()['id']}.") + + print("Create registry edc contract definition") + payload_ = create_edc_contract_definition_payload(policy_, registry_asset_id_) + response_ = session_.request(method="POST", url=edc_upload_url_ + edc_contract_definition_path_, + headers=header_, + data=payload_) + print_response(response_) + + if __name__ == "__main__": timestamp_start = time.time() parser = argparse.ArgumentParser(description="Script to upload testdata into CX-Network.", @@ -171,6 +237,7 @@ def create_policy(policy_, edc_upload_url_, edc_policy_path_, headers_, session_ parser.add_argument("-su", "--submodelupload", type=str, nargs="*", help="Submodel server upload URLs", required=False) parser.add_argument("-a", "--aas", type=str, help="aas url", required=True) + parser.add_argument("-au", "--aasupload", type=str, help="aas url", required=False) parser.add_argument("-edc", "--edc", type=str, nargs="*", help="EDC provider control plane display URLs", required=True) parser.add_argument("-eu", "--edcupload", type=str, nargs="*", help="EDC provider control plane upload URLs", @@ -190,6 +257,7 @@ def create_policy(policy_, edc_upload_url_, edc_policy_path_, headers_, session_ submodel_server_urls = config.get("submodel") submodel_server_upload_urls = config.get("submodelupload") aas_url = config.get("aas") + aas_upload_url = config.get("aasupload") edc_urls = config.get("edc") edc_upload_urls = config.get("edcupload") edc_api_key = config.get("apikey") @@ -206,11 +274,17 @@ def create_policy(policy_, edc_upload_url_, edc_policy_path_, headers_, session_ if default_policy is None: default_policy = "default-policy" + if aas_upload_url is None: + aas_upload_url = aas_url + check_url_args(submodel_server_upload_urls, submodel_server_urls, edc_upload_urls, edc_urls) edc_asset_path = "/api/v1/management/assets" edc_policy_path = "/api/v1/management/policydefinitions" edc_contract_definition_path = "/api/v1/management/contractdefinitions" + edc_catalog_path = "/api/v1/management/catalog/request" + + registry_asset_id = "registry-asset" headers = { 'Content-Type': 'application/json' @@ -223,7 +297,7 @@ def create_policy(policy_, edc_upload_url_, edc_policy_path_, headers_, session_ default_policy_definition = { "default": { - "id": default_policy, + "id": "default-policy", "policy": { "prohibitions": [], "obligations": [], @@ -260,6 +334,9 @@ def create_policy(policy_, edc_upload_url_, edc_policy_path_, headers_, session_ for url in edc_upload_urls: create_policy(policies[policy], url, edc_policy_path, headers_with_api_key, session) + create_registry_asset(edc_upload_urls, edc_asset_path, edc_contract_definition_path, edc_catalog_path, + headers_with_api_key, session, edc_urls, default_policy, registry_asset_id, aas_upload_url) + for tmp_data in testdata: catenax_id = tmp_data["catenaXId"] identification = uuid.uuid4().urn @@ -299,7 +376,7 @@ def create_policy(policy_, edc_upload_url_, edc_policy_path_, headers_, session_ policy_id = default_policy if "policy" in tmp_keys: policy_id = tmp_data["policy"] - print("Policy: " + policy_id) + print("Policy: " + policy_id) for tmp_key in tmp_keys: if "PlainObject" not in tmp_key and "catenaXId" not in tmp_key and "bpn" not in tmp_key and "policy" not in tmp_key: @@ -325,7 +402,6 @@ def create_policy(policy_, edc_upload_url_, edc_policy_path_, headers_, session_ endpoint_address) submodel_descriptors.append(json.loads(descriptor)) - edc_policy_id = str(uuid.uuid4()) asset_prop_id = catenax_id + "-" + submodel_identification print("Create submodel on submodel server") From 44352fb083c10462e3cd4dffa4385efc1989f196 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Mon, 8 May 2023 18:00:56 +0200 Subject: [PATCH 07/43] feat(local): Update local setup to decentralized registry --- .../full-irs/subcharts/discovery/Chart.yaml | 7 ++ .../discovery/templates/_helpers.tpl | 31 ++++++ .../discovery/templates/configmap.yaml | 95 ++++++++++++++++++ .../discovery/templates/deployment.yaml | 97 +++++++++++++++++++ .../subcharts/discovery/templates/hpa.yaml | 34 +++++++ .../discovery/templates/service.yaml | 21 ++++ .../discovery/templates/serviceaccount.yaml | 14 +++ .../full-irs/subcharts/discovery/values.yaml | 48 +++++++++ local/deployment/full-irs/upload-testdata.sh | 1 + 9 files changed, 348 insertions(+) create mode 100644 local/deployment/full-irs/subcharts/discovery/Chart.yaml create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/_helpers.tpl create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/configmap.yaml create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/service.yaml create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/serviceaccount.yaml create mode 100644 local/deployment/full-irs/subcharts/discovery/values.yaml diff --git a/local/deployment/full-irs/subcharts/discovery/Chart.yaml b/local/deployment/full-irs/subcharts/discovery/Chart.yaml new file mode 100644 index 0000000000..1882568915 --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/Chart.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v2 +name: discovery +description: Discovery +type: application +version: 0.0.1 +appVersion: "1.0.0" diff --git a/local/deployment/full-irs/subcharts/discovery/templates/_helpers.tpl b/local/deployment/full-irs/subcharts/discovery/templates/_helpers.tpl new file mode 100644 index 0000000000..96eaa19027 --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/_helpers.tpl @@ -0,0 +1,31 @@ +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "discovery.chart" -}} + {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "discovery.labels" -}} + service: {{ .Chart.Name }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "discovery.selectorLabels" -}} + service: {{ .Chart.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "discovery.serviceAccountName" -}} + {{- if .Values.serviceAccount.create -}} + {{- default .Chart.Name .Values.serviceAccount.name -}} + {{- else -}} + {{- default "default" .Values.serviceAccount.name -}} + {{- end -}} +{{- end -}} \ No newline at end of file diff --git a/local/deployment/full-irs/subcharts/discovery/templates/configmap.yaml b/local/deployment/full-irs/subcharts/discovery/templates/configmap.yaml new file mode 100644 index 0000000000..ec40598639 --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/configmap.yaml @@ -0,0 +1,95 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Chart.Name }} + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "discovery.labels" . | nindent 4 }} +data: + discovery_finder_request.json: |- + { + "request": { + "method": "POST", + "urlPathPattern": "/api/administration/connectors/discovery/search" + }, + "response": { + "status": 200, + "bodyFileName": "discovery_finder_response.json", + "headers": { + "Content-Type": "application/json" + } + } + } + + discovery_finder_response.json: |- + { + "endpoints": [ + { + "type": "bpn", + "description": "Service to discover EDC to a particular BPN", + "endpointAddress": "https://...", + "documentation": "http://.../swagger/index.html", + "resourceId": "316417cd-0fb5-4daf-8dfa-8f68125923f1" + } + ] + } + + edc_discovery_request.json: |- + { + "request": { + "method": "POST", + "urlPathPattern": "/discovery/api/administration/connectors/discovery" + }, + "response": { + "status": 200, + "bodyFileName": "edc_discovery_response.json", + "headers": { + "Content-Type": "application/json" + } + } + } + + edc_discovery_response.json: |- + [ + { + "bpn": "\\{\\{request.body.[0]\\}\\}", + "connectorEndpoint": [ + "https://irs-provider-controlplane.dev.demo.catena-x.net/", + "https://irs-provider-controlplane2.dev.demo.catena-x.net/", + "https://irs-provider-controlplane3.dev.demo.catena-x.net/" + ] + } + ] + + bpn_discovery_service_request.json: |- + { + "request": { + "method": "POST", + "urlPathPattern": "/api/administration/connectors/bpnDiscovery/search" + }, + "response": { + "status": 200, + "bodyFileName": "bpn_discovery_service_response.json", + "headers": { + "Content-Type": "application/json" + } + } + } + + bpn_discovery_service_response.json: |- + { + "bpns": [ + {"type": "bpn","key": ".*","value": "BPNL00000000BJTL","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003AVTH","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003AXS3","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003AYRE","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003AZQP","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003B0Q0","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003B2OM","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003B3NX","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003B5MJ","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003B5MJ","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"}, + {"type": "bpn","key": ".*","value": "BPNL00000003CSGV","resourceId": "1ca6f9b5-8e1d-422a-8541-9bb2cf5fe485"} + ] + } diff --git a/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml b/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml new file mode 100644 index 0000000000..25a41d1c87 --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml @@ -0,0 +1,97 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "discovery.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "discovery.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "discovery.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: {{ include "discovery.serviceAccountName" . }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: default + containerPort: 8080 + protocol: TCP + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /__admin + port: default + initialDelaySeconds: 30 + periodSeconds: 5 + failureThreshold: 3 + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /__admin + port: default + initialDelaySeconds: 30 + periodSeconds: 5 + failureThreshold: 3 + {{- end }} + envFrom: + - configMapRef: + name: {{ .Chart.Name }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: configuration + mountPath: /home/wiremock/mappings/discovery_finder_request.json + subPath: discovery_finder_request.json + - name: configuration + mountPath: home/wiremock/__files/discovery_finder_response.json + subPath: discovery_finder_response.json + - name: configuration + mountPath: /home/wiremock/mappings/bpn_discovery_service_request.json + subPath: bpn_discovery_service_request.json + - name: configuration + mountPath: home/wiremock/__files/bpn_discovery_service_response.json + subPath: bpn_discovery_service_response.json + - name: configuration + mountPath: /home/wiremock/mappings/edc_discovery_request.json.json + subPath: edc_discovery_request.json.json + - name: configuration + mountPath: home/wiremock/__files/edc_discovery_response.json + subPath: edc_discovery_response.json + - name: tmp + mountPath: /tmp + volumes: + - name: tmp + emptyDir: { } + - name: configuration + configMap: + name: {{ .Chart.Name }} + items: + - key: discovery_finder_request.json + path: discovery_finder_request.json + - key: discovery_finder_response.json + path: discovery_finder_response.json + - key: bpn_discovery_service_request.json + path: bpn_discovery_service_request.json + - key: bpn_discovery_service_response.json + path: bpn_discovery_service_response.json + - key: edc_discovery_request.json + path: edc_discovery_request.json + - key: edc_discovery_response.json + path: edc_discovery_response.json \ No newline at end of file diff --git a/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml b/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml new file mode 100644 index 0000000000..eb22672f3d --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.autoscaling.enabled -}} +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ .Chart.Name }} + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "discovery.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ .Chart.Name }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/local/deployment/full-irs/subcharts/discovery/templates/service.yaml b/local/deployment/full-irs/subcharts/discovery/templates/service.yaml new file mode 100644 index 0000000000..9f277a5742 --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/service.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "discovery.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: default + protocol: TCP + name: http + selector: + {{- include "discovery.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/local/deployment/full-irs/subcharts/discovery/templates/serviceaccount.yaml b/local/deployment/full-irs/subcharts/discovery/templates/serviceaccount.yaml new file mode 100644 index 0000000000..9c0f36b54e --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Chart.Name }} + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "discovery.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/local/deployment/full-irs/subcharts/discovery/values.yaml b/local/deployment/full-irs/subcharts/discovery/values.yaml new file mode 100644 index 0000000000..cc7803799b --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/values.yaml @@ -0,0 +1,48 @@ +--- +replicaCount: 1 + +image: + repository: wiremock/wiremock + pullPolicy: IfNotPresent + tag: "2.32.0" + +serviceAccount: + create: true + annotations: {} + name: "" + +livenessProbe: + enabled: true + +readinessProbe: + enabled: true + +service: + type: ClusterIP + port: 8080 + +resources: + limits: + cpu: 250m + memory: 512Mi + requests: + cpu: 250m + memory: 512Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 2 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + +securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsUser: 10001 + runAsGroup: 10001 + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ["ALL"] \ No newline at end of file diff --git a/local/deployment/full-irs/upload-testdata.sh b/local/deployment/full-irs/upload-testdata.sh index 05b17cdbf7..803c2b7ef9 100644 --- a/local/deployment/full-irs/upload-testdata.sh +++ b/local/deployment/full-irs/upload-testdata.sh @@ -6,6 +6,7 @@ python ../../testing/testdata/transform-and-upload.py \ -s http://irs-provider-backend:8080 \ -su http://localhost:10199 \ -a http://localhost:10200 \ + -au http://cx-irs-dependencies-registry-svc:8080 \ -edc http://edc-provider-control-plane:8282 \ -eu http://localhost:6181 \ -k password From 336a46797d8eeccd9e45bcc16816389be9c097ca Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Tue, 9 May 2023 10:12:12 +0200 Subject: [PATCH 08/43] feat(impl):[TRI-1192] extend with unit test --- .../services/BatchOrderEventListenerTest.java | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/BatchOrderEventListenerTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/BatchOrderEventListenerTest.java index 871339727c..a3c22775c6 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/BatchOrderEventListenerTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/BatchOrderEventListenerTest.java @@ -44,6 +44,7 @@ import org.eclipse.tractusx.irs.connector.batch.InMemoryBatchOrderStore; import org.eclipse.tractusx.irs.connector.batch.InMemoryBatchStore; import org.eclipse.tractusx.irs.connector.batch.JobProgress; +import org.eclipse.tractusx.irs.services.events.BatchOrderProcessingFinishedEvent; import org.eclipse.tractusx.irs.services.events.BatchOrderRegisteredEvent; import org.eclipse.tractusx.irs.services.events.BatchProcessingFinishedEvent; import org.eclipse.tractusx.irs.services.timeouts.TimeoutSchedulerBatchProcessingService; @@ -110,7 +111,7 @@ void shouldStartFirstBatch() { eventListener.handleBatchOrderRegisteredEvent(new BatchOrderRegisteredEvent(BATCH_ORDER_ID)); // then verify(irsItemGraphQueryService, times(numberOfJobs)).registerItemJob(any(), eq(FIRST_BATCH_ID)); - verify(timeoutScheduler, times(1)).registerBatchTimeout(eq(FIRST_BATCH_ID), eq(timeout)); + verify(timeoutScheduler, times(1)).registerBatchTimeout(FIRST_BATCH_ID, timeout); verify(timeoutScheduler, times(1)).registerJobsTimeout(anyList(), eq(timeout)); } @@ -151,10 +152,48 @@ void shouldStartNextBatchWhenPreviousFinished() { eventListener.handleBatchProcessingFinishedEvent(new BatchProcessingFinishedEvent(BATCH_ORDER_ID, FIRST_BATCH_ID, ProcessingState.PARTIAL, ProcessingState.COMPLETED, 1, "")); // then verify(irsItemGraphQueryService, times(numberOfJobs)).registerItemJob(any(), eq(SECOND_BATCH_ID)); - verify(timeoutScheduler, times(1)).registerBatchTimeout(eq(SECOND_BATCH_ID), eq(timeout)); + verify(timeoutScheduler, times(1)).registerBatchTimeout(SECOND_BATCH_ID, timeout); verify(timeoutScheduler, times(1)).registerJobsTimeout(anyList(), eq(timeout)); } + @Test + void shouldPublishBatchOrderProcessingFinishedEventWhenAllBatchesCompleted() { + // given + final int numberOfJobs = 10; + final int timeout = 60; + final BatchOrder batchOrder = BatchOrder.builder() + .batchOrderId(BATCH_ORDER_ID) + .batchOrderState(ProcessingState.PARTIAL) + .collectAspects(Boolean.TRUE) + .timeout(timeout) + .jobTimeout(timeout) + .lookupBPNs(Boolean.TRUE) + .build(); + final Batch firstBatch = Batch.builder() + .batchId(FIRST_BATCH_ID) + .batchState(ProcessingState.PARTIAL) + .batchNumber(1) + .batchState(ProcessingState.COMPLETED) + .batchOrderId(BATCH_ORDER_ID) + .build(); + final Batch secondBatch = Batch.builder() + .batchId(SECOND_BATCH_ID) + .batchState(ProcessingState.INITIALIZED) + .batchNumber(2) + .batchState(ProcessingState.COMPLETED) + .batchOrderId(BATCH_ORDER_ID) + .jobProgressList(createJobProgressList(numberOfJobs)) + .build(); + + batchOrderStore.save(BATCH_ORDER_ID, batchOrder); + batchStore.save(FIRST_BATCH_ID, firstBatch); + batchStore.save(SECOND_BATCH_ID, secondBatch); + // when + eventListener.handleBatchProcessingFinishedEvent(new BatchProcessingFinishedEvent(BATCH_ORDER_ID, SECOND_BATCH_ID, ProcessingState.PARTIAL, ProcessingState.COMPLETED, 2, "")); + // then + verify(applicationEventPublisher, times(1)).publishEvent(any(BatchOrderProcessingFinishedEvent.class)); + } + private List createJobProgressList(Integer size) { return IntStream.range(0, size) .boxed() From 03e0786c1aa5f6c64a412b5daf5f62a59ed58fde Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 9 May 2023 13:44:01 +0200 Subject: [PATCH 09/43] feat(local): Add discovery service mocks to irs-full --- local/deployment/full-irs/Chart.yaml | 5 ++ local/deployment/full-irs/forwardingPorts.sh | 1 + local/deployment/full-irs/installIRS.sh | 16 ++++ .../full-irs/subcharts/discovery/.helmignore | 23 +++++ .../full-irs/subcharts/discovery/Chart.yaml | 23 ++++- .../subcharts/discovery/templates/NOTES.txt | 22 +++++ .../discovery/templates/_helpers.tpl | 55 +++++++++--- .../discovery/templates/configmap.yaml | 37 +++++++-- .../discovery/templates/deployment.yaml | 74 ++++++++++++----- .../subcharts/discovery/templates/hpa.yaml | 40 ++++++--- .../discovery/templates/ingress.yaml | 83 +++++++++++++++++++ .../discovery/templates/service.yaml | 32 +++++-- .../discovery/templates/serviceaccount.yaml | 28 ++++++- .../templates/tests/test-connection.yaml | 15 ++++ .../full-irs/subcharts/discovery/values.yaml | 73 ++++++++++++---- .../full-irs/uninstallAllHelmCharts.sh | 1 + local/deployment/full-irs/values-dev.yaml | 26 ++++++ local/deployment/full-irs/values.yaml | 12 +++ 18 files changed, 481 insertions(+), 85 deletions(-) create mode 100644 local/deployment/full-irs/subcharts/discovery/.helmignore create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/NOTES.txt create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/ingress.yaml create mode 100644 local/deployment/full-irs/subcharts/discovery/templates/tests/test-connection.yaml diff --git a/local/deployment/full-irs/Chart.yaml b/local/deployment/full-irs/Chart.yaml index 1b3b9c8416..ca14d9b093 100644 --- a/local/deployment/full-irs/Chart.yaml +++ b/local/deployment/full-irs/Chart.yaml @@ -110,3 +110,8 @@ dependencies: version: 0.0.5 repository: "file://subcharts/irs-frontend-service" condition: install.irs.frontend + + - name: discovery + version: 0.0.1 + repository: "file://subcharts/discovery" + condition: install.discovery \ No newline at end of file diff --git a/local/deployment/full-irs/forwardingPorts.sh b/local/deployment/full-irs/forwardingPorts.sh index c1613b4859..6607ac11e4 100644 --- a/local/deployment/full-irs/forwardingPorts.sh +++ b/local/deployment/full-irs/forwardingPorts.sh @@ -9,6 +9,7 @@ kubectl port-forward svc/edc-daps 4567:4567 -n irs & kubectl port-forward svc/edc-provider-control-plane 6080:8080 6181:8181 -n irs & kubectl port-forward svc/edc-consumer-control-plane 7080:8080 7181:8181 -n irs & kubectl port-forward svc/semantic-hub 8088:8080 -n irs & +kubectl port-forward svc/discovery 8888:8080 -n irs & kubectl port-forward svc/cx-irs-dependencies-registry-svc 10200:8080 -n irs & kubectl port-forward svc/keycloak 4011:8080 -n irs & kubectl port-forward svc/irs-provider-backend 10199:8080 -n irs & diff --git a/local/deployment/full-irs/installIRS.sh b/local/deployment/full-irs/installIRS.sh index b44b19ae99..88ccd59e93 100644 --- a/local/deployment/full-irs/installIRS.sh +++ b/local/deployment/full-irs/installIRS.sh @@ -32,6 +32,22 @@ then kubectl wait deployment -n irs --for condition=Available --timeout=90s keycloak kubectl wait deployment -n irs --for condition=Available --timeout=90s irs-provider-backend + HELM_CHART_NAME=discovery + HELM_CHART=$(helm list -q -f "$HELM_CHART_NAME") + + if [ "$HELM_CHART" != "" ]; + then + echo -e "${BLUE}Un-installing helm chart: $HELM_CHART_NAME ${NC}" + helm uninstall $HELM_CHART_NAME --namespace irs + fi + + echo -e "${BLUE}Installing helm chart: $HELM_CHART_NAME ${NC}" + helm install $HELM_CHART_NAME \ + --set install.discovery=true \ + --namespace irs --create-namespace . + + echo -e "${BLUE}Waiting for the deployments to be available${NC}" + kubectl wait deployment -n irs --for condition=Available --timeout=90s discovery fi if $INSTALL_IRS_BACKEND diff --git a/local/deployment/full-irs/subcharts/discovery/.helmignore b/local/deployment/full-irs/subcharts/discovery/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/local/deployment/full-irs/subcharts/discovery/Chart.yaml b/local/deployment/full-irs/subcharts/discovery/Chart.yaml index 1882568915..ff5cc1a84b 100644 --- a/local/deployment/full-irs/subcharts/discovery/Chart.yaml +++ b/local/deployment/full-irs/subcharts/discovery/Chart.yaml @@ -1,7 +1,24 @@ ---- apiVersion: v2 name: discovery -description: Discovery +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) version: 0.0.1 -appVersion: "1.0.0" + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.0.1" diff --git a/local/deployment/full-irs/subcharts/discovery/templates/NOTES.txt b/local/deployment/full-irs/subcharts/discovery/templates/NOTES.txt new file mode 100644 index 0000000000..9d8c9a6ef8 --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "discovery.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "discovery.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "discovery.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "discovery.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/local/deployment/full-irs/subcharts/discovery/templates/_helpers.tpl b/local/deployment/full-irs/subcharts/discovery/templates/_helpers.tpl index 96eaa19027..97bba86109 100644 --- a/local/deployment/full-irs/subcharts/discovery/templates/_helpers.tpl +++ b/local/deployment/full-irs/subcharts/discovery/templates/_helpers.tpl @@ -1,31 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "discovery.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "discovery.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + {{/* Create chart name and version as used by the chart label. */}} {{- define "discovery.chart" -}} - {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} {{/* Common labels */}} {{- define "discovery.labels" -}} - service: {{ .Chart.Name }} -{{- end -}} +helm.sh/chart: {{ include "discovery.chart" . }} +{{ include "discovery.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} {{/* Selector labels */}} {{- define "discovery.selectorLabels" -}} - service: {{ .Chart.Name }} -{{- end -}} +app.kubernetes.io/name: {{ include "discovery.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} {{/* Create the name of the service account to use */}} {{- define "discovery.serviceAccountName" -}} - {{- if .Values.serviceAccount.create -}} - {{- default .Chart.Name .Values.serviceAccount.name -}} - {{- else -}} - {{- default "default" .Values.serviceAccount.name -}} - {{- end -}} -{{- end -}} \ No newline at end of file +{{- if .Values.serviceAccount.create }} +{{- default (include "discovery.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/local/deployment/full-irs/subcharts/discovery/templates/configmap.yaml b/local/deployment/full-irs/subcharts/discovery/templates/configmap.yaml index ec40598639..0c818c82f9 100644 --- a/local/deployment/full-irs/subcharts/discovery/templates/configmap.yaml +++ b/local/deployment/full-irs/subcharts/discovery/templates/configmap.yaml @@ -1,9 +1,29 @@ +# Copyright (c) 2021,2022,2023 + # 2022: ZF Friedrichshafen AG + # 2022: ISTOS GmbH + # 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # 2022,2023: BOSCH AG + # Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0. * + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + # --- apiVersion: v1 kind: ConfigMap metadata: - name: {{ .Chart.Name }} - namespace: {{ .Release.Namespace | default "default" | quote }} + name: {{ include "discovery.fullname" . }} labels: {{- include "discovery.labels" . | nindent 4 }} data: @@ -11,7 +31,7 @@ data: { "request": { "method": "POST", - "urlPathPattern": "/api/administration/connectors/discovery/search" + "urlPath": "/api/administration/connectors/discovery/search" }, "response": { "status": 200, @@ -28,7 +48,7 @@ data: { "type": "bpn", "description": "Service to discover EDC to a particular BPN", - "endpointAddress": "https://...", + "endpointAddress": "https://{{ .Values.wiremock.host }}/api/administration/connectors/discovery", "documentation": "http://.../swagger/index.html", "resourceId": "316417cd-0fb5-4daf-8dfa-8f68125923f1" } @@ -39,21 +59,22 @@ data: { "request": { "method": "POST", - "urlPathPattern": "/discovery/api/administration/connectors/discovery" + "urlPath": "/api/administration/connectors/discovery" }, "response": { "status": 200, "bodyFileName": "edc_discovery_response.json", "headers": { "Content-Type": "application/json" - } + }, + "transformers": ["response-template"] } } edc_discovery_response.json: |- [ { - "bpn": "\\{\\{request.body.[0]\\}\\}", + "bpn": "{{ printf "{{jsonPath request.body '$.[0]'}}" }}", "connectorEndpoint": [ "https://irs-provider-controlplane.dev.demo.catena-x.net/", "https://irs-provider-controlplane2.dev.demo.catena-x.net/", @@ -66,7 +87,7 @@ data: { "request": { "method": "POST", - "urlPathPattern": "/api/administration/connectors/bpnDiscovery/search" + "urlPath": "/api/administration/connectors/bpnDiscovery/search" }, "response": { "status": 200, diff --git a/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml b/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml index 25a41d1c87..55d7eac3da 100644 --- a/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml +++ b/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml @@ -1,58 +1,80 @@ +# Copyright (c) 2021,2022,2023 + # 2022: ZF Friedrichshafen AG + # 2022: ISTOS GmbH + # 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # 2022,2023: BOSCH AG + # Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0. * + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + # --- apiVersion: apps/v1 kind: Deployment metadata: - name: {{ .Chart.Name }} - namespace: {{ .Release.Namespace | default "default" | quote }} + name: {{ include "discovery.fullname" . }} labels: {{- include "discovery.labels" . | nindent 4 }} spec: + {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} + {{- end }} selector: matchLabels: {{- include "discovery.selectorLabels" . | nindent 6 }} template: metadata: + {{- with .Values.podAnnotations }} annotations: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} + {{- toYaml . | nindent 8 }} + {{- end }} labels: {{- include "discovery.selectorLabels" . | nindent 8 }} spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} serviceAccountName: {{ include "discovery.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --local-response-templating ports: - - name: default - containerPort: 8080 + - name: http + containerPort: {{ .Values.service.port }} protocol: TCP - {{- if .Values.livenessProbe.enabled }} livenessProbe: httpGet: path: /__admin - port: default + port: http initialDelaySeconds: 30 periodSeconds: 5 failureThreshold: 3 - {{- end }} - {{- if .Values.readinessProbe.enabled }} readinessProbe: httpGet: path: /__admin - port: default + port: http initialDelaySeconds: 30 periodSeconds: 5 failureThreshold: 3 - {{- end }} - envFrom: - - configMapRef: - name: {{ .Chart.Name }} resources: {{- toYaml .Values.resources | nindent 12 }} volumeMounts: @@ -69,8 +91,8 @@ spec: mountPath: home/wiremock/__files/bpn_discovery_service_response.json subPath: bpn_discovery_service_response.json - name: configuration - mountPath: /home/wiremock/mappings/edc_discovery_request.json.json - subPath: edc_discovery_request.json.json + mountPath: /home/wiremock/mappings/edc_discovery_request.json + subPath: edc_discovery_request.json - name: configuration mountPath: home/wiremock/__files/edc_discovery_response.json subPath: edc_discovery_response.json @@ -94,4 +116,16 @@ spec: - key: edc_discovery_request.json path: edc_discovery_request.json - key: edc_discovery_response.json - path: edc_discovery_response.json \ No newline at end of file + path: edc_discovery_response.json + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml b/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml index eb22672f3d..77236da938 100644 --- a/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml +++ b/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml @@ -1,17 +1,37 @@ -{{- if .Values.autoscaling.enabled -}} +# Copyright (c) 2021,2022,2023 + # 2022: ZF Friedrichshafen AG + # 2022: ISTOS GmbH + # 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # 2022,2023: BOSCH AG + # Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0. * + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + # --- -apiVersion: autoscaling/v2 +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: - name: {{ .Chart.Name }} - namespace: {{ .Release.Namespace | default "default" | quote }} + name: {{ include "discovery.fullname" . }} labels: {{- include "discovery.labels" . | nindent 4 }} spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment - name: {{ .Chart.Name }} + name: {{ include "discovery.fullname" . }} minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: @@ -19,16 +39,12 @@ spec: - type: Resource resource: name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} {{- end }} {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - type: Resource resource: name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} {{- end }} -{{- end -}} \ No newline at end of file +{{- end }} diff --git a/local/deployment/full-irs/subcharts/discovery/templates/ingress.yaml b/local/deployment/full-irs/subcharts/discovery/templates/ingress.yaml new file mode 100644 index 0000000000..e6a765e9e2 --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/ingress.yaml @@ -0,0 +1,83 @@ +# Copyright (c) 2021,2022,2023 + # 2022: ZF Friedrichshafen AG + # 2022: ISTOS GmbH + # 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # 2022,2023: BOSCH AG + # Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0. * + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + # +--- +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "discovery.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "discovery.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/local/deployment/full-irs/subcharts/discovery/templates/service.yaml b/local/deployment/full-irs/subcharts/discovery/templates/service.yaml index 9f277a5742..e653843e00 100644 --- a/local/deployment/full-irs/subcharts/discovery/templates/service.yaml +++ b/local/deployment/full-irs/subcharts/discovery/templates/service.yaml @@ -1,21 +1,37 @@ +# Copyright (c) 2021,2022,2023 + # 2022: ZF Friedrichshafen AG + # 2022: ISTOS GmbH + # 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # 2022,2023: BOSCH AG + # Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0. * + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + # --- apiVersion: v1 kind: Service metadata: - name: {{ .Chart.Name }} - namespace: {{ .Release.Namespace | default "default" | quote }} + name: {{ include "discovery.fullname" . }} labels: {{- include "discovery.labels" . | nindent 4 }} - {{- with .Values.service.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} spec: type: {{ .Values.service.type }} ports: - port: {{ .Values.service.port }} - targetPort: default + targetPort: http protocol: TCP name: http selector: - {{- include "discovery.selectorLabels" . | nindent 4 }} \ No newline at end of file + {{- include "discovery.selectorLabels" . | nindent 4 }} diff --git a/local/deployment/full-irs/subcharts/discovery/templates/serviceaccount.yaml b/local/deployment/full-irs/subcharts/discovery/templates/serviceaccount.yaml index 9c0f36b54e..dcdc8c407e 100644 --- a/local/deployment/full-irs/subcharts/discovery/templates/serviceaccount.yaml +++ b/local/deployment/full-irs/subcharts/discovery/templates/serviceaccount.yaml @@ -1,14 +1,34 @@ -{{- if .Values.serviceAccount.create -}} +# Copyright (c) 2021,2022,2023 + # 2022: ZF Friedrichshafen AG + # 2022: ISTOS GmbH + # 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # 2022,2023: BOSCH AG + # Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0. * + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + # --- +{{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount metadata: - name: {{ .Chart.Name }} - namespace: {{ .Release.Namespace | default "default" | quote }} + name: {{ include "discovery.serviceAccountName" . }} labels: {{- include "discovery.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} -{{- end -}} \ No newline at end of file +{{- end }} diff --git a/local/deployment/full-irs/subcharts/discovery/templates/tests/test-connection.yaml b/local/deployment/full-irs/subcharts/discovery/templates/tests/test-connection.yaml new file mode 100644 index 0000000000..6c7ceb2a78 --- /dev/null +++ b/local/deployment/full-irs/subcharts/discovery/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "discovery.fullname" . }}-test-connection" + labels: + {{- include "discovery.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "discovery.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/local/deployment/full-irs/subcharts/discovery/values.yaml b/local/deployment/full-irs/subcharts/discovery/values.yaml index cc7803799b..fe4c67e26e 100644 --- a/local/deployment/full-irs/subcharts/discovery/values.yaml +++ b/local/deployment/full-irs/subcharts/discovery/values.yaml @@ -1,26 +1,67 @@ ---- +# Default values for discovery. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + replicaCount: 1 image: repository: wiremock/wiremock pullPolicy: IfNotPresent - tag: "2.32.0" + tag: "2.35.0" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" serviceAccount: + # Specifies whether a service account should be created create: true + # Annotations to add to the service account annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template name: "" -livenessProbe: - enabled: true +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 10000 + runAsGroup: 3000 -readinessProbe: - enabled: true service: type: ClusterIP port: 8080 +wiremock: + host: "" + +ingress: + enabled: true + className: "nginx" + annotations: + nginx.ingress.kubernetes.io/ssl-passthrough: "false" + nginx.ingress.kubernetes.io/backend-protocol: "HTTP" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + hosts: + - host: "" + paths: + - path: / + pathType: ImplementationSpecific + tls: + - hosts: + - "" + secretName: tls-secret + resources: limits: cpu: 250m @@ -32,17 +73,13 @@ resources: autoscaling: enabled: false minReplicas: 1 - maxReplicas: 2 + maxReplicas: 100 targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} -securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - runAsUser: 10001 - runAsGroup: 10001 - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - capabilities: - drop: ["ALL"] \ No newline at end of file diff --git a/local/deployment/full-irs/uninstallAllHelmCharts.sh b/local/deployment/full-irs/uninstallAllHelmCharts.sh index 4952cc9ec9..a60c83a458 100644 --- a/local/deployment/full-irs/uninstallAllHelmCharts.sh +++ b/local/deployment/full-irs/uninstallAllHelmCharts.sh @@ -7,5 +7,6 @@ helm uninstall edc-consumer -n irs helm uninstall edc-provider -n irs helm uninstall edc-daps -n irs helm uninstall edc-vault -n irs +helm uninstall discovery -n irs helm list \ No newline at end of file diff --git a/local/deployment/full-irs/values-dev.yaml b/local/deployment/full-irs/values-dev.yaml index 66de94e826..79e4bd5c11 100644 --- a/local/deployment/full-irs/values-dev.yaml +++ b/local/deployment/full-irs/values-dev.yaml @@ -12,6 +12,7 @@ install: digitalTwin: true semanticHub: true keycloak: true + discovery: true irs: providerBackend: true @@ -114,6 +115,8 @@ config: hostname: &config-provider-backend-hostname "irs-full-submodel-server.dev.demo.catena-x.net" irs-frontend: hostname: &config-irs-frontend-hostname "irs-full-frontend.dev.demo.catena-x.net" + discovery: + host: &discovery-host "irs-full-discovery.dev.demo.catena-x.net" ###################### # DAPS Configuration # @@ -683,3 +686,26 @@ irs-provider-backend: - hosts: - *config-provider-backend-hostname secretName: tls-secret + +##################### +# Discovery Service # +##################### +discovery: + ingress: + enabled: true + className: "nginx" + annotations: + nginx.ingress.kubernetes.io/ssl-passthrough: "false" + nginx.ingress.kubernetes.io/backend-protocol: "HTTP" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + hosts: + - host: *discovery-host + paths: + - path: / + pathType: ImplementationSpecific + tls: + - hosts: + - *discovery-host + secretName: tls-secret + wiremock: + host: *discovery-host \ No newline at end of file diff --git a/local/deployment/full-irs/values.yaml b/local/deployment/full-irs/values.yaml index b8139046ec..e5e1bfab19 100644 --- a/local/deployment/full-irs/values.yaml +++ b/local/deployment/full-irs/values.yaml @@ -12,6 +12,7 @@ install: digitalTwin: false semanticHub: false keycloak: false + discovery: false irs: providerBackend: false @@ -108,6 +109,8 @@ config: grafana: user: *config-grafana-username password: *config-grafana-password + discovery: + host: &discovery-host "discovery:8080" # ########### # EDC VAULT # @@ -647,3 +650,12 @@ irs-frontend: client: id: *config-keycloak-client-id secret: *config-keycloak-client-secret + +##################### +# Discovery Service # +##################### +discovery: + ingress: + enabled: false + wiremock: + host: *discovery-host \ No newline at end of file From 9d679bec59b9e0baee3c7995e0f955dcb9fa11d1 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 9 May 2023 13:51:06 +0200 Subject: [PATCH 10/43] feat(local): Remove default ingress --- .../full-irs/subcharts/discovery/values.yaml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/local/deployment/full-irs/subcharts/discovery/values.yaml b/local/deployment/full-irs/subcharts/discovery/values.yaml index fe4c67e26e..438caeafa5 100644 --- a/local/deployment/full-irs/subcharts/discovery/values.yaml +++ b/local/deployment/full-irs/subcharts/discovery/values.yaml @@ -46,21 +46,7 @@ wiremock: host: "" ingress: - enabled: true - className: "nginx" - annotations: - nginx.ingress.kubernetes.io/ssl-passthrough: "false" - nginx.ingress.kubernetes.io/backend-protocol: "HTTP" - nginx.ingress.kubernetes.io/force-ssl-redirect: "true" - hosts: - - host: "" - paths: - - path: / - pathType: ImplementationSpecific - tls: - - hosts: - - "" - secretName: tls-secret + enabled: false resources: limits: From cfbad5da547c21b20584768c8a7f4e67c20d17ab Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 9 May 2023 13:52:09 +0200 Subject: [PATCH 11/43] feat(local): Remove hpa --- .../subcharts/discovery/templates/hpa.yaml | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml diff --git a/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml b/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml deleted file mode 100644 index 77236da938..0000000000 --- a/local/deployment/full-irs/subcharts/discovery/templates/hpa.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2021,2022,2023 - # 2022: ZF Friedrichshafen AG - # 2022: ISTOS GmbH - # 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - # 2022,2023: BOSCH AG - # Copyright (c) 2021,2022,2023 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License, Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0. * - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - # License for the specific language governing permissions and limitations - # under the License. - # - # SPDX-License-Identifier: Apache-2.0 - # ---- -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "discovery.fullname" . }} - labels: - {{- include "discovery.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "discovery.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} From 7e1f17534fc501ec5530cf31fca2cbc0c9f14cdf Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Tue, 9 May 2023 14:52:29 +0200 Subject: [PATCH 12/43] feat(charts): Update config map reference name --- .../full-irs/subcharts/discovery/templates/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml b/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml index 55d7eac3da..2d9a61d670 100644 --- a/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml +++ b/local/deployment/full-irs/subcharts/discovery/templates/deployment.yaml @@ -103,7 +103,7 @@ spec: emptyDir: { } - name: configuration configMap: - name: {{ .Chart.Name }} + name: {{ include "discovery.fullname" . }} items: - key: discovery_finder_request.json path: discovery_finder_request.json From bd80ce452c8cb06a5ab74197ca05d3ff6e347344 Mon Sep 17 00:00:00 2001 From: Jan Kreutzfeld Date: Tue, 9 May 2023 17:07:51 +0200 Subject: [PATCH 13/43] chore(release):[TRI-708] Add new workflow for release automation --- .github/workflows/release.yaml | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000000..88f42bcccd --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,46 @@ +name: Release IRS + +on: + workflow_dispatch: + push: + tags: + - '[0-9]+.[0-9]+.[0-9]+' + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Calculate Helm release version from CHANGELOG + run: echo HELM_VERSION=$(cat charts/irs-helm/CHANGELOG.md | sed -n 's/.*\[\([0-9]\+\.[0-9]\+\.[0-9]\+\)\].*/\1/p' | head -n 1) >> $GITHUB_ENV + + - name: Update Chart.yaml + run: | + sed -n -i 's/.*appVersion:.*/appVersion: ${{ github.ref_name }}/p' charts/irs-helm/Chart.yaml + sed -n -i 's/.*version:.*/version: ${{ env.HELM_VERSION }}/p' charts/irs-helm/Chart.yaml + + - name: Prepare Helm release + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "chore(release): Prepare release for Helm version ${{ env.HELM_VERSION }}" + branch: chore/prepare-helm-release-${{ env.HELM_VERSION }} + base: main + delete-branch: true + body: | + This PR prepares the Helm chart release for version ${{ env.HELM_VERSION }}. + Please check whether the Chart was updated correctly and that the CHANGELOG contains the relevant information + for this release. Also, make sure that the values.yaml is correct before merging this PR. + + - name: Extract changelog text + run: echo CHANGELOG=$(sed -n -e '/## \[${{ github.ref_name }}\]/,/## \[/ p' CHANGELOG.md | head -n -1) >> $GITHUB_ENV + + - name: Create IRS release + uses: softprops/action-gh-release@v1 + with: + body: ${{ env.CHANGELOG }} + + - name: Trigger Jira release + uses: ./.github/workflows/jira-publish-release.yaml + with: + version: ${{ github.ref_name }} \ No newline at end of file From ecf7db4dcdac2c11e75fc4e60afbef174a71362b Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Wed, 10 May 2023 09:08:10 +0200 Subject: [PATCH 14/43] feat(impl):[TRI-1080] change rules to match api --- .config/spectral/restBasicUrls.yml | 4 +-- .config/spectral/restBasicsJsonPayload.yml | 30 +++++++++++----------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.config/spectral/restBasicUrls.yml b/.config/spectral/restBasicUrls.yml index 74b8dad5cc..3756df4615 100644 --- a/.config/spectral/restBasicUrls.yml +++ b/.config/spectral/restBasicUrls.yml @@ -104,7 +104,7 @@ rules: # MUST use camelCase for query parameters - use-snake-case-for-query-parameters: + use-camel-case-for-query-parameters: description: | MUST use camelCase for query parameters message: '{{property}} use camelCase for query parameters: {{error}}' @@ -114,7 +114,7 @@ rules: then: function: pattern functionOptions: - match: "^[a-z]+([A-Z][a-z0-9]+)+" + match: "^[a-z]+([A-Z][a-z0-9]+)*$" # MUST pluralize resource names [134] # => https://opensource.zalando.com/restful-api-guidelines/#134 diff --git a/.config/spectral/restBasicsJsonPayload.yml b/.config/spectral/restBasicsJsonPayload.yml index 89b58916c8..5a2c4c58d5 100644 --- a/.config/spectral/restBasicsJsonPayload.yml +++ b/.config/spectral/restBasicsJsonPayload.yml @@ -21,17 +21,17 @@ rules: functionOptions: match: ^application\/(problem\+)?json$|^[a-zA-Z0-9_]+\/[-+.a-zA-Z0-9_]+;(v|version)=[0-9]+$ - # MUST property names must be ASCII camelCase - must-use-snake-case-for-property-names: - message: Property name has to be ASCII camelCase - description: MUST property names must be ASCII camelCase + # MUST property names must be ASCII pascalCase + must-use-pascal-case-for-property-names: + message: Property name has to be ASCII pascalCase + description: MUST property names must be ASCII pascalCase documentationUrl: https://opensource.zalando.com/restful-api-guidelines/#118 severity: error given: $.paths.*.*[responses,requestBody]..content..schema..properties.*~ then: function: pattern functionOptions: - match: ^[a-z]+([A-Z][a-z0-9]+)+ + match: ^[A-Z][a-z]+(?:[A-Z][a-z]+)*$ # SHOULD declare enum values using UPPER_SNAKE_CASE string [240] # => https://opensource.zalando.com/restful-api-guidelines/#240 @@ -75,15 +75,15 @@ rules: # SHOULD not use null for empty arrays [124] # => https://opensource.zalando.com/restful-api-guidelines/#124 - should-not-use-null-for-empty-array-values: - message: '{{error}}' - description: SHOULD not use null for empty arrays [124] - documentationUrl: https://opensource.zalando.com/restful-api-guidelines/#124 - severity: error - given: $..properties[?(@.type == 'array')] - then: - field: default - function: truthy +# should-not-use-null-for-empty-array-values: +# message: '{{error}}' +# description: SHOULD not use null for empty arrays [124] +# documentationUrl: https://opensource.zalando.com/restful-api-guidelines/#124 +# severity: error +# given: $..properties[?(@.type == 'array')] +# then: +# field: default +# function: truthy # MUST use common field names and semantics [174] # => https://opensource.zalando.com/restful-api-guidelines/#174 @@ -106,7 +106,7 @@ rules: then: function: pattern functionOptions: - match: "^[a-z0-9]+(?:_[a-z0-9]+)*$" + match: "^[a-z]+([A-Z][a-z0-9]+)*$" must-use-common-field-names-and-semantics-for-id-field: message: '{{error}}' From d1fae0e36e117875668ffa1d1446f7fd4f450d5e Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 10 May 2023 09:12:41 +0200 Subject: [PATCH 15/43] chore(testing): Add request collection for Discovery services --- local/testing/IRS_Request_Collection.json | 126 ++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/local/testing/IRS_Request_Collection.json b/local/testing/IRS_Request_Collection.json index 112c358031..14e0937519 100644 --- a/local/testing/IRS_Request_Collection.json +++ b/local/testing/IRS_Request_Collection.json @@ -281,6 +281,132 @@ "settingFollowRedirects": "global", "_type": "request" }, + { + "_id": "req_bf05cbc9e3254950a1f0b8799d63ba97", + "parentId": "fld_d8d37148ca95493196d260c5e6adbfc6", + "modified": 1683630958934, + "created": 1682672699249, + "url": "{{ _.BPN_DISCOVERY }}/api/administration/connectors/bpnDiscovery/search", + "name": "Query BPN Discovery", + "description": "", + "method": "POST", + "body": { + "mimeType": "application/json", + "text": "{\n \"searchFilter\": [\n {\n \"type\": \"oen\",\n \"keys\": [\n \"oen-1243\",\n \"oen-11\"\n ]\n },\n {\n \"type\": \"bpid\",\n \"keys\": [\n \"bpid-1243\",\n \"bpid-11\"\n ]\n }\n ]\n}" + }, + "parameters": [], + "headers": [ + { + "name": "Content-Type", + "value": "application/json" + } + ], + "authentication": { + "type": "oauth2", + "grantType": "client_credentials", + "accessTokenUrl": "{{ _.KEYCLOAK_TOKEN_URL }}", + "clientId": "{{ _.CLIENT_ID }}", + "clientSecret": "{{ _.CLIENT_SECRET }}", + "disabled": false + }, + "metaSortKey": -1683630902023, + "isPrivate": false, + "settingStoreCookies": true, + "settingSendCookies": true, + "settingDisableRenderRequestBody": false, + "settingEncodeUrl": true, + "settingRebuildPath": true, + "settingFollowRedirects": "global", + "_type": "request" + }, + { + "_id": "fld_d8d37148ca95493196d260c5e6adbfc6", + "parentId": "fld_ffbe46c3addc49fbb0247f24788433ea", + "modified": 1683630931664, + "created": 1683630887514, + "name": "Discovery", + "description": "", + "environment": {}, + "environmentPropertyOrder": null, + "metaSortKey": -1680682418417.5, + "_type": "request_group" + }, + { + "_id": "req_5cc5e7a14e4144c8930f7c1270fbbe99", + "parentId": "fld_d8d37148ca95493196d260c5e6adbfc6", + "modified": 1683630963691, + "created": 1683031718699, + "url": "{{ _.DISCOVERY_FINDER }}/api/administration/connectors/discovery/search", + "name": "Query Discovery Finder", + "description": "", + "method": "POST", + "body": { + "mimeType": "", + "text": "{\n \"types\": [\n \"bpn\"\n ]\n}" + }, + "parameters": [], + "headers": [ + { + "name": "Content-Type", + "value": "application/json" + } + ], + "authentication": { + "type": "oauth2", + "grantType": "client_credentials", + "accessTokenUrl": "{{ _.KEYCLOAK_TOKEN_URL }}", + "clientId": "{{ _.CLIENT_ID }}", + "clientSecret": "{{ _.CLIENT_SECRET }}", + "disabled": false + }, + "metaSortKey": -1683630901923, + "isPrivate": false, + "settingStoreCookies": true, + "settingSendCookies": true, + "settingDisableRenderRequestBody": false, + "settingEncodeUrl": true, + "settingRebuildPath": true, + "settingFollowRedirects": "global", + "_type": "request" + }, + { + "_id": "req_447e74079e50498ca92036cc4b044464", + "parentId": "fld_d8d37148ca95493196d260c5e6adbfc6", + "modified": 1683630977846, + "created": 1683560906453, + "url": "{{ _.EDC_DISCOVERY }}/api/administration/connectors/discovery", + "name": "Query EDC Discovery", + "description": "", + "method": "POST", + "body": { + "mimeType": "application/json", + "text": "[\n\t\"BPNL00000001CRHK\"\n]\t" + }, + "parameters": [], + "headers": [ + { + "name": "Content-Type", + "value": "application/json" + } + ], + "authentication": { + "type": "oauth2", + "grantType": "client_credentials", + "accessTokenUrl": "{{ _.KEYCLOAK_TOKEN_URL }}", + "clientId": "{{ _.CLIENT_ID }}", + "clientSecret": "{{ _.CLIENT_SECRET }}", + "disabled": false + }, + "metaSortKey": -1683630901873, + "isPrivate": false, + "settingStoreCookies": true, + "settingSendCookies": true, + "settingDisableRenderRequestBody": false, + "settingEncodeUrl": true, + "settingRebuildPath": true, + "settingFollowRedirects": "global", + "_type": "request" + }, { "_id": "fld_216efc7a70fe40b7b25378c60c4534f9", "parentId": "fld_ffbe46c3addc49fbb0247f24788433ea", From 7ce4238ae481396c1bba12231d97fccbec9bc01f Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Wed, 10 May 2023 10:07:32 +0200 Subject: [PATCH 16/43] feat(impl):[TRI-1080] change regexp --- .config/spectral/restBasicsJsonPayload.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.config/spectral/restBasicsJsonPayload.yml b/.config/spectral/restBasicsJsonPayload.yml index 5a2c4c58d5..13ea4f7c5c 100644 --- a/.config/spectral/restBasicsJsonPayload.yml +++ b/.config/spectral/restBasicsJsonPayload.yml @@ -22,16 +22,16 @@ rules: match: ^application\/(problem\+)?json$|^[a-zA-Z0-9_]+\/[-+.a-zA-Z0-9_]+;(v|version)=[0-9]+$ # MUST property names must be ASCII pascalCase - must-use-pascal-case-for-property-names: - message: Property name has to be ASCII pascalCase - description: MUST property names must be ASCII pascalCase + must-use-pascal-or-camel-case-for-property-names: + message: Property name has to be ASCII PascalCase or camelCase + description: MUST property names must be ASCII PascalCase or camelCase documentationUrl: https://opensource.zalando.com/restful-api-guidelines/#118 severity: error given: $.paths.*.*[responses,requestBody]..content..schema..properties.*~ then: function: pattern functionOptions: - match: ^[A-Z][a-z]+(?:[A-Z][a-z]+)*$ + match: ^[A-Z]?[a-z]+(?:[A-Z][a-z]+)*$ # SHOULD declare enum values using UPPER_SNAKE_CASE string [240] # => https://opensource.zalando.com/restful-api-guidelines/#240 From 99c8b1103cdac0e228edf677b3ee41d171ae19dc Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 10 May 2023 10:19:54 +0200 Subject: [PATCH 17/43] chore(testing): Update discovery request titles --- local/testing/IRS_Request_Collection.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/local/testing/IRS_Request_Collection.json b/local/testing/IRS_Request_Collection.json index 14e0937519..56de69f4b3 100644 --- a/local/testing/IRS_Request_Collection.json +++ b/local/testing/IRS_Request_Collection.json @@ -287,7 +287,7 @@ "modified": 1683630958934, "created": 1682672699249, "url": "{{ _.BPN_DISCOVERY }}/api/administration/connectors/bpnDiscovery/search", - "name": "Query BPN Discovery", + "name": "Find BPN endpoints for manufacturer numbers", "description": "", "method": "POST", "body": { @@ -337,7 +337,7 @@ "modified": 1683630963691, "created": 1683031718699, "url": "{{ _.DISCOVERY_FINDER }}/api/administration/connectors/discovery/search", - "name": "Query Discovery Finder", + "name": "Find BPN Discovery Endpoints of type BPN", "description": "", "method": "POST", "body": { @@ -375,7 +375,7 @@ "modified": 1683630977846, "created": 1683560906453, "url": "{{ _.EDC_DISCOVERY }}/api/administration/connectors/discovery", - "name": "Query EDC Discovery", + "name": "Find EDC endpoints for BPNs", "description": "", "method": "POST", "body": { From cf609f92e481796e0b57138da3cbc1fe80bb3d19 Mon Sep 17 00:00:00 2001 From: Jan Kreutzfeld Date: Wed, 10 May 2023 14:54:32 +0200 Subject: [PATCH 18/43] chore(release):[TRI-708] Replace sed with yq to improve readability --- .github/workflows/release.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 88f42bcccd..901684e3ad 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,9 +16,11 @@ jobs: run: echo HELM_VERSION=$(cat charts/irs-helm/CHANGELOG.md | sed -n 's/.*\[\([0-9]\+\.[0-9]\+\.[0-9]\+\)\].*/\1/p' | head -n 1) >> $GITHUB_ENV - name: Update Chart.yaml - run: | - sed -n -i 's/.*appVersion:.*/appVersion: ${{ github.ref_name }}/p' charts/irs-helm/Chart.yaml - sed -n -i 's/.*version:.*/version: ${{ env.HELM_VERSION }}/p' charts/irs-helm/Chart.yaml + uses: mikefarah/yq@v4.33.3 + with: + cmd: | + yq -i eval '.appVersion = ${{ github.ref_name }}' charts/irs-helm/Chart.yaml + yq -i eval '.version = ${{ env.HELM_VERSION }}' charts/irs-helm/Chart.yaml - name: Prepare Helm release uses: peter-evans/create-pull-request@v5 From 1496e7c2cff876a2c576c262bad377805011d430 Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Wed, 10 May 2023 15:36:54 +0200 Subject: [PATCH 19/43] feat(impl):[TRI-1163] validate bpn endpoint before starting job --- .../tractusx/irs/services/IrsItemGraphQueryService.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryService.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryService.java index bf198c1bcb..5ea68da43c 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryService.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryService.java @@ -36,6 +36,7 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.eclipse.tractusx.irs.aaswrapper.job.AASTransferProcess; import org.eclipse.tractusx.irs.aaswrapper.job.ItemContainer; import org.eclipse.tractusx.irs.aaswrapper.job.ItemDataRequest; @@ -71,6 +72,7 @@ import org.eclipse.tractusx.irs.semanticshub.SemanticsHubFacade; import org.eclipse.tractusx.irs.services.validation.SchemaNotFoundException; import org.eclipse.tractusx.irs.util.JsonUtil; +import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.support.MutableSortDefinition; import org.springframework.beans.support.PagedListHolder; import org.springframework.context.ApplicationEventPublisher; @@ -104,6 +106,9 @@ public class IrsItemGraphQueryService implements IIrsItemGraphQueryService { private final ApplicationEventPublisher applicationEventPublisher; + @Value("${bpdm.bpnEndpoint:}") + private String bpdmUrl; + @Override public PageResult getJobsByState(final @NonNull List states, final Pageable pageable) { final List jobs = states.isEmpty() ? jobStore.findAll() : jobStore.findByStates(states); @@ -156,6 +161,9 @@ public JobHandle registerItemJob(final @NonNull RegisterJob request, final UUID // Currently not supported variant throw new IllegalArgumentException("BomLifecycle asPlanned with direction upward is not supported yet!"); } + if (params.isLookupBPNs() && StringUtils.isBlank(bpdmUrl)) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Can't start job with BPN lookup - configured bpdm endpoint is empty!"); + } final JobInitiateResponse jobInitiateResponse = orchestrator.startJob(request.getGlobalAssetId(), params, batchId); meterRegistryService.incrementNumberOfCreatedJobs(); From b6fc434ae31c01cfc2280bffa66a5c13e6789d1c Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Wed, 10 May 2023 15:46:48 +0200 Subject: [PATCH 20/43] feat(impl):[TRI-1163] unit test --- .../irs/services/IrsItemGraphQueryServiceTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java index f96b556a4f..8bbd109a6a 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java @@ -23,6 +23,7 @@ package org.eclipse.tractusx.irs.services; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.irs.util.TestMother.registerJob; import static org.eclipse.tractusx.irs.util.TestMother.registerJobWithDepthAndAspect; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -42,6 +43,8 @@ import org.eclipse.tractusx.irs.component.Jobs; import org.eclipse.tractusx.irs.component.PageResult; import org.eclipse.tractusx.irs.component.Relationship; +import org.eclipse.tractusx.irs.component.enums.AspectType; +import org.eclipse.tractusx.irs.component.enums.Direction; import org.eclipse.tractusx.irs.component.enums.JobState; import org.eclipse.tractusx.irs.connector.job.JobStore; import org.eclipse.tractusx.irs.connector.job.MultiTransferJob; @@ -230,4 +233,13 @@ void shouldThrowExceptionForUnknownAspectTypes() throws SchemaNotFoundException assertThrows(IllegalArgumentException.class, executable); } + @Test + void shouldThrowExceptionWhenLookupBpnAndBpdmEndpointUrlIsMissing() throws SchemaNotFoundException { + when(semanticsHubFacade.getAllAspectModels()).thenReturn(AspectModels.builder().models(List.of(AspectModel.builder().name("AssemblyPartRelationship").build())).build()); + final Executable executable = () -> testee.registerItemJob(registerJob("urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4c79e", 5, + List.of(AspectType.ASSEMBLY_PART_RELATIONSHIP.toString()), false, true, Direction.DOWNWARD)); + + assertThrows(ResponseStatusException.class, executable); + } + } \ No newline at end of file From b3c10c0274b2d3334c1ef84dd3f4285d492580c0 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Wed, 10 May 2023 15:47:30 +0200 Subject: [PATCH 21/43] chore(dependencies): Update DEPENDENCIES --- DEPENDENCIES | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index ebf072069b..6d5e91a5bf 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -66,12 +66,12 @@ maven/mavencentral/io.swagger.core.v3/swagger-core/2.2.0, Apache-2.0, approved, maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.7, Apache-2.0, approved, #5919 maven/mavencentral/io.swagger.core.v3/swagger-models/2.2.0, Apache-2.0, approved, clearlydefined maven/mavencentral/io.swagger/swagger-annotations/1.6.8, Apache-2.0, approved, #3792 -maven/mavencentral/jakarta.activation/jakarta.activation-api/1.2.1, BSD-3-Clause, approved, #8017 -maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.1, BSD-3-Clause AND ((EPL-2.0 AND BSD-3-Clause AND GPL-2.0-only) AND LicenseRef-scancode-unknown-spdx), restricted, #8015 -maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 AND (GPL-2.0-only WITH Classpath-exception-2.0) AND (EPL-2.0 AND (GPL-2.0-only WITH Classpath-exception-2.0) AND LicenseRef-scancode-generic-export-compliance) AND (CDDL-1.0 AND EPL-2.0 AND (GPL-2.0-only WITH Classpath-exception-2.0)), restricted, #8018 +maven/mavencentral/jakarta.activation/jakarta.activation-api/1.2.1, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf +maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.1, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf +maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca maven/mavencentral/jakarta.validation/jakarta.validation-api/3.0.2, Apache-2.0, approved, clearlydefined -maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/2.3.2, CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, CQ16911 -maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.0, BSD-3-Clause, approved, #8016 +maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/2.3.2, BSD-3-Clause, approved, ee4j.jaxb +maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.0, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/junit/junit/4.13.2, EPL-2.0, approved, CQ23636 maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.12.23, Apache-2.0, approved, #1810 maven/mavencentral/net.bytebuddy/byte-buddy/1.12.23, Apache-2.0 AND BSD-3-Clause, approved, #1811 From ab305d714f77b0e2b6aec660b5407702be18ac05 Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Wed, 10 May 2023 15:48:34 +0200 Subject: [PATCH 22/43] feat(impl):[TRI-1163] unit test --- .../tractusx/irs/services/IrsItemGraphQueryServiceTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java index 8bbd109a6a..55dfa295a6 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java @@ -235,9 +235,11 @@ void shouldThrowExceptionForUnknownAspectTypes() throws SchemaNotFoundException @Test void shouldThrowExceptionWhenLookupBpnAndBpdmEndpointUrlIsMissing() throws SchemaNotFoundException { + final boolean lookupBPNs = true; when(semanticsHubFacade.getAllAspectModels()).thenReturn(AspectModels.builder().models(List.of(AspectModel.builder().name("AssemblyPartRelationship").build())).build()); + final Executable executable = () -> testee.registerItemJob(registerJob("urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4c79e", 5, - List.of(AspectType.ASSEMBLY_PART_RELATIONSHIP.toString()), false, true, Direction.DOWNWARD)); + List.of(AspectType.ASSEMBLY_PART_RELATIONSHIP.toString()), false, lookupBPNs, Direction.DOWNWARD)); assertThrows(ResponseStatusException.class, executable); } From 8de242fb25058513877ef6c2a2ca25a2c5f6cfd0 Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Wed, 10 May 2023 16:05:26 +0200 Subject: [PATCH 23/43] feat(impl):[TRI-1163] fix test --- .../java/org/eclipse/tractusx/irs/IrsFunctionalTest.java | 2 +- .../irs/services/IrsItemGraphQueryServiceTest.java | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsFunctionalTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsFunctionalTest.java index 33206e733a..7e22e94895 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsFunctionalTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/IrsFunctionalTest.java @@ -61,7 +61,7 @@ import org.testcontainers.shaded.org.awaitility.Awaitility; @Testcontainers -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "bpdm.bpnEndpoint=http://localbpdm.com" }) @ContextConfiguration(initializers = IrsFunctionalTest.MinioConfigInitializer.class) @ActiveProfiles(profiles = { "local" }) class IrsFunctionalTest { diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java index 55dfa295a6..2d06cd9824 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/services/IrsItemGraphQueryServiceTest.java @@ -23,8 +23,8 @@ package org.eclipse.tractusx.irs.services; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.irs.util.TestMother.registerJob; import static org.eclipse.tractusx.irs.util.TestMother.registerJobWithDepthAndAspect; +import static org.eclipse.tractusx.irs.util.TestMother.registerJobWithLookupBPNs; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -43,8 +43,6 @@ import org.eclipse.tractusx.irs.component.Jobs; import org.eclipse.tractusx.irs.component.PageResult; import org.eclipse.tractusx.irs.component.Relationship; -import org.eclipse.tractusx.irs.component.enums.AspectType; -import org.eclipse.tractusx.irs.component.enums.Direction; import org.eclipse.tractusx.irs.component.enums.JobState; import org.eclipse.tractusx.irs.connector.job.JobStore; import org.eclipse.tractusx.irs.connector.job.MultiTransferJob; @@ -235,11 +233,9 @@ void shouldThrowExceptionForUnknownAspectTypes() throws SchemaNotFoundException @Test void shouldThrowExceptionWhenLookupBpnAndBpdmEndpointUrlIsMissing() throws SchemaNotFoundException { - final boolean lookupBPNs = true; when(semanticsHubFacade.getAllAspectModels()).thenReturn(AspectModels.builder().models(List.of(AspectModel.builder().name("AssemblyPartRelationship").build())).build()); - final Executable executable = () -> testee.registerItemJob(registerJob("urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4c79e", 5, - List.of(AspectType.ASSEMBLY_PART_RELATIONSHIP.toString()), false, lookupBPNs, Direction.DOWNWARD)); + final Executable executable = () -> testee.registerItemJob(registerJobWithLookupBPNs()); assertThrows(ResponseStatusException.class, executable); } From 5f61bc09d91d0e6d779283091349b426e1cf7df1 Mon Sep 17 00:00:00 2001 From: Jan Kreutzfeld Date: Wed, 10 May 2023 21:02:51 +0200 Subject: [PATCH 24/43] chore(release):[TRI-708] Fix release workflow --- .github/workflows/release.yaml | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 901684e3ad..2781138666 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,12 +15,15 @@ jobs: - name: Calculate Helm release version from CHANGELOG run: echo HELM_VERSION=$(cat charts/irs-helm/CHANGELOG.md | sed -n 's/.*\[\([0-9]\+\.[0-9]\+\.[0-9]\+\)\].*/\1/p' | head -n 1) >> $GITHUB_ENV - - name: Update Chart.yaml + - name: Update Chart.yaml appVersion uses: mikefarah/yq@v4.33.3 with: - cmd: | - yq -i eval '.appVersion = ${{ github.ref_name }}' charts/irs-helm/Chart.yaml - yq -i eval '.version = ${{ env.HELM_VERSION }}' charts/irs-helm/Chart.yaml + cmd: yq -i eval '.appVersion = "${{ github.ref_name }}"' charts/irs-helm/Chart.yaml + + - name: Update Chart.yaml version + uses: mikefarah/yq@v4.33.3 + with: + cmd: yq -i eval '.version = "${{ env.HELM_VERSION }}"' charts/irs-helm/Chart.yaml - name: Prepare Helm release uses: peter-evans/create-pull-request@v5 @@ -42,7 +45,9 @@ jobs: with: body: ${{ env.CHANGELOG }} - - name: Trigger Jira release - uses: ./.github/workflows/jira-publish-release.yaml - with: - version: ${{ github.ref_name }} \ No newline at end of file + trigger-jira: + needs: + - release + uses: ./.github/workflows/jira-publish-release.yaml + with: + version: ${{ github.ref_name }} \ No newline at end of file From b29ca7a693e6e114012c688aeb0f8ee2781ac672 Mon Sep 17 00:00:00 2001 From: Jan Kreutzfeld Date: Thu, 11 May 2023 08:42:05 +0200 Subject: [PATCH 25/43] chore(release):[TRI-708] Add call trigger for jira workflow --- .github/workflows/jira-publish-release.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/jira-publish-release.yaml b/.github/workflows/jira-publish-release.yaml index c62e93dbbd..da15c3da38 100644 --- a/.github/workflows/jira-publish-release.yaml +++ b/.github/workflows/jira-publish-release.yaml @@ -7,7 +7,12 @@ on: required: true type: string description: Version that will be released in Jira, eg. 2.0.0 - + workflow_call: + inputs: + version: + required: true + type: string + description: Version that will be released in Jira, eg. 2.0.0 jobs: build: runs-on: ubuntu-latest From 1388ef73fd969157055e0ffb26ad5acf6f01688f Mon Sep 17 00:00:00 2001 From: Jan Kreutzfeld Date: Thu, 11 May 2023 09:40:36 +0200 Subject: [PATCH 26/43] chore(release):[TRI-708] Add title for PR --- .github/workflows/release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2781138666..e222f42a0a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -32,6 +32,7 @@ jobs: branch: chore/prepare-helm-release-${{ env.HELM_VERSION }} base: main delete-branch: true + title: Prepare Helm release for next version body: | This PR prepares the Helm chart release for version ${{ env.HELM_VERSION }}. Please check whether the Chart was updated correctly and that the CHANGELOG contains the relevant information From 1abfefb22d7476ab9b0f819012a0c11ab7bfcaf8 Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Thu, 11 May 2023 10:46:36 +0200 Subject: [PATCH 27/43] feat(charts): Adjust bpdm.bpnEndpoint template to be empty if bpdm.url is not set --- charts/irs-helm/CHANGELOG.md | 2 ++ charts/irs-helm/values.yaml | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/charts/irs-helm/CHANGELOG.md b/charts/irs-helm/CHANGELOG.md index 4cb0f5d2c7..762badf383 100644 --- a/charts/irs-helm/CHANGELOG.md +++ b/charts/irs-helm/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- `bpdm.bpnEndpoint` will not be set to an unresolvable URL if `bpdm.url` is not set. ## [5.3.0] - 2023-05-05 ### Added diff --git a/charts/irs-helm/values.yaml b/charts/irs-helm/values.yaml index dfc30717d5..5edc04786e 100644 --- a/charts/irs-helm/values.yaml +++ b/charts/irs-helm/values.yaml @@ -132,7 +132,9 @@ semanticshub: bpdm: url: # https:// bpnEndpoint: >- - {{ tpl (.Values.bpdm.url | default "") . }}/api/catena/legal-entities/{partnerId}?idType={idType} + {{- if .Values.bpdm.url }} + {{- tpl (.Values.bpdm.url | default "") . }}/api/catena/legal-entities/{partnerId}?idType={idType} + {{- end }} minioUser: "minio" # minioPassword: # minioUrl: "http://{{ .Release.Name }}-minio:9000" From 65551e10cad03241cb4dd3e9cb33b92cf22e194d Mon Sep 17 00:00:00 2001 From: Jaro Hartmann Date: Thu, 11 May 2023 11:26:17 +0200 Subject: [PATCH 28/43] chore(workflows): Add kind-registry image repository for helm testing --- .github/workflows/helm-test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/helm-test.yaml b/.github/workflows/helm-test.yaml index 084f7362d4..4eb2ff6d94 100644 --- a/.github/workflows/helm-test.yaml +++ b/.github/workflows/helm-test.yaml @@ -56,5 +56,5 @@ jobs: helm repo add minio https://charts.min.io/ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo add grafana https://grafana.github.io/helm-charts - ct install --charts charts/irs-helm --helm-extra-set-args "--set=image.tag=testing" + ct install --charts charts/irs-helm --helm-extra-set-args "--set=image.tag=testing --set=image.repository=kind-registry:5000/irs-api" if: steps.list-changed.outputs.changed == 'true' \ No newline at end of file From da6f3de26939be9f14e0def6c0aadcf2047abb10 Mon Sep 17 00:00:00 2001 From: Adam Bugajewski Date: Fri, 12 May 2023 09:25:45 +0200 Subject: [PATCH 29/43] fix(api):[TRI-1094] [CVE][PENTEST][MEDIUM] Blind Server Side Request Forgery - bugfix, validate if callback url starts with http or https --- .../irs/controllers/IrsControllerTest.java | 23 +++++++++++++++++++ .../eclipse/tractusx/irs/util/TestMother.java | 6 +++++ .../tractusx/irs/component/RegisterJob.java | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/controllers/IrsControllerTest.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/controllers/IrsControllerTest.java index fd30d13271..deb25c0718 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/controllers/IrsControllerTest.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/controllers/IrsControllerTest.java @@ -25,6 +25,7 @@ import static java.lang.String.format; import static org.eclipse.tractusx.irs.util.TestMother.registerJob; import static org.eclipse.tractusx.irs.util.TestMother.registerJobWithDepthAndAspect; +import static org.eclipse.tractusx.irs.util.TestMother.registerJobWithUrl; import static org.eclipse.tractusx.irs.util.TestMother.registerJobWithoutDepthAndAspect; import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -148,6 +149,28 @@ void shouldReturnBadRequestWhenRegisterJobBodyNotValid(final RegisterJob registe .andExpect(status().isBadRequest()); } + @Test + @WithMockUser(authorities = "view_irs") + void shouldReturnBadRequestWhenRegisterJobHasWrongCallbackUrl() throws Exception { + this.mockMvc.perform(post("/irs/jobs").contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString( + registerJobWithUrl("hhh://example.com")))) + .andExpect(status().isBadRequest()); + } + + @Test + @WithMockUser(authorities = "view_irs") + void shouldAcceptCorrectCallbackUrl() throws Exception { + final UUID returnedJob = UUID.randomUUID(); + when(service.registerItemJob(any())).thenReturn(JobHandle.builder().id(returnedJob).build()); + when(authorizationService.verifyBpn()).thenReturn(Boolean.TRUE); + + this.mockMvc.perform(post("/irs/jobs").contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString( + registerJobWithUrl("https://example.com")))) + .andExpect(status().isCreated()); + } + @Test @WithMockUser(authorities = "view_irs") void getJobsByState() throws Exception { diff --git a/irs-api/src/test/java/org/eclipse/tractusx/irs/util/TestMother.java b/irs-api/src/test/java/org/eclipse/tractusx/irs/util/TestMother.java index 3c03fa7c8b..40efa99284 100644 --- a/irs-api/src/test/java/org/eclipse/tractusx/irs/util/TestMother.java +++ b/irs-api/src/test/java/org/eclipse/tractusx/irs/util/TestMother.java @@ -87,6 +87,12 @@ public static RegisterJob registerJobWithDirection(final String globalAssetId, f return registerJob(globalAssetId, 100, List.of(), false, false, direction); } + public static RegisterJob registerJobWithUrl(final String callbackUrl) { + final RegisterJob registerJob = registerJob("urn:uuid:4132cd2b-cbe7-4881-a6b4-39fdc31cca2b", 100, List.of(), false, false, Direction.DOWNWARD); + registerJob.setCallbackUrl(callbackUrl); + return registerJob; + } + public static RegisterJob registerJobWithDepthAndAspectAndCollectAspects(final Integer depth, final List aspectTypes) { return registerJob("urn:uuid:4132cd2b-cbe7-4881-a6b4-39fdc31cca2b", depth, aspectTypes, diff --git a/irs-models/src/main/java/org/eclipse/tractusx/irs/component/RegisterJob.java b/irs-models/src/main/java/org/eclipse/tractusx/irs/component/RegisterJob.java index 99d953ca92..851ee3fb1b 100644 --- a/irs-models/src/main/java/org/eclipse/tractusx/irs/component/RegisterJob.java +++ b/irs-models/src/main/java/org/eclipse/tractusx/irs/component/RegisterJob.java @@ -87,7 +87,7 @@ public class RegisterJob { @Schema(description = "Flag to specify whether BPNs should be collected and resolved via the configured BPDM URL. Default is false.") private boolean lookupBPNs; - @URL + @URL(regexp = "^(http|https).*") @Schema(description = "Callback url to notify requestor when job processing is finished. There are two uri variable placeholders that can be used: id and state.", example = "https://hostname.com/callback?id={id}&state={state}") private String callbackUrl; From 880e50c0bb9568266e6c7f76278b303266c59a2b Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Fri, 12 May 2023 15:11:01 +0200 Subject: [PATCH 30/43] feat(impl):[TRI-XXX] adjustments for smells --- .../tractusx/irs/configuration/TrustedPortConfiguration.java | 2 +- .../tractusx/irs/connector/job/PersistentJobStore.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/TrustedPortConfiguration.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/TrustedPortConfiguration.java index 3ca7652b40..1b0f81f44d 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/TrustedPortConfiguration.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/configuration/TrustedPortConfiguration.java @@ -58,7 +58,7 @@ public TrustedPortConfiguration(@Value("${server.port:8080}") final String serve } @Bean - public WebServerFactoryCustomizer servletContainer() { + public WebServerFactoryCustomizer servletContainer() { final Connector[] additionalConnectors = this.additionalConnector(); diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/job/PersistentJobStore.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/job/PersistentJobStore.java index 30ca2690ad..5b228839fc 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/job/PersistentJobStore.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/connector/job/PersistentJobStore.java @@ -130,9 +130,9 @@ private String toBlobId(final String jobId) { return JOB_PREFIX + jobId; } - private Boolean isLastStateSameAsCurrentState(final String jobId, final JobState state) { + private boolean isLastStateSameAsCurrentState(final String jobId, final JobState state) { final Optional optJob = get(jobId); - return optJob.isPresent() && optJob.get().getJob().getState() == state; + return optJob.isPresent() && optJob.get().getJob().getState().equals(state); } } From e945d9db7ff467635841791f8783008c874dbaa8 Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Fri, 12 May 2023 15:23:16 +0200 Subject: [PATCH 31/43] feat(impl):[TRI-1222] introduce constant after review --- .../irs/controllers/BatchController.java | 18 +++++++------- .../irs/controllers/IrsController.java | 24 +++++++++++-------- .../tractusx/irs/common/ApiConstants.java | 9 +++++++ .../ess/controller/EssController.java | 10 ++++---- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java index 8c95994cfc..3094d6e4dd 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/BatchController.java @@ -22,6 +22,8 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.controllers; +import static org.eclipse.tractusx.irs.common.ApiConstants.FORBIDDEN_DESC; +import static org.eclipse.tractusx.irs.common.ApiConstants.UNAUTHORIZED_DESC; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import java.util.UUID; @@ -96,13 +98,13 @@ public class BatchController { examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", @@ -135,13 +137,13 @@ public BatchOrderCreated registerBatchOrder(final @Valid @RequestBody RegisterBa examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", @@ -181,13 +183,13 @@ public BatchOrderResponse getBatchOrder( examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", @@ -230,13 +232,13 @@ public BatchResponse getBatch( examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", diff --git a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/IrsController.java b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/IrsController.java index 9c306e29c2..536317cfe3 100644 --- a/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/IrsController.java +++ b/irs-api/src/main/java/org/eclipse/tractusx/irs/controllers/IrsController.java @@ -23,6 +23,8 @@ package org.eclipse.tractusx.irs.controllers; import static io.swagger.v3.oas.annotations.enums.ParameterIn.QUERY; +import static org.eclipse.tractusx.irs.common.ApiConstants.FORBIDDEN_DESC; +import static org.eclipse.tractusx.irs.common.ApiConstants.UNAUTHORIZED_DESC; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import java.util.List; @@ -85,6 +87,8 @@ }) public class IrsController { + + private final IrsItemGraphQueryService itemJobService; private final SemanticHubService semanticHubService; private final AuthorizationService authorizationService; @@ -107,13 +111,13 @@ public class IrsController { examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", @@ -153,13 +157,13 @@ public JobHandle registerJobForGlobalAssetId(final @Valid @RequestBody RegisterJ examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", @@ -202,13 +206,13 @@ public Jobs getJobById( examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", @@ -249,13 +253,13 @@ public Job cancelJobByJobId( examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", @@ -287,13 +291,13 @@ public PageResult getJobsByState( examples = { @ExampleObject(name = "complete", ref = "#/components/examples/aspect-models-list") }) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", diff --git a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/ApiConstants.java b/irs-common/src/main/java/org/eclipse/tractusx/irs/common/ApiConstants.java index 05665a2380..d52cf42318 100644 --- a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/ApiConstants.java +++ b/irs-common/src/main/java/org/eclipse/tractusx/irs/common/ApiConstants.java @@ -36,4 +36,13 @@ public class ApiConstants { */ public static final String API_PREFIX_INTERNAL = "internal"; + /** + * + */ + public static final String UNAUTHORIZED_DESC = "No valid authentication credentials."; + /** + * + */ + public static final String FORBIDDEN_DESC = "Authorization refused by server."; + } diff --git a/irs-ess/src/main/java/org/eclipse/tractusx/ess/controller/EssController.java b/irs-ess/src/main/java/org/eclipse/tractusx/ess/controller/EssController.java index 0da66da59a..505ed1efd0 100644 --- a/irs-ess/src/main/java/org/eclipse/tractusx/ess/controller/EssController.java +++ b/irs-ess/src/main/java/org/eclipse/tractusx/ess/controller/EssController.java @@ -22,6 +22,8 @@ ********************************************************************************/ package org.eclipse.tractusx.ess.controller; +import static org.eclipse.tractusx.irs.common.ApiConstants.FORBIDDEN_DESC; +import static org.eclipse.tractusx.irs.common.ApiConstants.UNAUTHORIZED_DESC; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import java.util.UUID; @@ -86,13 +88,13 @@ class EssController { examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", @@ -124,13 +126,13 @@ public JobHandle registerBPNInvestigation(final @Valid @RequestBody RegisterBpnI examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-400")) }), - @ApiResponse(responseCode = "401", description = "No valid authentication credentials.", + @ApiResponse(responseCode = "401", description = UNAUTHORIZED_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", ref = "#/components/examples/error-response-401")) }), - @ApiResponse(responseCode = "403", description = "Authorization refused by server.", + @ApiResponse(responseCode = "403", description = FORBIDDEN_DESC, content = { @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class), examples = @ExampleObject(name = "error", From 427e6cc91a658f93a774822e34a244c2d9a301c3 Mon Sep 17 00:00:00 2001 From: "Krzysztof Massalski (Extern)" Date: Fri, 12 May 2023 15:28:54 +0200 Subject: [PATCH 32/43] feat(impl):[TRI-1222] introduce constant after review --- .../java/org/eclipse/tractusx/irs/common/ApiConstants.java | 4 ++-- .../org/eclipse/tractusx/ess/controller/EssController.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/ApiConstants.java b/irs-common/src/main/java/org/eclipse/tractusx/irs/common/ApiConstants.java index d52cf42318..a1ba337060 100644 --- a/irs-common/src/main/java/org/eclipse/tractusx/irs/common/ApiConstants.java +++ b/irs-common/src/main/java/org/eclipse/tractusx/irs/common/ApiConstants.java @@ -37,11 +37,11 @@ public class ApiConstants { public static final String API_PREFIX_INTERNAL = "internal"; /** - * + * Api description for 401 http status */ public static final String UNAUTHORIZED_DESC = "No valid authentication credentials."; /** - * + * Api description for 403 http status */ public static final String FORBIDDEN_DESC = "Authorization refused by server."; diff --git a/irs-ess/src/main/java/org/eclipse/tractusx/ess/controller/EssController.java b/irs-ess/src/main/java/org/eclipse/tractusx/ess/controller/EssController.java index 505ed1efd0..b71f5bb944 100644 --- a/irs-ess/src/main/java/org/eclipse/tractusx/ess/controller/EssController.java +++ b/irs-ess/src/main/java/org/eclipse/tractusx/ess/controller/EssController.java @@ -64,7 +64,8 @@ @RequiredArgsConstructor @Validated @SuppressWarnings({ "PMD.AvoidDuplicateLiterals", - "PMD.ShortVariable" + "PMD.ShortVariable", + "PMD.ExcessiveImports" }) class EssController { From 37633a5ea5ee178bf895d63ae8b257cd1d89d2dc Mon Sep 17 00:00:00 2001 From: Adam Bugajewski Date: Mon, 15 May 2023 10:27:50 +0200 Subject: [PATCH 33/43] chore(release): Prepare IRS release 2.6.1 and helm 5.3.1 --- .run/IrsApplication.run.xml | 2 +- CHANGELOG.md | 9 ++++++++- charts/irs-helm/CHANGELOG.md | 2 ++ charts/irs-helm/Chart.yaml | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.run/IrsApplication.run.xml b/.run/IrsApplication.run.xml index 0837bbec03..e5631923d0 100644 --- a/.run/IrsApplication.run.xml +++ b/.run/IrsApplication.run.xml @@ -2,7 +2,7 @@