Skip to content

Commit

Permalink
Merge branch 'main' into chore/#247-update-upload-testdata-documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
dsmf committed Nov 17, 2023
2 parents 982cb71 + 1fa8ef5 commit 5bd41ca
Show file tree
Hide file tree
Showing 32 changed files with 937 additions and 150 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/integration-test-DEV.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ jobs:
trigger-integration-test:
uses: ./.github/workflows/xray-cucumber-integration.yaml
secrets:
keycloakTokenUrl: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_TOKEN_URI }}
clientId: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_ID }}
clientSecret: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_SECRET }}
oauth2TokenUrl: ${{ secrets.OAUTH2_CLIENT_TOKEN_URI }}
clientId: ${{ secrets.OAUTH2_CLIENT_ID }}
clientSecret: ${{ secrets.OAUTH2_CLIENT_SECRET }}
jiraUser: ${{ secrets.ORG_IRS_JIRA_USERNAME }}
jiraPassword: ${{ secrets.ORG_IRS_JIRA_PASSWORD }}
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration-test-DIL.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
trigger-integration-test:
uses: ./.github/workflows/xray-cucumber-integration.yaml
secrets:
keycloakTokenUrl: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_TOKEN_URI }}
oauth2TokenUrl: ${{ secrets.OAUTH2_CLIENT_TOKEN_URI }}
clientId: ${{ secrets.IRS_OAUTH2_CLIENT_ID_DIL }}
clientSecret: ${{ secrets.IRS_OAUTH2_CLIENT_SECRET_DIL }}
jiraUser: ${{ secrets.ORG_IRS_JIRA_USERNAME }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration-test-INT.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
trigger-integration-test:
uses: ./.github/workflows/xray-cucumber-integration.yaml
secrets:
keycloakTokenUrl: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_TOKEN_URI }}
oauth2TokenUrl: ${{ secrets.OAUTH2_CLIENT_TOKEN_URI }}
clientId: ${{ secrets.ORG_IRS_OAUTH2_CLIENT_ID_INT }}
clientSecret: ${{ secrets.ORG_IRS_OAUTH2_CLIENT_SECRET_INT }}
jiraUser: ${{ secrets.ORG_IRS_JIRA_USERNAME }}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/xray-cucumber.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ jobs:
trigger-integration-test:
uses: ./.github/workflows/xray-cucumber-integration.yaml
secrets:
keycloakTokenUrl: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_TOKEN_URI }}
clientId: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_ID }}
clientSecret: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_SECRET }}
oauth2TokenUrl: ${{ secrets.OAUTH2_CLIENT_TOKEN_URI }}
clientId: ${{ secrets.OAUTH2_CLIENT_ID }}
clientSecret: ${{ secrets.OAUTH2_CLIENT_SECRET }}
jiraUser: ${{ secrets.ORG_IRS_JIRA_USERNAME }}
jiraPassword: ${{ secrets.ORG_IRS_JIRA_PASSWORD }}
with:
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ 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]
### Changed
- ESS
- Added 'hops' parameter to SupplyChainImpacted Aspect model - contains relative distance in the supply chain
- Added `impactedSuppliersOnFirstTier` parameter to Supply SupplyChainImpacted Aspect model - contains information of first level supply chain impacted

