Skip to content

Commit

Permalink
Merge pull request #176 from catenax-ng/main
Browse files Browse the repository at this point in the history
Release 3.5.0 of IRS
  • Loading branch information
ds-jhartmann authored Sep 28, 2023
2 parents 54f608a + 83b5ba8 commit bbcf9a7
Show file tree
Hide file tree
Showing 82 changed files with 3,230 additions and 1,194 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/integration-test-DIL.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ jobs:
uses: ./.github/workflows/xray-cucumber-integration.yaml
secrets:
keycloakTokenUrl: ${{ secrets.KEYCLOAK_OAUTH2_CLIENT_TOKEN_URI }}
clientId: ${{ secrets.ORG_IRS_OAUTH2_CLIENT_ID_DIL }}
clientSecret: ${{ secrets.ORG_IRS_OAUTH2_CLIENT_SECRET_DIL }}
clientId: ${{ secrets.IRS_OAUTH2_CLIENT_ID_DIL }}
clientSecret: ${{ secrets.IRS_OAUTH2_CLIENT_SECRET_DIL }}
jiraUser: ${{ secrets.ORG_IRS_JIRA_USERNAME }}
jiraPassword: ${{ secrets.ORG_IRS_JIRA_PASSWORD }}
with:
Expand Down
17 changes: 15 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [3.5.0] - 2023-09-27
### Changed
- IRS now makes use of the value `dspEndpoint` in `subprotocolBody` of the Asset Administration Shell to request submodel data directly.

### Fixed
- Fixed a case where IRS submodel requests did not reuqest all EDC endpoints discovered by Discovery Finder
- ESS
- Updated investigation request body field `incidentBPNs` to `incidentBPNSs`.
- Streamlined EDC notification flow and adjusted it to existing EDC client methods
- Changed investigation from BPNL to BPNS (`catenaXSiteId` of `PartSiteInformationAsPlanned`)
- Additional validation for `validityPeriod` of `PartAsPlanned`

## [3.4.1] - 2023-09-22
### Changed
- Updated SingleLevelUsageAsBuilt schema to 2.0.0 version.
Expand All @@ -21,7 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed
- Adjusted API access control. Users with role `view_irs` can only access jobs they created themselves. PolicyStore API access is restricted to role `admin_irs`.
-

### Fixed
- Fixed bug where BPN's were delivered without 'manufacturerName' property filled

Expand Down Expand Up @@ -334,7 +346,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Unresolved
- **Select Aspects you need** You are able to select the needed aspects for which you want to collect the correct endpoint information.

[Unreleased]: https://github.com/eclipse-tractusx/item-relationship-service/compare/3.4.1...HEAD
[Unreleased]: https://github.com/eclipse-tractusx/item-relationship-service/compare/3.5.0...HEAD
[3.5.0]: https://github.com/eclipse-tractusx/item-relationship-service/compare/3.4.1...3.5.0
[3.4.1]: https://github.com/eclipse-tractusx/item-relationship-service/compare/3.4.0...3.4.1
[3.4.0]: https://github.com/eclipse-tractusx/item-relationship-service/compare/3.3.5...3.4.0
[3.3.5]: https://github.com/eclipse-tractusx/item-relationship-service/compare/3.3.4...3.3.5
Expand Down
222 changes: 221 additions & 1 deletion DEPENDENCIES

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion charts/irs-helm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [6.7.0] - 2023-09-28
### Changed
- Update IRS version to 3.5.0

### Removed
- Removed unused configuration parameters `edc.submodel.path`,`discovery.endpoint`, `discovery.mockEdcAddres`

## [6.6.1] - 2023-09-22
### Changed
- Update IRS version to 3.4.1
-

## [6.6.0] - 2023-09-01
### Changed
- Update IRS version to 3.4.0
Expand Down
4 changes: 2 additions & 2 deletions charts/irs-helm/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ 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: 6.6.1
version: 6.7.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: "3.4.1"
appVersion: "3.5.0"
dependencies:
- name: common
repository: https://charts.bitnami.com/bitnami
Expand Down
6 changes: 0 additions & 6 deletions charts/irs-helm/templates/configmap-spring-app-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ data:

Check warning on line 105 in charts/irs-helm/templates/configmap-spring-app-config.yaml

View workflow job for this annotation

GitHub Actions / Analyze

[HIGH] Passwords And Secrets - Generic Secret

Query to find passwords and secrets in infrastructure code.

Check warning on line 105 in charts/irs-helm/templates/configmap-spring-app-config.yaml

View workflow job for this annotation

GitHub Actions / Analyze

[HIGH] Passwords And Secrets - Generic Secret

