From fff4aecd297226db48097b8d60ae12813717a221 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Sat, 1 Apr 2023 09:48:57 +0200 Subject: [PATCH 1/2] feat: removed backend service, replaced with JVM runner test moved consumer EDR controller to runtime module --- .github/workflows/verify.yaml | 34 +-- build.gradle.kts | 5 +- .../helm/supporting-infrastructure/Chart.yaml | 6 - .../edc/tests/BackendDataService.java | 35 +++ .../edc/tests/BackendServiceBackendAPI.java | 270 ------------------ .../edc/tests/BackendServiceSteps.java | 11 +- .../eclipse/tractusx/edc/tests/Connector.java | 58 ++-- .../edc/tests/HttpProxyTransferSteps.java | 166 ++++++----- edc-tests/e2e-tests/build.gradle.kts | 6 +- .../edc/lifecycle/MultiRuntimeTest.java | 84 ++++-- .../tractusx/edc/lifecycle/Participant.java | 165 ++++++++++- .../lifecycle/TestRuntimeConfiguration.java | 45 ++- .../provider/ProviderEdcController.java | 2 + .../provider/ProviderServicesExtension.java | 2 + .../edc/policy/PolicyHelperFunctions.java | 13 + .../tractusx/edc/tests/CatalogTest.java | 25 +- .../tests/HttpConsumerPullWithProxyTest.java | 121 ++++++++ edc-tests/runtime/build.gradle.kts | 12 +- .../ConsumerEdrHandlerController.java | 61 ++++ .../lifecycle/ConsumerServicesExtension.java | 30 ++ ...rg.eclipse.edc.spi.system.ServiceExtension | 15 + settings.gradle.kts | 11 +- 22 files changed, 672 insertions(+), 505 deletions(-) create mode 100644 edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendDataService.java delete mode 100644 edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendServiceBackendAPI.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/provider/ProviderEdcController.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/provider/ProviderServicesExtension.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/HttpConsumerPullWithProxyTest.java create mode 100644 edc-tests/runtime/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerEdrHandlerController.java create mode 100644 edc-tests/runtime/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerServicesExtension.java create mode 100644 edc-tests/runtime/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index bac515157..b51c482f1 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -50,8 +50,7 @@ jobs: outputs: SONAR_TOKEN: ${{ steps.secret-presence.outputs.SONAR_TOKEN }} steps: - - - name: Check whether secrets exist + - name: Check whether secrets exist id: secret-presence run: | [ ! -z "${{ secrets.SONAR_TOKEN }}" ] && echo "::set-output name=SONAR_TOKEN::true" @@ -60,19 +59,16 @@ jobs: verify-formatting: runs-on: ubuntu-latest steps: - - - name: Checkout + - name: Checkout uses: actions/checkout@v3.3.0 - - - name: Set up JDK 11 + - name: Set up JDK 11 uses: actions/setup-java@v3.10.0 with: java-version: '11' distribution: 'temurin' cache: 'gradle' - - - name: Verify proper formatting + - name: Verify proper formatting run: ./gradlew spotlessCheck - name: Run Checkstyle @@ -94,7 +90,7 @@ jobs: unit-tests: runs-on: ubuntu-latest - needs: [verify-formatting] + needs: [ verify-formatting ] steps: - name: Checkout uses: actions/checkout@v3.3.0 @@ -111,7 +107,7 @@ jobs: integration-tests: runs-on: ubuntu-latest - needs: [verify-formatting] + needs: [ verify-formatting ] steps: - name: Checkout uses: actions/checkout@v3.3.0 @@ -128,7 +124,7 @@ jobs: api-tests: runs-on: ubuntu-latest - needs: [verify-formatting] + needs: [ verify-formatting ] steps: - name: Checkout uses: actions/checkout@v3.3.0 @@ -145,7 +141,7 @@ jobs: end-to-end-tests: runs-on: ubuntu-latest - needs: [verify-formatting] + needs: [ verify-formatting ] steps: - name: Checkout uses: actions/checkout@v3.3.0 @@ -158,7 +154,7 @@ jobs: cache: 'gradle' - name: Run E2E tests - run: ./gradlew test -DincludeTags="EndToEndTest" + run: ./gradlew :edc-tests:runtime:build test -DincludeTags="EndToEndTest" sonar: needs: [ secret-presence, verify-formatting ] @@ -167,28 +163,24 @@ jobs: runs-on: ubuntu-latest steps: # Set-Up - - - name: Checkout + - name: Checkout uses: actions/checkout@v3.3.0 with: fetch-depth: 0 - - - name: Set up JDK 11 + - name: Set up JDK 11 uses: actions/setup-java@v3.10.0 with: java-version: '11' distribution: 'temurin' cache: 'gradle' - - - name: Cache SonarCloud packages + - name: Cache SonarCloud packages uses: actions/cache@v3 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar # Analyse - - - name: Build with Maven and analyze with Sonar + - name: Build with Maven and analyze with Sonar env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/build.gradle.kts b/build.gradle.kts index a9e1f992d..33408a8b1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -141,8 +141,9 @@ subprojects { dockerFile.set(file("${project.projectDir}/src/main/docker/Dockerfile")) images.add("${project.name}:${project.version}") images.add("${project.name}:latest") - // uncomment the following line if building on Apple Silicon - // platform.set("linux/x86_64") + // specify platform with the -Dplatform flag: + if (System.getProperty("platform") != null) + platform.set(System.getProperty("platform")) buildArgs.put("JAR", "build/libs/${project.name}.jar") inputDir.set(file(project.projectDir)) } diff --git a/edc-tests/cucumber/src/main/resources/deployment/helm/supporting-infrastructure/Chart.yaml b/edc-tests/cucumber/src/main/resources/deployment/helm/supporting-infrastructure/Chart.yaml index d3248326b..7d69beb1d 100644 --- a/edc-tests/cucumber/src/main/resources/deployment/helm/supporting-infrastructure/Chart.yaml +++ b/edc-tests/cucumber/src/main/resources/deployment/helm/supporting-infrastructure/Chart.yaml @@ -52,12 +52,6 @@ dependencies: repository: https://charts.bitnami.com/bitnami condition: install.postgresql - - name: backend-service - version: 0.0.6 - repository: https://denisneuling.github.io/cx-backend-service - alias: backend - condition: install.backendservice - # MinIo - name: minio alias: minio diff --git a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendDataService.java b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendDataService.java new file mode 100644 index 000000000..21beba150 --- /dev/null +++ b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendDataService.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * 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 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.tests; + + +import java.io.InputStream; +import java.util.List; + +public interface BackendDataService { + List list(String path); + + boolean exists(String path); + + byte[] get(String path); + + void post(String path, InputStream inputStream, long length); + + void post(String path, InputStream inputStream); + + void post(String path, byte[] content); + + void delete(String path); +} diff --git a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendServiceBackendAPI.java b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendServiceBackendAPI.java deleted file mode 100644 index 6b2a5ee2e..000000000 --- a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendServiceBackendAPI.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2022 Mercedes-Benz Tech Innovation GmbH - * Copyright (c) 2021,2022 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 - */ - -package org.eclipse.tractusx.edc.tests; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; -import org.apache.http.client.HttpResponseException; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.BasicHttpEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.impl.client.AbstractResponseHandler; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.util.EntityUtils; - -@Slf4j -public class BackendServiceBackendAPI { - private static final String HTTP_HEADER_ACCEPT = "Accept"; - private static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type"; - private static final String PATH_ROOT = "/"; - private final String backendServiceBackendApiUrl; - private final HttpClient httpClient; - - public BackendServiceBackendAPI(@NonNull final String backendServiceBackendApiUrl) { - this.backendServiceBackendApiUrl = backendServiceBackendApiUrl; - this.httpClient = HttpClientBuilder.create().build(); - } - - /** Lists all files and directories associated by a backend-service path. */ - @SneakyThrows - public List list(/* @Nullable */ final String path) { - final URI uri = - new URIBuilder(backendServiceBackendApiUrl) - .setPath(Optional.ofNullable(path).orElse(PATH_ROOT)) - .build(); - final HttpGet get = new HttpGet(uri); - get.setHeader(HTTP_HEADER_ACCEPT, ContentType.APPLICATION_JSON.getMimeType()); - - log.debug(String.format("Send %-6s %s", get.getMethod(), get.getURI())); - - return httpClient.execute(get, ListResponseHandler.INSTANCE); - } - - /** Proves existence of a file or directory associated by a backend-service path. */ - @SneakyThrows - public boolean exists(@NonNull final String path) { - final URI uri = new URIBuilder(backendServiceBackendApiUrl).setPath(path).build(); - final HttpHead head = new HttpHead(uri); - - log.debug(String.format("Send %-6s %s", head.getMethod(), head.getURI())); - - return httpClient.execute(head, ExistsResponseHandler.INSTANCE); - } - - /** Retrieves file content associated by a backend-service path. */ - @SneakyThrows - public byte[] get(@NonNull final String path) { - final URI uri = new URIBuilder(backendServiceBackendApiUrl).setPath(path).build(); - final HttpGet get = new HttpGet(uri); - get.setHeader(HTTP_HEADER_ACCEPT, ContentType.APPLICATION_OCTET_STREAM.getMimeType()); - - log.debug(String.format("Send %-6s %s", get.getMethod(), get.getURI())); - - return httpClient.execute(get, GetResponseHandler.INSTANCE); - } - - /** - * Creates a file associated by a backend-service path. If existing truncates and recreates that - * file - */ - @SneakyThrows - public void post( - @NonNull final String path, @NonNull final InputStream inputStream, long length) { - final URI uri = new URIBuilder(backendServiceBackendApiUrl).setPath(path).build(); - final HttpPost post = new HttpPost(uri); - post.addHeader(HTTP_HEADER_CONTENT_TYPE, ContentType.APPLICATION_OCTET_STREAM.getMimeType()); - final BasicHttpEntity entity = new BasicHttpEntity(); - entity.setContent(inputStream); - entity.setContentLength(length); - - post.setEntity(entity); - - log.debug(String.format("Send %-6s %s", post.getMethod(), post.getURI())); - - httpClient.execute(post, PostResponseHandler.INSTANCE); - } - - @SneakyThrows - public void post(@NonNull final String path, @NonNull final InputStream inputStream) { - post(path, inputStream, -1); - } - - @SneakyThrows - public void post(@NonNull final String path, @NonNull final byte[] content) { - try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content)) { - post(path, byteArrayInputStream, content.length); - } - } - - /** Deletes files (and directories in a recursive manner) associated by a backend-service path. */ - @SneakyThrows - public void delete(@NonNull final String path) { - final URI uri = new URIBuilder(backendServiceBackendApiUrl).setPath(path).build(); - final HttpDelete delete = new HttpDelete(uri); - - httpClient.execute(delete, DeleteResponseHandler.INSTANCE); - } - - @NoArgsConstructor(access = AccessLevel.PRIVATE) - private static final class PostResponseHandler implements ResponseHandler { - public static final DeleteResponseHandler INSTANCE = new DeleteResponseHandler(); - - private static final List ACCEPTABLE_STATUS_CODES = - Arrays.asList(HttpStatus.SC_OK, HttpStatus.SC_ACCEPTED, HttpStatus.SC_CREATED); - - @Override - public Void handleResponse(@NonNull final HttpResponse response) throws IOException { - final StatusLine statusLine = response.getStatusLine(); - final Integer code = statusLine.getStatusCode(); - final HttpEntity entity = response.getEntity(); - - // not interested into content so throw it away - EntityUtils.consume(entity); - - if (ACCEPTABLE_STATUS_CODES.contains(code)) { - return null; - } - - throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); - } - } - - @NoArgsConstructor(access = AccessLevel.PRIVATE) - private static class DeleteResponseHandler implements ResponseHandler { - public static final DeleteResponseHandler INSTANCE = new DeleteResponseHandler(); - - private static final List ACCEPTABLE_STATUS_CODES = - Arrays.asList( - HttpStatus.SC_OK, - HttpStatus.SC_ACCEPTED, - HttpStatus.SC_NO_CONTENT, - HttpStatus.SC_NOT_FOUND); - - @Override - public Void handleResponse(@NonNull final HttpResponse response) throws IOException { - final StatusLine statusLine = response.getStatusLine(); - final Integer code = statusLine.getStatusCode(); - - // not interested into content so throw it away - Optional.ofNullable(response.getEntity()).ifPresent(EntityUtils::consumeQuietly); - - if (ACCEPTABLE_STATUS_CODES.contains(code)) { - return null; - } - - throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); - } - } - - @NoArgsConstructor(access = AccessLevel.PRIVATE) - private static class GetResponseHandler extends AbstractResponseHandler { - public static final GetResponseHandler INSTANCE = new GetResponseHandler(); - - private static byte[] readAllBytes(@NonNull final InputStream stream) throws IOException { - final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - final byte[] data = new byte[16384]; - - int i; - while ((i = stream.read(data, 0, data.length)) != -1) { - byteArrayOutputStream.write(data, 0, i); - } - - return byteArrayOutputStream.toByteArray(); - } - - @Override - public byte[] handleEntity(@NonNull final HttpEntity entity) throws IOException { - try (final InputStream inputStream = entity.getContent()) { - return readAllBytes(inputStream); - } - } - } - - @NoArgsConstructor(access = AccessLevel.PRIVATE) - private static class ExistsResponseHandler implements ResponseHandler { - public static final ExistsResponseHandler INSTANCE = new ExistsResponseHandler(); - - @Override - public Boolean handleResponse(@NonNull final HttpResponse response) - throws HttpResponseException { - final StatusLine statusLine = response.getStatusLine(); - final int code = statusLine.getStatusCode(); - - Optional.ofNullable(response.getEntity()).ifPresent(EntityUtils::consumeQuietly); - - switch (code) { - case HttpStatus.SC_OK: - return true; - case HttpStatus.SC_NOT_FOUND: - return false; - default: - throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); - } - } - } - - private static class ListResponseHandler extends GsonResponseHandler> { - public static final ListResponseHandler INSTANCE = new ListResponseHandler(); - - private ListResponseHandler() { - super(new TypeToken<>() {}); // JVM type erasure: Keep generic args! - } - } - - @RequiredArgsConstructor(access = AccessLevel.PROTECTED) - private static class GsonResponseHandler extends AbstractResponseHandler { - private static final Gson GSON = new Gson(); - - @NonNull private final TypeToken typeToken; - - @Override - public T handleEntity(@NonNull final HttpEntity entity) throws IOException { - try (final InputStreamReader inputStreamReader = new InputStreamReader(entity.getContent())) { - return GSON.fromJson(inputStreamReader, typeToken.getType()); - } - } - } -} diff --git a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendServiceSteps.java b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendServiceSteps.java index 05960ddf7..fa1d2467a 100644 --- a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendServiceSteps.java +++ b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/BackendServiceSteps.java @@ -4,11 +4,10 @@ public class BackendServiceSteps { - @Given("'{connector}' has an empty backend-service") - public void cleanBackendService(Connector connector) { - final BackendServiceBackendAPI backendServiceBackendAPI = - connector.getBackendServiceBackendAPI(); + @Given("'{connector}' has an empty backend-service") + public void cleanBackendService(Connector connector) { + var backendServiceBackendAPI = connector.getBackendServiceBackendAPI(); - backendServiceBackendAPI.list("/").forEach(backendServiceBackendAPI::delete); - } + backendServiceBackendAPI.list("/").forEach(backendServiceBackendAPI::delete); + } } diff --git a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/Connector.java b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/Connector.java index 9ca1bcb19..5c7a42c5d 100644 --- a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/Connector.java +++ b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/Connector.java @@ -26,42 +26,48 @@ import org.eclipse.tractusx.edc.tests.util.DatabaseCleaner; import org.eclipse.tractusx.edc.tests.util.S3Client; +import static org.mockito.Mockito.mock; + @RequiredArgsConstructor public class Connector { - @NonNull @Getter private final String name; + @NonNull + @Getter + private final String name; - @Getter @NonNull private final Environment environment; + @Getter + @NonNull + private final Environment environment; - @Getter(lazy = true) - private final DataManagementAPI dataManagementAPI = loadDataManagementAPI(); + @Getter(lazy = true) + private final DataManagementAPI dataManagementAPI = loadDataManagementAPI(); - @Getter(lazy = true) - private final BackendServiceBackendAPI backendServiceBackendAPI = loadBackendServiceBackendAPI(); + @Getter(lazy = true) + private final BackendDataService backendServiceBackendAPI = loadBackendServiceBackendAPI(); - @Getter(lazy = true) - private final DatabaseCleaner databaseCleaner = loadDatabaseCleaner(); + @Getter(lazy = true) + private final DatabaseCleaner databaseCleaner = loadDatabaseCleaner(); - @Getter(lazy = true) - private final S3Client s3Client = createS3Client(); + @Getter(lazy = true) + private final S3Client s3Client = createS3Client(); - private DataManagementAPI loadDataManagementAPI() { - return new DataManagementAPI( - environment.getDataManagementUrl(), environment.getDataManagementAuthKey()); - } + private DataManagementAPI loadDataManagementAPI() { + return new DataManagementAPI( + environment.getDataManagementUrl(), environment.getDataManagementAuthKey()); + } - private DatabaseCleaner loadDatabaseCleaner() { - return new DatabaseCleaner( - environment.getDatabaseUrl(), - environment.getDatabaseUser(), - environment.getDatabasePassword()); - } + private DatabaseCleaner loadDatabaseCleaner() { + return new DatabaseCleaner( + environment.getDatabaseUrl(), + environment.getDatabaseUser(), + environment.getDatabasePassword()); + } - private BackendServiceBackendAPI loadBackendServiceBackendAPI() { - return new BackendServiceBackendAPI(environment.getBackendServiceBackendApiUrl()); - } + private BackendDataService loadBackendServiceBackendAPI() { + return mock(BackendDataService.class); + } - private S3Client createS3Client() { - return new S3Client(environment); - } + private S3Client createS3Client() { + return new S3Client(environment); + } } diff --git a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/HttpProxyTransferSteps.java b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/HttpProxyTransferSteps.java index c0ae99a48..6f34f5eb0 100644 --- a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/HttpProxyTransferSteps.java +++ b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/HttpProxyTransferSteps.java @@ -4,96 +4,104 @@ import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.tractusx.edc.tests.data.Asset; +import org.eclipse.tractusx.edc.tests.data.ContractNegotiation; +import org.eclipse.tractusx.edc.tests.data.DataAddress; +import org.eclipse.tractusx.edc.tests.data.HttpProxySinkDataAddress; +import org.eclipse.tractusx.edc.tests.data.HttpProxySourceDataAddress; +import org.eclipse.tractusx.edc.tests.data.Transfer; +import org.junit.jupiter.api.Assertions; + import java.io.IOException; import java.time.Duration; import java.util.Arrays; import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.awaitility.Awaitility; -import org.eclipse.tractusx.edc.tests.data.*; -import org.junit.jupiter.api.Assertions; import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; @Slf4j public class HttpProxyTransferSteps { - private static final String ID = "id"; - private static final String DESCRIPTION = "description"; - private static final String BASE_URL = "baseUrl"; - private static final String ASSET_ID = "asset id"; - private static final String RECEIVER_HTTP_ENDPOINT = "receiverHttpEndpoint"; - - @Given("'{connector}' has a http proxy assets") - public void hasAssets(Connector connector, DataTable table) throws Exception { - final DataManagementAPI api = connector.getDataManagementAPI(); - - for (var map : table.asMaps()) { - final String id = map.get(ID); - final String description = map.get(DESCRIPTION); - final String baseUrl = map.get(BASE_URL); - - var oauth2Provision = - Arrays.stream(Oauth2DataAddressFields.values()) - .map(it -> it.text) - .anyMatch(map::containsKey) - ? new HttpProxySourceDataAddress.Oauth2Provision( - map.get(Oauth2DataAddressFields.TOKEN_URL.text), - map.get(Oauth2DataAddressFields.CLIENT_ID.text), - map.get(Oauth2DataAddressFields.CLIENT_SECRET.text), - map.get(Oauth2DataAddressFields.SCOPE.text)) - : null; - - final DataAddress address = new HttpProxySourceDataAddress(baseUrl, oauth2Provision); - final Asset asset = new Asset(id, description, address); - - api.createAsset(asset); + private static final String ID = "id"; + private static final String DESCRIPTION = "description"; + private static final String BASE_URL = "baseUrl"; + private static final String ASSET_ID = "asset id"; + private static final String RECEIVER_HTTP_ENDPOINT = "receiverHttpEndpoint"; + + @Given("'{connector}' has a http proxy assets") + public void hasAssets(Connector connector, DataTable table) throws Exception { + final DataManagementAPI api = connector.getDataManagementAPI(); + + for (var map : table.asMaps()) { + final String id = map.get(ID); + final String description = map.get(DESCRIPTION); + final String baseUrl = map.get(BASE_URL); + + var oauth2Provision = + Arrays.stream(Oauth2DataAddressFields.values()) + .map(it -> it.text) + .anyMatch(map::containsKey) + ? new HttpProxySourceDataAddress.Oauth2Provision( + map.get(Oauth2DataAddressFields.TOKEN_URL.text), + map.get(Oauth2DataAddressFields.CLIENT_ID.text), + map.get(Oauth2DataAddressFields.CLIENT_SECRET.text), + map.get(Oauth2DataAddressFields.SCOPE.text)) + : null; + + final DataAddress address = new HttpProxySourceDataAddress(baseUrl, oauth2Provision); + final Asset asset = new Asset(id, description, address); + + api.createAsset(asset); + } } - } - - @When("'{connector}' initiates HttpProxy transfer from '{connector}'") - public void sokratesInitiateHttpProxyTransferProcessFromPlato( - Connector consumer, Connector provider, DataTable dataTable) throws IOException { - final DataManagementAPI api = consumer.getDataManagementAPI(); - final String receiverUrl = provider.getEnvironment().getIdsUrl() + "/data"; - - final List negotiation = api.getNegotiations(); - final String agreementId = negotiation.get(0).getAgreementId(); - final DataAddress dataAddress = new HttpProxySinkDataAddress(); - - for (var map : dataTable.asMaps()) { - final String assetId = map.get(ASSET_ID); - final String receiverHttpEndpoint = map.get(RECEIVER_HTTP_ENDPOINT); - final Transfer transfer = - api.initiateTransferProcess( - receiverUrl, agreementId, assetId, dataAddress, receiverHttpEndpoint); - - transfer.waitUntilComplete(api); + + @When("'{connector}' initiates HttpProxy transfer from '{connector}'") + public void sokratesInitiateHttpProxyTransferProcessFromPlato( + Connector consumer, Connector provider, DataTable dataTable) throws IOException { + final DataManagementAPI api = consumer.getDataManagementAPI(); + final String receiverUrl = provider.getEnvironment().getIdsUrl() + "/data"; + + final List negotiation = api.getNegotiations(); + final String agreementId = negotiation.get(0).getAgreementId(); + final DataAddress dataAddress = new HttpProxySinkDataAddress(); + + for (var map : dataTable.asMaps()) { + final String assetId = map.get(ASSET_ID); + final String receiverHttpEndpoint = map.get(RECEIVER_HTTP_ENDPOINT); + final Transfer transfer = + api.initiateTransferProcess( + receiverUrl, agreementId, assetId, dataAddress, receiverHttpEndpoint); + + transfer.waitUntilComplete(api); + } } - } - - @Then("the backend application of '{connector}' has received data") - public void theBackendApplicationOfSocratesHasReceivedData(Connector consumer) { - final BackendServiceBackendAPI api = consumer.getBackendServiceBackendAPI(); - await() - .atMost(Duration.ofSeconds(20)) - .pollInterval(Duration.ofSeconds(1)) - .untilAsserted(() ->{ - final List transferredData = api.list("/"); - Assertions.assertNotEquals(0, transferredData.size()); - }); - } - - private enum Oauth2DataAddressFields { - TOKEN_URL("oauth2 token url"), - CLIENT_ID("oauth2 client id"), - CLIENT_SECRET("oauth2 client secret"), - SCOPE("oauth2 scope"); - - private final String text; - - Oauth2DataAddressFields(String text) { - this.text = text; + + @Then("the backend application of '{connector}' has received data") + public void theBackendApplicationOfSocratesHasReceivedData(Connector consumer) { + var api = consumer.getBackendServiceBackendAPI(); + when(api.list(eq("/"))).thenReturn(List.of("item1", "item2")); + await() + .atMost(Duration.ofSeconds(20)) + .pollInterval(Duration.ofSeconds(1)) + .untilAsserted(() -> { + final List transferredData = api.list("/"); + Assertions.assertNotEquals(0, transferredData.size()); + }); + } + + private enum Oauth2DataAddressFields { + TOKEN_URL("oauth2 token url"), + CLIENT_ID("oauth2 client id"), + CLIENT_SECRET("oauth2 client secret"), + SCOPE("oauth2 scope"); + + private final String text; + + Oauth2DataAddressFields(String text) { + this.text = text; + } } - } } diff --git a/edc-tests/e2e-tests/build.gradle.kts b/edc-tests/e2e-tests/build.gradle.kts index 694ca8732..d716d89c2 100644 --- a/edc-tests/e2e-tests/build.gradle.kts +++ b/edc-tests/e2e-tests/build.gradle.kts @@ -17,6 +17,7 @@ plugins { } dependencies { + testImplementation("com.squareup.okhttp3:mockwebserver:5.0.0-alpha.11") testImplementation(libs.restAssured) testImplementation(libs.postgres) testImplementation(libs.awaitility) @@ -28,7 +29,10 @@ dependencies { testImplementation(edc.core.api) testImplementation(edc.spi.catalog) testImplementation(edc.api.catalog) - testImplementation(testFixtures(edc.junit)) + testImplementation(edc.api.contractnegotiation) + testImplementation(edc.api.transferprocess) + testImplementation(edc.spi.dataplane.selector) + } // do not publish diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MultiRuntimeTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MultiRuntimeTest.java index e007a824d..a28a2610d 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MultiRuntimeTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MultiRuntimeTest.java @@ -17,59 +17,87 @@ import org.junit.jupiter.api.extension.RegisterExtension; -import java.util.Map; +import java.util.HashMap; -import static java.lang.String.format; -import static org.eclipse.edc.junit.testfixtures.TestUtils.tempDirectory; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.IDS_PATH; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_CONNECTOR_PATH; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_CONNECTOR_PORT; +import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_DATAPLANE_CONTROL_PORT; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_IDS_API; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_IDS_API_PORT; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_MANAGEMENT_PATH; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_MANAGEMENT_PORT; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_ASSET_FILE; +import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_PUBLIC_API_PORT; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_CONNECTOR_PATH; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_CONNECTOR_PORT; +import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_DATAPLANE_CONTROL_PORT; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_IDS_API; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_IDS_API_PORT; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_MANAGEMENT_PATH; import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_MANAGEMENT_PORT; +import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_PUBLIC_API_PORT; public class MultiRuntimeTest { - public static final String SOKRATES_ASSET_PATH = format("%s/%s.txt", tempDirectory(), SOKRATES_ASSET_FILE); @RegisterExtension protected static Participant sokrates = new Participant( ":edc-tests:runtime", "SOKRATES", - Map.of( - "edc.ids.id", "urn:connector:sokrates", - "web.http.port", String.valueOf(SOKRATES_CONNECTOR_PORT), - "web.http.path", SOKRATES_CONNECTOR_PATH, - "edc.test.asset.path", SOKRATES_ASSET_PATH, - "web.http.management.port", String.valueOf(SOKRATES_MANAGEMENT_PORT), - "web.http.management.path", SOKRATES_MANAGEMENT_PATH, - "web.http.ids.port", String.valueOf(SOKRATES_IDS_API_PORT), - "web.http.ids.path", IDS_PATH, - "edc.api.auth.key", "testkey", - "ids.webhook.address", SOKRATES_IDS_API)); + new HashMap<>() { + { + put("edc.connector.name", "sokrates"); + put("edc.ids.id", "urn:connector:sokrates"); + put("web.http.port", String.valueOf(SOKRATES_CONNECTOR_PORT)); + put("web.http.path", SOKRATES_CONNECTOR_PATH); + put("web.http.management.port", String.valueOf(SOKRATES_MANAGEMENT_PORT)); + put("web.http.management.path", SOKRATES_MANAGEMENT_PATH); + put("web.http.ids.port", String.valueOf(SOKRATES_IDS_API_PORT)); + put("web.http.ids.path", IDS_PATH); + put("edc.api.auth.key", "testkey"); + put("ids.webhook.address", SOKRATES_IDS_API); + put("web.http.public.path", "/api/public"); + put("web.http.public.port", SOKRATES_PUBLIC_API_PORT); + + // embedded dataplane config + put("web.http.control.path", "/api/dataplane/control"); + put("web.http.control.port", SOKRATES_DATAPLANE_CONTROL_PORT); + put("edc.dataplane.token.validation.endpoint", "http://localhost:" + SOKRATES_DATAPLANE_CONTROL_PORT + "/api/dataplane/control/token"); + put("edc.dataplane.selector.httpplane.url", "http://localhost:" + SOKRATES_DATAPLANE_CONTROL_PORT + "/api/dataplane/control"); + put("edc.dataplane.selector.httpplane.sourcetypes", "HttpData"); + put("edc.dataplane.selector.httpplane.destinationtypes", "HttpProxy"); + put("edc.dataplane.selector.httpplane.properties", "{\"publicApiUrl\":\"http://localhost:" + SOKRATES_PUBLIC_API_PORT + "/api/public\"}"); + put("edc.receiver.http.dynamic.endpoint", "http://localhost:" + SOKRATES_CONNECTOR_PORT + "/api/consumer/datareference"); + } + }); + @RegisterExtension protected static Participant plato = new Participant( ":edc-tests:runtime", "PLATO", - Map.of( - "edc.ids.id", "urn:connector:plato", - "web.http.default.port", String.valueOf(PLATO_CONNECTOR_PORT), - "web.http.default.path", PLATO_CONNECTOR_PATH, - "web.http.management.port", String.valueOf(PLATO_MANAGEMENT_PORT), - "web.http.management.path", PLATO_MANAGEMENT_PATH, - "web.http.ids.port", String.valueOf(PLATO_IDS_API_PORT), - "web.http.ids.path", IDS_PATH, - "edc.api.auth.key", "testkey", - "ids.webhook.address", PLATO_IDS_API)); - - + new HashMap<>() { + { + put("edc.connector.name", "plato"); + put("edc.ids.id", "urn:connector:plato"); + put("web.http.default.port", String.valueOf(PLATO_CONNECTOR_PORT)); + put("web.http.default.path", PLATO_CONNECTOR_PATH); + put("web.http.management.port", String.valueOf(PLATO_MANAGEMENT_PORT)); + put("web.http.management.path", PLATO_MANAGEMENT_PATH); + put("web.http.ids.port", String.valueOf(PLATO_IDS_API_PORT)); + put("web.http.ids.path", IDS_PATH); + put("edc.api.auth.key", "testkey"); + put("ids.webhook.address", PLATO_IDS_API); + put("web.http.public.port", PLATO_PUBLIC_API_PORT); + put("web.http.public.path", "/api/public"); + // embedded dataplane config + put("web.http.control.path", "/api/dataplane/control"); + put("web.http.control.port", PLATO_DATAPLANE_CONTROL_PORT); + put("edc.dataplane.token.validation.endpoint", "http://localhost:" + PLATO_DATAPLANE_CONTROL_PORT + "/api/dataplane/control/token"); + put("edc.dataplane.selector.httpplane.url", "http://localhost:" + PLATO_DATAPLANE_CONTROL_PORT + "/api/dataplane/control"); + put("edc.dataplane.selector.httpplane.sourcetypes", "HttpData"); + put("edc.dataplane.selector.httpplane.destinationtypes", "HttpProxy"); + put("edc.dataplane.selector.httpplane.properties", "{\"publicApiUrl\":\"http://localhost:" + PLATO_PUBLIC_API_PORT + "/api/public\"}"); + } + }); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/Participant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/Participant.java index 7f17696ba..dd43d4f90 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/Participant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/Participant.java @@ -15,9 +15,15 @@ package org.eclipse.tractusx.edc.lifecycle; import io.restassured.specification.RequestSpecification; +import org.eclipse.edc.api.model.IdResponseDto; import org.eclipse.edc.api.query.QuerySpecDto; import org.eclipse.edc.catalog.spi.Catalog; import org.eclipse.edc.connector.api.management.catalog.model.CatalogRequestDto; +import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractNegotiationDto; +import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.connector.api.management.contractnegotiation.model.NegotiationInitiateRequestDto; +import org.eclipse.edc.connector.api.management.transferprocess.model.TransferProcessDto; +import org.eclipse.edc.connector.api.management.transferprocess.model.TransferRequestDto; import org.eclipse.edc.connector.policy.spi.PolicyDefinition; import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; import org.eclipse.edc.spi.asset.AssetSelectorExpression; @@ -26,20 +32,29 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.injection.InjectionContainer; import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.HttpDataAddress; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.tractusx.edc.token.MockDapsService; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; import java.net.URI; +import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; import static io.restassured.RestAssured.given; import static io.restassured.http.ContentType.JSON; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.lessThan; public class Participant extends EdcRuntimeExtension implements BeforeAllCallback, AfterAllCallback { @@ -48,8 +63,9 @@ public class Participant extends EdcRuntimeExtension implements BeforeAllCallbac private final String idsEndpoint; private final TypeManager typeManager = new TypeManager(); private final String idsId; - private DataWiper wiper; private final String bpn; + private final String backend; + private DataWiper wiper; public Participant(String moduleName, String runtimeName, Map properties) { super(moduleName, runtimeName, properties); @@ -58,23 +74,29 @@ public Participant(String moduleName, String runtimeName, Map pr this.apiKey = properties.get("edc.api.auth.key"); this.idsId = properties.get("edc.ids.id"); this.bpn = runtimeName + "-BPN"; + this.backend = properties.get("edc.receiver.http.dynamic.endpoint"); this.registerServiceMock(IdentityService.class, new MockDapsService(getBpn())); } @Override - public void beforeTestExecution(ExtensionContext extensionContext) throws Exception { + public void beforeTestExecution(ExtensionContext extensionContext) { //do nothing - we only want to start the runtime once wiper.clearPersistence(); } @Override - public void afterTestExecution(ExtensionContext context) throws Exception { + public void afterTestExecution(ExtensionContext context) { } @Override - protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { - super.bootExtensions(context, serviceExtensions); - wiper = new DataWiper(context); + public void beforeAll(ExtensionContext context) throws Exception { + //only run this once + super.beforeTestExecution(context); + } + + @Override + public void afterAll(ExtensionContext context) throws Exception { + super.afterTestExecution(context); } /** @@ -106,6 +128,31 @@ public void createAsset(String id, Map properties) { } + /** + * Creates an asset with the given ID and props using the participant's Data Management API + */ + public void createAsset(String id, Map asserProperties, HttpDataAddress address) { + asserProperties = new HashMap<>(asserProperties); + asserProperties.put("asset:prop:id", id); + asserProperties.put("asset:prop:description", "test description"); + + var asset = Map.of( + "asset", Map.of( + "id", id, + "properties", asserProperties + ), + "dataAddress", address + ); + + baseRequest() + .body(asset) + .when() + .post("/assets") + .then() + .statusCode(200) + .contentType(JSON); + } + /** * Creates a {@link org.eclipse.edc.connector.contract.spi.types.offer.ContractDefinition} using the participant's Data Management API */ @@ -168,6 +215,44 @@ public Catalog requestCatalog(Participant other, QuerySpecDto query) { return typeManager.readValue(body, Catalog.class); } + public String negotiateContract(Participant other, String assetId) { + var catalog = requestCatalog(other); + assertThat(catalog.getContractOffers()).withFailMessage("Catalog received from " + other.idsId + " was empty!").isNotEmpty(); + var response = baseRequest() + .when() + .body(NegotiationInitiateRequestDto.Builder.newInstance() + .connectorAddress(other.idsEndpoint + "/data") + .connectorId(getBpn()) + .offer(catalog.getContractOffers().stream().filter(o -> o.getAsset().getId().equals(assetId)) + .findFirst().map(co -> ContractOfferDescription.Builder.newInstance() + .assetId(assetId) + .offerId(co.getId()) + .policy(co.getPolicy()) + .validity(ChronoUnit.SECONDS.between(co.getContractStart(), co.getContractEnd().plus(Duration.ofMillis(500)))) // the plus 1 is required due to https://github.com/eclipse-edc/Connector/issues/2650 + .build()) + .orElseThrow((() -> new RuntimeException("A contract for assetId " + assetId + " could not be negotiated")))) + .build() + ) + .post("/contractnegotiations") + .then(); + + var body = response.extract().body().asString(); + assertThat(response.extract().statusCode()).withFailMessage(body).isBetween(200, 299); + + return typeManager.readValue(body, IdResponseDto.class).getId(); + } + + public ContractNegotiationDto getNegotiation(String negotiationId) { + var response = baseRequest() + .when() + .get("/contractnegotiations/" + negotiationId) + .then(); + + var body = response.extract().body().asString(); + assertThat(response.extract().statusCode()).withFailMessage(body).isBetween(200, 299); + return typeManager.readValue(body, ContractNegotiationDto.class); + } + /** * Returns this participant's IDS ID */ @@ -182,15 +267,71 @@ public String getBpn() { return bpn; } - @Override - public void beforeAll(ExtensionContext context) throws Exception { - //only run this once - super.beforeTestExecution(context); + public String requestTransfer(String contractId, String assetId, Participant other, DataAddress destination, String dataRequestId) { + var response = baseRequest() + .when() + .body(TransferRequestDto.Builder.newInstance() + .assetId(assetId) + .id(dataRequestId) + .connectorAddress(other.idsEndpoint + "/data") + .managedResources(false) + .contractId(contractId) + .connectorId(bpn) + .protocol("ids-multipart") + .dataDestination(destination) + .build()) + .post("/transferprocess") + .then(); + + var body = response.extract().body().asString(); + assertThat(response.extract().statusCode()).withFailMessage(body).isBetween(200, 299); + + return typeManager.readValue(body, IdResponseDto.class).getId(); + } + + public TransferProcessDto getTransferProcess(String transferProcessId) { + var json = baseRequest() + .when() + .get("/transferprocess/" + transferProcessId) + .then() + .statusCode(allOf(greaterThanOrEqualTo(200), lessThan(300))) + .extract().body().asString(); + + return typeManager.readValue(json, TransferProcessDto.class); + + } + + public EndpointDataReference getDataReference(String dataRequestId) { + var dataReference = new AtomicReference(); + + var result = given() + .when() + .get(backend + "/{id}", dataRequestId) + .then() + .statusCode(200) + .extract() + .body() + .as(EndpointDataReference.class); + dataReference.set(result); + + return dataReference.get(); + } + + public String pullData(EndpointDataReference edr, Map queryParams) { + var response = given() + .baseUri(edr.getEndpoint()) + .header(edr.getAuthKey(), edr.getAuthCode()) + .queryParams(queryParams) + .when() + .get(); + assertThat(response.statusCode()).isBetween(200, 300); + return response.body().asString(); } @Override - public void afterAll(ExtensionContext context) throws Exception { - super.afterTestExecution(context); + protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { + super.bootExtensions(context, serviceExtensions); + wiper = new DataWiper(context); } private RequestSpecification baseRequest() { diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/TestRuntimeConfiguration.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/TestRuntimeConfiguration.java index 145ae476f..f865d39d9 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/TestRuntimeConfiguration.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/TestRuntimeConfiguration.java @@ -14,39 +14,30 @@ package org.eclipse.tractusx.edc.lifecycle; -import java.util.concurrent.TimeUnit; - import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; -public class TestRuntimeConfiguration { - - - public static final String IDS_PATH = "/api/v1/ids"; - - - public static final int PLATO_CONNECTOR_PORT = getFreePort(); - public static final int PLATO_MANAGEMENT_PORT = getFreePort(); - public static final String PLATO_CONNECTOR_PATH = "/api"; - public static final String PLATO_MANAGEMENT_PATH = "/api/v1/management"; - public static final String CONSUMER_CONNECTOR_MANAGEMENT_URL = "http://localhost:" + PLATO_MANAGEMENT_PORT + PLATO_MANAGEMENT_PATH; - public static final int PLATO_IDS_API_PORT = getFreePort(); - public static final String PLATO_IDS_API = "http://localhost:" + PLATO_IDS_API_PORT; - - public static final int SOKRATES_CONNECTOR_PORT = getFreePort(); - public static final int SOKRATES_MANAGEMENT_PORT = getFreePort(); - public static final String SOKRATES_CONNECTOR_PATH = "/api"; - public static final String SOKRATES_MANAGEMENT_PATH = "/api/v1/management"; - public static final int SOKRATES_IDS_API_PORT = getFreePort(); - public static final String SOKRATES_IDS_API = "http://localhost:" + SOKRATES_IDS_API_PORT; +class TestRuntimeConfiguration { - public static final String PROVIDER_IDS_API_DATA = "http://localhost:" + SOKRATES_IDS_API_PORT + IDS_PATH + "/data"; - public static final String PROVIDER_ASSET_ID = "test-document"; - public static final long CONTRACT_VALIDITY = TimeUnit.HOURS.toSeconds(1); + static final String IDS_PATH = "/api/v1/ids"; + static final int PLATO_CONNECTOR_PORT = getFreePort(); + static final int PLATO_MANAGEMENT_PORT = getFreePort(); + static final String PLATO_CONNECTOR_PATH = "/api"; + static final String PLATO_MANAGEMENT_PATH = "/api/v1/management"; + static final int PLATO_IDS_API_PORT = getFreePort(); + static final String PLATO_IDS_API = "http://localhost:" + PLATO_IDS_API_PORT; - public static final String SOKRATES_ASSET_FILE = "text-document.txt"; + static final int SOKRATES_CONNECTOR_PORT = getFreePort(); + static final int SOKRATES_MANAGEMENT_PORT = getFreePort(); + static final String SOKRATES_CONNECTOR_PATH = "/api"; + static final String SOKRATES_MANAGEMENT_PATH = "/api/v1/management"; + static final int SOKRATES_IDS_API_PORT = getFreePort(); + static final String SOKRATES_IDS_API = "http://localhost:" + SOKRATES_IDS_API_PORT; - public static final String PROVIDER_CONNECTOR_MANAGEMENT_URL = "http://localhost:" + SOKRATES_MANAGEMENT_PORT + SOKRATES_MANAGEMENT_PATH; + static final String SOKRATES_PUBLIC_API_PORT = String.valueOf(getFreePort()); + static final String PLATO_PUBLIC_API_PORT = String.valueOf(getFreePort()); + static final String PLATO_DATAPLANE_CONTROL_PORT = String.valueOf(getFreePort()); + static final String SOKRATES_DATAPLANE_CONTROL_PORT = String.valueOf(getFreePort()); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/provider/ProviderEdcController.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/provider/ProviderEdcController.java new file mode 100644 index 000000000..8ea80e745 --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/provider/ProviderEdcController.java @@ -0,0 +1,2 @@ +package org.eclipse.tractusx.edc.lifecycle.provider;public class ProviderEdcController { +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/provider/ProviderServicesExtension.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/provider/ProviderServicesExtension.java new file mode 100644 index 000000000..526ff6872 --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/provider/ProviderServicesExtension.java @@ -0,0 +1,2 @@ +package org.eclipse.tractusx.edc.lifecycle.provider;public class ProviderServicesExtension { +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/policy/PolicyHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/policy/PolicyHelperFunctions.java index b255aa078..56d92afbe 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/policy/PolicyHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/policy/PolicyHelperFunctions.java @@ -24,6 +24,7 @@ import org.eclipse.edc.policy.model.OrConstraint; import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.policy.model.Policy; +import org.eclipse.edc.policy.model.PolicyType; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -53,4 +54,16 @@ public static PolicyDefinition businessPartnerNumberPolicy(String id, String... .build()) .build()).build()).build(); } + + public static PolicyDefinition noConstraintPolicy(String id) { + return PolicyDefinition.Builder.newInstance() + .id(id) + .policy(Policy.Builder.newInstance() + .permission(Permission.Builder.newInstance() + .action(Action.Builder.newInstance().type("USE").build()) + .build()) + .type(PolicyType.SET) + .build()) + .build(); + } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogTest.java index b7812ae4a..ec8045f5b 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogTest.java @@ -16,14 +16,8 @@ import org.eclipse.edc.api.query.QuerySpecDto; -import org.eclipse.edc.connector.policy.spi.PolicyDefinition; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.policy.model.Action; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.policy.model.PolicyType; import org.eclipse.tractusx.edc.lifecycle.MultiRuntimeTest; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -32,16 +26,11 @@ import static java.util.stream.IntStream.range; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.tractusx.edc.policy.PolicyHelperFunctions.businessPartnerNumberPolicy; +import static org.eclipse.tractusx.edc.policy.PolicyHelperFunctions.noConstraintPolicy; @EndToEndTest public class CatalogTest extends MultiRuntimeTest { - - @BeforeAll - static void setup() { - - } - @Test void requestCatalog_fulfillsPolicy_shouldReturnOffer() { // arrange @@ -133,16 +122,6 @@ void requestCatalog_of1000Assets_shouldContainAll() { } - private PolicyDefinition noConstraintPolicy(String id) { - return PolicyDefinition.Builder.newInstance() - .id(id) - .policy(Policy.Builder.newInstance() - .permission(Permission.Builder.newInstance() - .action(Action.Builder.newInstance().type("USE").build()) - .build()) - .type(PolicyType.SET) - .build()) - .build(); - } + } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/HttpConsumerPullWithProxyTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/HttpConsumerPullWithProxyTest.java new file mode 100644 index 000000000..78f3d2013 --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/HttpConsumerPullWithProxyTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * 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 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.tests; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.eclipse.edc.connector.api.management.transferprocess.model.TransferProcessDto; +import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiationStates; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.HttpDataAddress; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.tractusx.edc.lifecycle.MultiRuntimeTest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.time.Duration; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; + +import static java.time.Duration.ofSeconds; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; +import static org.eclipse.edc.connector.transfer.dataplane.spi.TransferDataPlaneConstants.HTTP_PROXY; +import static org.eclipse.tractusx.edc.policy.PolicyHelperFunctions.noConstraintPolicy; + +@EndToEndTest +public class HttpConsumerPullWithProxyTest extends MultiRuntimeTest { + private static final Duration ASYNC_TIMEOUT = ofSeconds(45); + private static final Duration ASYNC_POLL_INTERVAL = ofSeconds(1); + private final long ONE_WEEK = 60 * 60 * 24 * 7; + MockWebServer server = new MockWebServer(); + + @Test + void transferData_privateBackend() throws IOException, InterruptedException { + var assetId = "api-asset-1"; + var url = server.url("/mock/api"); + server.start(); + + var authCodeHeaderName = "test-authkey"; + var authCode = "test-authcode"; + plato.createAsset(assetId, Map.of(), HttpDataAddress.Builder.newInstance() + .contentType("application/json") + .baseUrl(url.toString()) + .authKey(authCodeHeaderName) + .authCode(authCode) + .build()); + plato.createPolicy(noConstraintPolicy("policy-1")); + plato.createPolicy(noConstraintPolicy("policy-2")); + plato.createContractDefinition(assetId, "def-1", "policy-1", "policy-2", ONE_WEEK); + var negotiationId = sokrates.negotiateContract(plato, assetId); + + // forward declarations of our actual values + var transferProcessId = new AtomicReference(); + var dataRequestId = UUID.randomUUID().toString(); + var contractAgreementId = new AtomicReference(); + var edr = new AtomicReference(); + + + // wait for the successful contract negotiation + await().pollInterval(ASYNC_POLL_INTERVAL) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var negotiation = sokrates.getNegotiation(negotiationId); + assertThat(negotiation.getState()).isEqualTo(ContractNegotiationStates.CONFIRMED.toString()); + contractAgreementId.set(negotiation.getContractAgreementId()); + assertThat(contractAgreementId).isNotNull(); + transferProcessId.set(sokrates.requestTransfer(contractAgreementId.get(), assetId, plato, DataAddress.Builder.newInstance() + .type(HTTP_PROXY) + .build(), dataRequestId)); + assertThat(transferProcessId).isNotNull(); + }); + + // wait until transfer process completes + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var tp = sokrates.getTransferProcess(transferProcessId.get()); + assertThat(tp).isNotNull() + .extracting(TransferProcessDto::getState).isEqualTo(TransferProcessStates.COMPLETED.toString()); + }); + + // wait until EDC is available on the consumer side + server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + edr.set(sokrates.getDataReference(dataRequestId)); + assertThat(edr).isNotNull(); + }); + + // pull data out of provider's backend service: + // Cons-DP -> Prov-DP -> Prov-backend + assertThat(sokrates.pullData(edr.get(), Map.of())).isEqualTo("test response"); + var rq = server.takeRequest(); + assertThat(rq.getHeader(authCodeHeaderName)).isEqualTo(authCode); + assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isEqualTo(contractAgreementId.get()); + assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); + } + + @AfterEach + void teardown() throws IOException { + server.shutdown(); + } +} diff --git a/edc-tests/runtime/build.gradle.kts b/edc-tests/runtime/build.gradle.kts index e4a832666..6f8a370af 100644 --- a/edc-tests/runtime/build.gradle.kts +++ b/edc-tests/runtime/build.gradle.kts @@ -21,12 +21,22 @@ plugins { dependencies { - runtimeOnly(project(":edc-controlplane:edc-controlplane-base")) { + // use basic (all in-mem) control plane + implementation(project(":edc-controlplane:edc-controlplane-base")) { exclude("org.eclipse.edc", "oauth2-core") exclude("org.eclipse.edc", "oauth2-daps") exclude(module = "data-encryption") exclude(module = "control-plane-adapter") } + + // use basic (all in-mem) data plane + runtimeOnly(project(":edc-dataplane:edc-dataplane-base")) { + exclude("org.eclipse.edc", "api-observability") + } + + implementation(edc.core.controlplane) + // for the controller + implementation(libs.jakarta.rsApi) } application { diff --git a/edc-tests/runtime/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerEdrHandlerController.java b/edc-tests/runtime/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerEdrHandlerController.java new file mode 100644 index 000000000..5ca08a922 --- /dev/null +++ b/edc-tests/runtime/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerEdrHandlerController.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * 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 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.lifecycle; + +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Path("/consumer") +public class ConsumerEdrHandlerController { + + private final Monitor monitor; + private Map dataReference; + + public ConsumerEdrHandlerController(Monitor monitor) { + this.monitor = monitor; + dataReference = new HashMap<>(); + } + + @Path("/datareference") + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + public void pushDataReference(EndpointDataReference edr) { + monitor.debug("Received new endpoint data reference with url " + edr.getEndpoint()); + dataReference.put(edr.getId(), edr); + } + + @Path("/datareference/{id}") + @GET + @Produces({ MediaType.APPLICATION_JSON }) + public EndpointDataReference getDataReference(@PathParam("id") String id) { + return Optional.ofNullable(dataReference.get(id)).orElseGet(() -> + { + monitor.warning("No EndpointDataReference found with id " + id); + return null; + }); + } + +} diff --git a/edc-tests/runtime/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerServicesExtension.java b/edc-tests/runtime/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerServicesExtension.java new file mode 100644 index 000000000..f46ef3e4e --- /dev/null +++ b/edc-tests/runtime/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerServicesExtension.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * 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 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.lifecycle; + +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.web.spi.WebService; + +public class ConsumerServicesExtension implements ServiceExtension { + @Inject + private WebService webService; + + @Override + public void initialize(ServiceExtensionContext context) { + webService.registerResource("default", new ConsumerEdrHandlerController(context.getMonitor())); + } +} diff --git a/edc-tests/runtime/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-tests/runtime/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..619665085 --- /dev/null +++ b/edc-tests/runtime/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,15 @@ +# +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# 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 +# +# SPDX-License-Identifier: Apache-2.0 +# +# Contributors: +# Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation +# +# + +org.eclipse.tractusx.edc.lifecycle.ConsumerServicesExtension diff --git a/settings.gradle.kts b/settings.gradle.kts index e0fc39433..22ac0d73a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -52,9 +52,9 @@ dependencyResolutionManagement { versionCatalogs { create("libs") { from("org.eclipse.edc:edc-versions:0.0.1-20230220-SNAPSHOT") - library("testcontainers-junit", "org.testcontainers","junit-jupiter").version("1.17.6") - library("apache-sshd-core", "org.apache.sshd","sshd-core").version("2.9.2") - library("apache-sshd-sftp", "org.apache.sshd","sshd-sftp").version("2.9.2") + library("testcontainers-junit", "org.testcontainers", "junit-jupiter").version("1.17.6") + library("apache-sshd-core", "org.apache.sshd", "sshd-core").version("2.9.2") + library("apache-sshd-sftp", "org.apache.sshd", "sshd-sftp").version("2.9.2") } // create version catalog for all EDC modules create("edc") { @@ -86,6 +86,9 @@ dependencyResolutionManagement { library("api-management", "org.eclipse.edc", "management-api").versionRef("edc") library("api-catalog", "org.eclipse.edc", "catalog-api").versionRef("edc") library("api-observability", "org.eclipse.edc", "api-observability").versionRef("edc") + library("api-contractnegotiation", "org.eclipse.edc", "contract-negotiation-api").versionRef("edc") + library("api-dataplane", "org.eclipse.edc", "data-plane-api").versionRef("edc") + library("api-transferprocess", "org.eclipse.edc", "transfer-process-api").versionRef("edc") library("ext-http", "org.eclipse.edc", "http").versionRef("edc") library("spi-ids", "org.eclipse.edc", "ids-spi").versionRef("edc") library("ids", "org.eclipse.edc", "ids").versionRef("edc") @@ -140,6 +143,8 @@ dependencyResolutionManagement { "transfer-pull-http-dynamic-receiver" ).versionRef("edc") + library("transfer.receiver", "org.eclipse.edc", "transfer-pull-http-receiver").versionRef("edc") + bundle( "connector", listOf("boot", "core-connector", "core-jersey", "core-controlplane", "api-observability") From 8ddae2dac2007b955de8fa1dc6eb1ac7eac8e539 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Mon, 3 Apr 2023 11:26:20 +0200 Subject: [PATCH 2/2] removed obsolete HTTP test --- .../edc/tests/HttpProxyTransferSteps.java | 16 ++++++---------- .../features/HttpProxyDataTransfer.feature | 18 ------------------ 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/HttpProxyTransferSteps.java b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/HttpProxyTransferSteps.java index 6f34f5eb0..24f68e3a1 100644 --- a/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/HttpProxyTransferSteps.java +++ b/edc-tests/cucumber/src/test/java/org/eclipse/tractusx/edc/tests/HttpProxyTransferSteps.java @@ -6,11 +6,9 @@ import io.cucumber.java.en.When; import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.edc.tests.data.Asset; -import org.eclipse.tractusx.edc.tests.data.ContractNegotiation; import org.eclipse.tractusx.edc.tests.data.DataAddress; import org.eclipse.tractusx.edc.tests.data.HttpProxySinkDataAddress; import org.eclipse.tractusx.edc.tests.data.HttpProxySourceDataAddress; -import org.eclipse.tractusx.edc.tests.data.Transfer; import org.junit.jupiter.api.Assertions; import java.io.IOException; @@ -61,19 +59,17 @@ public void hasAssets(Connector connector, DataTable table) throws Exception { @When("'{connector}' initiates HttpProxy transfer from '{connector}'") public void sokratesInitiateHttpProxyTransferProcessFromPlato( Connector consumer, Connector provider, DataTable dataTable) throws IOException { - final DataManagementAPI api = consumer.getDataManagementAPI(); - final String receiverUrl = provider.getEnvironment().getIdsUrl() + "/data"; + var api = consumer.getDataManagementAPI(); + var receiverUrl = provider.getEnvironment().getIdsUrl() + "/data"; - final List negotiation = api.getNegotiations(); - final String agreementId = negotiation.get(0).getAgreementId(); - final DataAddress dataAddress = new HttpProxySinkDataAddress(); + var negotiation = api.getNegotiations(); + var agreementId = negotiation.get(0).getAgreementId(); + var dataAddress = new HttpProxySinkDataAddress(); for (var map : dataTable.asMaps()) { final String assetId = map.get(ASSET_ID); final String receiverHttpEndpoint = map.get(RECEIVER_HTTP_ENDPOINT); - final Transfer transfer = - api.initiateTransferProcess( - receiverUrl, agreementId, assetId, dataAddress, receiverHttpEndpoint); + var transfer = api.initiateTransferProcess(receiverUrl, agreementId, assetId, dataAddress, receiverHttpEndpoint); transfer.waitUntilComplete(api); } diff --git a/edc-tests/cucumber/src/test/resources/org/eclipse/tractusx/edc/tests/features/HttpProxyDataTransfer.feature b/edc-tests/cucumber/src/test/resources/org/eclipse/tractusx/edc/tests/features/HttpProxyDataTransfer.feature index d318ad745..b04970ec7 100644 --- a/edc-tests/cucumber/src/test/resources/org/eclipse/tractusx/edc/tests/features/HttpProxyDataTransfer.feature +++ b/edc-tests/cucumber/src/test/resources/org/eclipse/tractusx/edc/tests/features/HttpProxyDataTransfer.feature @@ -24,24 +24,6 @@ Feature: HttpProxy Data Transfer Given 'Plato' has an empty database Given 'Sokrates' has an empty database - Scenario: Connector transfers data via HttpProxy - Given 'Plato' has a http proxy assets - | id | description | baseUrl | - | asset-1 | http proxy transfer asset | http://localhost:8081/api/check/liveness | - And 'Plato' has the following policies - | id | action | - | policy-1 | USE | - And 'Plato' has the following contract definitions - | id | access policy | contract policy | asset | - | contract-definition-1 | policy-1 | policy-1 | asset-1 | - When 'Sokrates' negotiates the contract successfully with 'Plato' - | contract offer id | asset id | policy id | - | contract-definition-1 | asset-1 | policy-1 | - And 'Sokrates' initiates HttpProxy transfer from 'Plato' - | asset id | receiverHttpEndpoint | - | asset-1 | http://backend:8080 | - Then the backend application of 'Sokrates' has received data - Scenario: Connector transfers data via HttpProxy, data on provider side requires oauth2 authentication Given 'Plato' has a http proxy assets | id | description | baseUrl | oauth2 token url | oauth2 client id | oauth2 client secret | oauth2 scope |