### Known knowns
- [#253] Cancelation of order jobs is not working stable

## [4.1.0] - 2023-11-15
### Added
Expand Down
2 changes: 2 additions & 0 deletions charts/irs-helm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
- Fixed templating for `management.health.dependencies`

## [6.10.0]
### Changed
Expand Down
4 changes: 2 additions & 2 deletions charts/irs-helm/templates/configmap-spring-app-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ data:
management:
health:
dependencies:
enabled: {{ tpl (.Values.management.health.dependencies.enabled | default "false") . | quote }}
enabled: {{ .Values.management.health.dependencies.enabled | default false }}
urls:
{{- tpl (toYaml .Values.management.health.dependencies.urls) . | nindent 10 }}
{{- tpl (toYaml .Values.management.health.dependencies.urls) . | nindent 12 }}
{{- end }}
{{- end }}
Expand Down
3 changes: 2 additions & 1 deletion charts/irs-helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ management:
health:
dependencies:
enabled: false # Flag to determine if external service healthcheck endpoints should be checked
urls: {} # Map of services with corresponding healthcheck endpoint url's, example service_name: http://service_name_host.com/health
urls: {} # Map of services with corresponding healthcheck endpoint url's. Example:
# service_name: http://service_name_host.com/health

digitalTwinRegistry:
type: decentral # The type of DTR. This can be either "central" or "decentral". If "decentral", descriptorEndpoint, shellLookupEndpoint and oAuthClientId is not required.
Expand Down
9 changes: 7 additions & 2 deletions docs/src/api/irs-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2524,6 +2524,11 @@ components:
type: object
additionalProperties: false
properties:
hops:
type: integer
format: int32
bpn:
type: string
result:
type: string
SemanticId:
Expand Down Expand Up @@ -2566,10 +2571,10 @@ components:
items:
$ref: '#/components/schemas/Endpoint'
maxItems: 2147483647
idShort:
type: string
id:
type: string
idShort:
type: string
semanticId:
$ref: '#/components/schemas/Reference'
Summary:
Expand Down
20 changes: 10 additions & 10 deletions docs/src/docs/arc42/runtime-view/ess-top-down/ess-top-down.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -94,45 +94,45 @@ In case at least one "YES" is received, the process step 3 ends

== Application Functionality Overview

== Register an Ess-Investigation-Order
=== Register an Ess-Investigation-Order

[plantuml,target=submodel-processing,format=svg]
....
include::../../../../uml-diagrams/runtime-view/use-case-ess-top-down/1_ess-top-down-sequence-highlevel.puml[]
....

== 1. Client Request
==== 1. Client Request

The _Client App (Script)_ initiates a request to the IRS (Item Relationship Service) by sending a GET request for shell lookup based on a specific BPN (Business Partner Number).

== 2. Shell Lookup
==== 2. Shell Lookup

IRS, along with other services like DiscoveryFinder, EDCDiscoveryService, and Digital Twin Registry, collaborates to look up shells for the given BPN, returning an array of AAS identifiers.

== 3. AAS Descriptor Retrieval
==== 3. AAS Descriptor Retrieval

For each AAS identifier, the client requests the IRS for the corresponding shell descriptors, adding them to a collection.

== 4. Filtering AAS
==== 4. Filtering AAS

The _Client App (Script)_ filters the AAS collection for SubmodelDescriptors marked _asPlanned_, based on certain criteria.

== 5. Incident Registration
==== 5. Incident Registration

The client then initiates an IRS incident registration by sending a POST request with specific parameters, including bomLifecycle and callback URL.

== 6. Incident Handling Loop
==== 6. Incident Handling Loop

IRS proceeds to handle the incident by iterating through AAS identifiers, extracting child CXIds, and performing checks on associated data.

== 7. Data Validation
==== 7. Data Validation

The system checks the validity period of the received data and, if valid, proceeds to extract additional information.

== 8. Incident Response
==== 8. Incident Response

If certain conditions are met (e.g., incidentBpns contain catenaXsiteId), the system responds to the client indicating a part-chain infection.

== 9. Notification Handling
==== 9. Notification Handling

Otherwise, the system sends an ess-request notification to the next tier level IRS, and after processing the request on the next tier level, receives an ess-response notification.
1 change: 0 additions & 1 deletion docs/src/docs/arc42/runtime-view/full.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ include::irs-iterative/scenario-4.adoc[leveloffset=+1]
This section covers the main processes of the IRS in a recursive scenario in a network.
This recursive scenario is illustrated using the various use cases realized in the scenario.

=== Use Case: ESS (Environmental and Social Standards) Top-Down approach

include::ess-top-down/ess-top-down.adoc[leveloffset=+1]
include::ess-top-down/ess-top-down-scenario-1.adoc[leveloffset=+1]
Expand Down
4 changes: 2 additions & 2 deletions docs/src/docs/security/security-assessment.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ System_Ext(EDC, "EDC")
System_Ext(EDC-DS, "EDC Discovery Service")
System_Ext(DF, "Discovery Finder")
System_Ext(DTR, "Digital Twin Registry")
System_Ext(KC, "Keycloak")
System_Ext(OAuth2, "OAuth2")
System_Ext(BPDM, "BPDM")
System_Ext(SH, "Semantic Hub")
Expand Down Expand Up @@ -46,7 +46,7 @@ Rel(IRS-App, EDC, "https, access token")
Rel(IRS-App, EDC-DS, "Find decentral DTs, https, access token")
Rel(IRS-App, DF, "Get EDC Discovery Service URL, https, access token")
Rel(IRS-App, DTR, "https, access token")
Rel(IRS-App, KC, "https, clientID, clientSecret, Get tokens to access DTR")
Rel(IRS-App, OAuth2, "https, clientID, clientSecret, Get tokens to access DTR")
Rel(IRS-App, BPDM, "https, access token, Get BPN")
Rel(IRS-App, SH, "Get schemas to validate response from EDC, https, access token")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,57 +27,44 @@
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.tractusx.irs.component.Job;
import org.eclipse.tractusx.irs.component.Jobs;
import org.eclipse.tractusx.irs.component.Notification;
import org.eclipse.tractusx.irs.component.Submodel;
import org.eclipse.tractusx.irs.component.Summary;
import org.eclipse.tractusx.irs.component.enums.JobState;
import org.eclipse.tractusx.irs.edc.client.model.notification.EdcNotification;
import org.eclipse.tractusx.irs.edc.client.model.notification.ResponseNotificationContent;
import org.eclipse.tractusx.irs.util.JsonUtil;

/**
* Object to store in cache
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class BpnInvestigationJob {

private static final String SUPPLY_CHAIN_ASPECT_TYPE = "supply_chain_impacted";

private Jobs jobSnapshot;
private List<String> incidentBpns;
private List<String> unansweredNotifications;
private List<String> answeredNotifications;
private List<Notification> unansweredNotifications;
private List<EdcNotification<ResponseNotificationContent>> answeredNotifications;
private JobState state;

public BpnInvestigationJob(final Jobs jobSnapshot, final List<String> incidentBpns) {
this(jobSnapshot, incidentBpns, new ArrayList<>(), new ArrayList<>(), JobState.RUNNING);
}

private static Jobs extendJobWithSupplyChainSubmodel(final Jobs irsJob,
final SupplyChainImpacted supplyChainImpacted) {
final Submodel supplyChainImpactedSubmodel = Submodel.builder()
.aspectType(SUPPLY_CHAIN_ASPECT_TYPE)
.payload(Map.of("supplyChainImpacted",
supplyChainImpacted.getDescription()))
.build();

return irsJob.toBuilder()
.clearSubmodels()
.submodels(Collections.singletonList(supplyChainImpactedSubmodel))
.build();
}

private static Jobs updateLastModified(final Jobs irsJob, final ZonedDateTime lastModifiedOn) {
final Job job = irsJob.getJob().toBuilder().completedOn(lastModifiedOn).lastModifiedOn(lastModifiedOn).build();
return irsJob.toBuilder().job(job).build();
}

public BpnInvestigationJob update(final Jobs jobSnapshot, final SupplyChainImpacted newSupplyChain) {
final Optional<SupplyChainImpacted> previousSupplyChain = getSupplyChainImpacted();

Expand All @@ -90,6 +77,42 @@ public BpnInvestigationJob update(final Jobs jobSnapshot, final SupplyChainImpac
return this;
}

public BpnInvestigationJob withUnansweredNotifications(final List<Notification> notifications) {
this.unansweredNotifications.addAll(notifications);
return this;
}

public BpnInvestigationJob withAnsweredNotification(
final EdcNotification<ResponseNotificationContent> notification) {
final Optional<String> bpn = getChildBpn(notification);
removeFromUnansweredNotification(notification);
notification.getContent().setBpn(bpn.orElse(null));
notification.getContent().incrementHops();
this.answeredNotifications.add(notification);

return this;
}

private Optional<String> getChildBpn(final EdcNotification<ResponseNotificationContent> notification) {
return this.unansweredNotifications.stream()
.filter(unansweredNotification -> unansweredNotification.notificationId()
.equals(notification.getHeader()
.getOriginalNotificationId()))
.map(Notification::childBpn)
.findAny();
}

private void removeFromUnansweredNotification(final EdcNotification<ResponseNotificationContent> notification) {
this.unansweredNotifications.removeIf(unansweredNotification -> unansweredNotification.notificationId()
.equals(notification.getHeader()
.getOriginalNotificationId()));
}

public BpnInvestigationJob complete() {
this.state = JobState.COMPLETED;
return this;
}

/* package */ Optional<SupplyChainImpacted> getSupplyChainImpacted() {
return this.getJobSnapshot()
.getSubmodels()
Expand All @@ -101,6 +124,46 @@ public BpnInvestigationJob update(final Jobs jobSnapshot, final SupplyChainImpac
.findFirst();
}

private Jobs extendJobWithSupplyChainSubmodel(final Jobs irsJob, final SupplyChainImpacted supplyChainImpacted) {
final SupplyChainImpactedAspect.SupplyChainImpactedAspectBuilder supplyChainImpactedAspectBuilder = SupplyChainImpactedAspect.builder()
.supplyChainImpacted(
supplyChainImpacted);

if (getUnansweredNotifications().isEmpty()) {
final Optional<SupplyChainImpactedAspect.ImpactedSupplierFirstLevel> impactedSupplierWithLowestHopsNumber = getImpactedSupplierWithLowestHopsNumber();
supplyChainImpactedAspectBuilder.impactedSuppliersOnFirstTier(
impactedSupplierWithLowestHopsNumber.orElse(null));
}

return irsJob.toBuilder()
.clearSubmodels()
.submodels(Collections.singletonList(
createSupplyChainImpactedSubmodel(supplyChainImpactedAspectBuilder)))
.build();
}

private Optional<SupplyChainImpactedAspect.ImpactedSupplierFirstLevel> getImpactedSupplierWithLowestHopsNumber() {
return getAnsweredNotifications().stream()
.map(EdcNotification::getContent)
.filter(ResponseNotificationContent::thereIsIncident)
.min(Comparator.comparing(ResponseNotificationContent::getHops))
.map(impacted -> new SupplyChainImpactedAspect.ImpactedSupplierFirstLevel(
impacted.getBpn(), impacted.getHops()));
}

private static Submodel createSupplyChainImpactedSubmodel(
final SupplyChainImpactedAspect.SupplyChainImpactedAspectBuilder supplyChainImpactedAspectBuilder) {
return Submodel.builder()
.aspectType(SUPPLY_CHAIN_ASPECT_TYPE)
.payload(new JsonUtil().asMap(supplyChainImpactedAspectBuilder.build()))
.build();
}

private Jobs updateLastModified(final Jobs irsJob, final ZonedDateTime lastModifiedOn) {
final Job job = irsJob.getJob().toBuilder().completedOn(lastModifiedOn).lastModifiedOn(lastModifiedOn).build();
return irsJob.toBuilder().job(job).build();
}

private Jobs extendSummary(final Jobs irsJob) {
final Summary oldSummary = Optional.ofNullable(irsJob.getJob().getSummary()).orElse(Summary.builder().build());
final NotificationSummary newSummary = new NotificationSummary(oldSummary.getAsyncFetchedItems(),
Expand All @@ -111,19 +174,4 @@ private Jobs extendSummary(final Jobs irsJob) {
return irsJob.toBuilder().job(job).build();
}

public BpnInvestigationJob withNotifications(final List<String> notifications) {
this.unansweredNotifications.addAll(notifications);
return this;
}

public BpnInvestigationJob withAnsweredNotification(final String notificationId) {
this.unansweredNotifications.remove(notificationId);
this.answeredNotifications.add(notificationId);
return this;
}

public BpnInvestigationJob complete() {
this.state = JobState.COMPLETED;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public EdcNotificationSender(final EdcSubmodelFacade edcSubmodelFacade,
}

public void sendEdcNotification(final EdcNotification<InvestigationNotificationContent> originalEdcNotification,
final SupplyChainImpacted supplyChainImpacted) {
final SupplyChainImpacted supplyChainImpacted, final Integer hops, final String bpn) {
final String notificationId = UUID.randomUUID().toString();
final String originalNotificationId = originalEdcNotification.getHeader().getNotificationId();
final String recipientBpn = originalEdcNotification.getHeader().getSenderBpn();
Expand All @@ -69,6 +69,8 @@ public void sendEdcNotification(final EdcNotification<InvestigationNotificationC
log.info("Edc Notification will be send to connector endpoint: {}", connectorEndpoint);
final NotificationContent notificationContent = ResponseNotificationContent.builder()
.result(supplyChainImpacted.getDescription())
.hops(hops)
.bpn(bpn)
.build();
final EdcNotification<NotificationContent> responseNotification = edcRequest(notificationId,
originalNotificationId, essLocalEdcEndpoint, localBpn, recipientBpn, notificationContent);
Expand Down
Loading

0 comments on commit 5bd41ca

Please sign in to comment.