Query to find passwords and secrets in infrastructure code.
submodel:
request-ttl: {{ tpl .Values.edc.submodel.request.ttl . | default "PT10M" | quote }}
path: {{ tpl (.Values.edc.submodel.path | default "/submodel") . | quote }}
urn-prefix: {{ tpl (.Values.edc.submodel.urnprefix | default "/urn") . | quote }}
catalog:
Expand All @@ -125,12 +124,7 @@ data:
irs:
url: {{ tpl (.Values.irsUrl | default "") . | quote }}
discovery:
endpoint: {{ tpl (.Values.discovery.endpoint | default "") . | quote }}
oAuthClientId: {{ .Values.discovery.oAuthClientId | default "portal" }}
{{- if .Values.discovery.mockEdcAddress }}
mockEdcAddress:
{{- tpl (toYaml .Values.discovery.mockEdcAddress) . | nindent 10 }}
{{- end }}
{{- if .Values.ess.mockEdcResult }}
mockEdcResult:
{{- tpl (toYaml .Values.ess.mockEdcResult) . | nindent 10 }}
Expand Down
2 changes: 1 addition & 1 deletion charts/irs-helm/templates/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ spec:
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
number: {{ .port | default $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
Expand Down
3 changes: 0 additions & 3 deletions charts/irs-helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ edc:
submodel:
request:
ttl: PT10M # Requests to dataplane will time out after this duration (see https://en.wikipedia.org/wiki/ISO_8601#Durations)
path: /submodel
urnprefix: /urn
catalog:
policies:
Expand All @@ -187,8 +186,6 @@ edc:
acceptedLeftOperands: PURPOSE # List of comma separated names of the leftOperands to accept.

discovery:
endpoint: # EDC Discovery Service endpoint
mockEdcAddress: # Map of BPNs and EDC Provider URLs - this overrides any real Discovery Service for the given BPN
oAuthClientId: portal # ID of the OAuth2 client registration to use, see config spring.security.oauth2.client

ess:
Expand Down
21 changes: 14 additions & 7 deletions docs/src/api/irs-v1.0.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/EdcNotification'
$ref: '#/components/schemas/EdcNotificationResponseNotificationContent'
required: true
responses:
"200":

Check notice on line 145 in docs/src/api/irs-v1.0.yaml

View workflow job for this annotation

GitHub Actions / Lint (push)

http-response-content-2xx

200, 201, 202, 203 and 206 responses usually have a content: "[200].content" property must be truthy.

Check notice on line 145 in docs/src/api/irs-v1.0.yaml

View workflow job for this annotation

GitHub Actions / Lint (push)

http-response-content-2xx

200, 201, 202, 203 and 206 responses usually have a content: "[200].content" property must exist.
Expand Down Expand Up @@ -1669,14 +1669,12 @@ components:
- permissions
- policyId
- validUntil
EdcNotification:
EdcNotificationResponseNotificationContent:
type: object
additionalProperties: false
properties:
content:
type: object
additionalProperties:
type: object
$ref: '#/components/schemas/ResponseNotificationContent'
header:
$ref: '#/components/schemas/EdcNotificationHeader'
required:
Expand Down Expand Up @@ -2266,6 +2264,7 @@ components:
description: The requested job definition.
properties:
bomLifecycle:
example: asPlanned
type: string
description: The lifecycle context in which the child part was assembled
into the parent part.
Expand All @@ -2281,13 +2280,13 @@ components:
example: "https://hostname.com/callback?jobId={jobId}&jobState={jobState}"
key:
$ref: '#/components/schemas/PartChainIdentificationKey'
incidentBpns:
incidentBPNSs:

Check failure on line 2283 in docs/src/api/irs-v1.0.yaml

View workflow job for this annotation

GitHub Actions / Lint (push)

must-use-common-field-names-and-semantics-for-custom-field-names

Object{} must match the pattern "^[a-z]+([A-Z][a-z0-9]+)*$"

Check failure on line 2283 in docs/src/api/irs-v1.0.yaml

View workflow job for this annotation

GitHub Actions / Lint (push)

must-use-pascal-or-camel-case-for-property-names

Property name has to be ASCII PascalCase or camelCase
type: array
items:
type: string
maxItems: 2147483647
required:
- incidentBpns
- incidentBPNSs
- key
RegisterJob:
type: object
Expand Down Expand Up @@ -2345,6 +2344,8 @@ components:
properties:
aspectType:
type: string
bpn:
type: string
catenaXId:

Check failure on line 2349 in docs/src/api/irs-v1.0.yaml

View workflow job for this annotation

GitHub Actions / Lint (push)

must-use-pascal-or-camel-case-for-property-names

Property name has to be ASCII PascalCase or camelCase

Check failure on line 2349 in docs/src/api/irs-v1.0.yaml

View workflow job for this annotation

GitHub Actions / Lint (push)

must-use-common-field-names-and-semantics-for-custom-field-names

Object{} must match the pattern "^[a-z]+([A-Z][a-z0-9]+)*$"
type: string
description: CATENA-X global asset id in the format urn:uuid:uuid4.
Expand All @@ -2354,6 +2355,12 @@ components:
pattern: "^urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
linkedItem:
$ref: '#/components/schemas/LinkedItem'
ResponseNotificationContent:
type: object
additionalProperties: false
properties:
result:
type: string
SemanticId:
type: object
additionalProperties: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
basePackages = {
"org.eclipse.tractusx.irs",
"org.eclipse.tractusx.ess",
"org.eclipse.tractusx.edc",
"org.eclipse.tractusx.irs.edc",
"org.eclipse.tractusx.irs.common.auth",
},
excludeFilters = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package org.eclipse.tractusx.irs.aaswrapper.job;

import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -35,20 +36,28 @@
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExtractDataFromProtocolInformation {
public static final String DSP_ENDPOINT = "dspEndpoint";
public static final String DSP_ID = "id";
private static final String ASSET_ID_SEPARATOR = ";";

public static String extractAssetId(final String subprotocolBody) {
final Map<String, String> parametersFromPath = Stream.of(subprotocolBody.split(ASSET_ID_SEPARATOR))
.map(str -> str.split("="))
.collect(Collectors.toMap(e -> e[0], e -> e[1]));
return parametersFromPath.get("id");
return parametersFromPath.get(DSP_ID);
}

public static String extractDspEndpoint(final String subprotocolBody) {
final Map<String, String> parametersFromPath = Stream.of(subprotocolBody.split(ASSET_ID_SEPARATOR))
.map(str -> str.split("="))
.collect(Collectors.toMap(e -> e[0], e -> e[1]));
return parametersFromPath.get("dspEndpoint");
public static Optional<String> extractDspEndpoint(final String subprotocolBody) {
if (subprotocolBody.contains(DSP_ENDPOINT)) {
final Map<String, String> parametersFromPath = Stream.of(subprotocolBody.split(ASSET_ID_SEPARATOR))
.map(str -> str.split("="))
.filter(strings -> strings.length == 2)
.collect(Collectors.toMap(e -> e[0], e -> e[1]));

return Optional.ofNullable(parametersFromPath.get(DSP_ENDPOINT));
} else {
return Optional.empty();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
********************************************************************************/
package org.eclipse.tractusx.irs.aaswrapper.job.delegate;

import static org.eclipse.tractusx.irs.aaswrapper.job.ExtractDataFromProtocolInformation.DSP_ENDPOINT;
import static org.eclipse.tractusx.irs.aaswrapper.job.ExtractDataFromProtocolInformation.extractAssetId;
import static org.eclipse.tractusx.irs.aaswrapper.job.ExtractDataFromProtocolInformation.extractDspEndpoint;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import io.github.resilience4j.retry.RetryRegistry;
import lombok.RequiredArgsConstructor;
Expand All @@ -37,7 +39,6 @@
import org.eclipse.tractusx.irs.component.PartChainIdentificationKey;
import org.eclipse.tractusx.irs.component.assetadministrationshell.Endpoint;
import org.eclipse.tractusx.irs.edc.client.EdcSubmodelFacade;
import org.eclipse.tractusx.irs.edc.client.ItemNotFoundInCatalogException;
import org.eclipse.tractusx.irs.edc.client.exceptions.EdcClientException;
import org.eclipse.tractusx.irs.registryclient.discovery.ConnectorEndpointsService;

Expand Down Expand Up @@ -87,27 +88,33 @@ protected ItemContainer next(final ItemContainer.ItemContainerBuilder itemContai
protected String requestSubmodelAsString(final EdcSubmodelFacade submodelFacade,
final ConnectorEndpointsService connectorEndpointsService, final Endpoint endpoint, final String bpn)
throws EdcClientException {
final List<String> connectorEndpoints = connectorEndpointsService.fetchConnectorEndpoints(bpn);
final ArrayList<String> submodelPayload = new ArrayList<>();
for (final String connectorEndpoint : connectorEndpoints) {
addSubmodelToList(submodelFacade, endpoint, submodelPayload, connectorEndpoint);
final String subprotocolBody = endpoint.getProtocolInformation().getSubprotocolBody();
final Optional<String> dspEndpoint = extractDspEndpoint(subprotocolBody);
if (dspEndpoint.isPresent()) {
log.debug("Using dspEndpoint of subprotocolBody '{}' to get submodel payload", subprotocolBody);
return submodelFacade.getSubmodelRawPayload(dspEndpoint.get(), endpoint.getProtocolInformation().getHref(),
extractAssetId(subprotocolBody));
} else {
log.info("SubprotocolBody does not contain '{}'. Using Discovery Service as fallback.", DSP_ENDPOINT);
final List<String> connectorEndpoints = connectorEndpointsService.fetchConnectorEndpoints(bpn);
return getSubmodel(submodelFacade, endpoint, connectorEndpoints);
}
return submodelPayload.stream()
.findFirst()
.orElseThrow(() -> new EdcClientException(String.format(
"Called %s connectorEndpoints but did not get any submodels. Connectors: '%s'",
connectorEndpoints.size(), String.join(", ", connectorEndpoints))));
}

private void addSubmodelToList(final EdcSubmodelFacade submodelFacade, final Endpoint endpoint,
final List<String> submodelPayload, final String connectorEndpoint) throws EdcClientException {
try {
submodelPayload.add(
submodelFacade.getSubmodelRawPayload(connectorEndpoint, endpoint.getProtocolInformation().getHref(),
extractAssetId(endpoint.getProtocolInformation().getSubprotocolBody())));
} catch (ItemNotFoundInCatalogException e) {
log.info("Could not find asset in catalog. Requesting next endpoint.", e);
private String getSubmodel(final EdcSubmodelFacade submodelFacade, final Endpoint endpoint,
final List<String> connectorEndpoints) throws EdcClientException {
for (final String connectorEndpoint : connectorEndpoints) {
try {
return submodelFacade.getSubmodelRawPayload(connectorEndpoint,
endpoint.getProtocolInformation().getHref(),
extractAssetId(endpoint.getProtocolInformation().getSubprotocolBody()));
} catch (EdcClientException e) {
log.info("EdcClientException while accessing endpoint '{}'", connectorEndpoint, e);
}
}
throw new EdcClientException(
String.format("Called %s connectorEndpoints but did not get any submodels. Connectors: '%s'",
connectorEndpoints.size(), String.join(", ", connectorEndpoints)));
}

}
3 changes: 0 additions & 3 deletions irs-api/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ irs-edc-client:

submodel:
request-ttl: ${EDC_SUBMODEL_REQUEST_TTL:PT10M} # How long to wait for an async EDC submodel retrieval to finish, ISO 8601 Duration
path: ${EDC_SUBMODEL_PATH:/submodel} # The path to append to the submodel data reference endpoint
urn-prefix: ${EDC_SUBMODEL_URN_PREFIX:/urn} # A prefix used to identify URNs correctly in the submodel endpoint address
timeout:
read: PT90S # HTTP read timeout for the submodel client
Expand Down Expand Up @@ -215,12 +214,10 @@ ess:
irs:
url: "${IRS_URL:}" # IRS Url to connect with
discovery:
endpoint: "${DISCOVERY_URL:}" # Endpoint to retrieve EDC base url address for BPN
oAuthClientId: portal # ID of the OAuth2 client registration to use, see config spring.security.oauth2.client
timeout:
read: PT90S # HTTP read timeout for the discovery client
connect: PT90S # HTTP connect timeout for the discovery client
mockEdcAddress: { } # Mocked EDC BPN Addresses
mockEdcResult: { } # Mocked BPN Investigation results
mockRecursiveEdcAsset: # Mocked BPN Recursive Investigation results

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class ExtractDataFromProtocolInformationTest {

Expand All @@ -24,10 +28,25 @@ void shouldExtractDspEndpointFromSubprotocol() {
final String exampleSubprotocol = "other_id=fake-id;id=12345;dspEndpoint=http://edc.control.plane/";

// when
final String actual = ExtractDataFromProtocolInformation.extractDspEndpoint(exampleSubprotocol);
final Optional<String> actual = ExtractDataFromProtocolInformation.extractDspEndpoint(exampleSubprotocol);

// then
assertThat(actual).isPresent().contains("http://edc.control.plane/");
}

@ParameterizedTest()
@ValueSource(strings = { "other_id=fake-id;id=12345;dspEndpoint=",
"other_id=fake-id;id=12345;dspEndpoint",
"other_id=fake-id;id=12345;",
"other_id=fake-id;id=12345"
})
void shouldReturnEmptyIfDspEndpointMissing(final String subprotocolBody) {

// when
final Optional<String> actual = ExtractDataFromProtocolInformation.extractDspEndpoint(subprotocolBody);

// then
assertThat(actual).isEqualTo("http://edc.control.plane/");
assertThat(actual).isEmpty();
}

}
Loading

0 comments on commit bbcf9a7

Please sign in to comment.